Debug Uboot with gdb
Table of Contents
Boot flow
We have qemu virt arm64 running ATF code and Uboot.
Boot flow as
BL1 → BL2 → BL31 → BL33 (Uboot)
Compile Test images
ATF
git clone https://github.com/ARM-software/arm-trusted-firmware.git -b v2.7.0make PLAT=qemu DEBUG=1 -j9U-BOOT
git clone https://github.com/u-boot/u-boot.git -b v2022.07make qemu_arm64_defconfigmake -j9Prepare image
ln -sf arm-trusted-firmware/build/qemu/debug/bl1.bin bl1.binln -sf arm-trusted-firmware/build/qemu/debug/bl2.bin bl2.binln -sf arm-trusted-firmware/build/qemu/debug/bl31.bin bl31.binln -sf u-boot/u-boot.bin bl33.binBoot image
~/work/src/qemu/build/aarch64-softmmu/qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 -smp 2 -m 1024 -bios bl1.bin -d unimp -semihosting-config enable,target=native
U-Boot Debug
Debug a command
If you can boot to Uboot console, it's more easy to debug
you can get the relocated address from x18 (in AARCH64), then add symbol to that address
(gdb) p/x ((gd_t *)$x18)->relocaddr$8 = 0x7ff12000(gdb) add-symbol-file u-boot/u-boot 0x7ff12000add symbol table from file "u-boot/u-boot" at.text_addr = 0x7ff12000(y or n) yReading symbols from u-boot/u-boot...done.(gdb) bt#0 pl01x_serial_pending (dev=<optimized out>, input=true) at drivers/serial/serial_pl01x.c:327#1 0x000000007ff3707c in console_tstc (file=0) at common/console.c:492#2 fgetc (file=0) at common/console.c:492#3 0x000000007ff36650 in cread_line (timeout=0, len=<synthetic pointer>, buf=0x7ffe4590 "", prompt=0x7ffb2e59 "=> ") at common/cli_readline.c:277#4 cli_readline_into_buffer (prompt=0x7ffb2e59 "=> ", buffer=0x7ffe4590 "", timeout=0) at common/cli_readline.c:554#5 0x000000007ff2f460 in uboot_cli_readline (i=0x7eecfc70) at common/cli_hush.c:1028#6 get_user_input (i=0x7eecfc70) at common/cli_hush.c:1028#7 file_get (i=<optimized out>) at common/cli_hush.c:1107#8 file_get (i=0x7eecfc70) at common/cli_hush.c:1090#9 0x000000007ff305fc in parse_stream (end_trigger=<optimized out>, input=<optimized out>, ctx=<optimized out>, dest=<optimized out>) at common/cli_hush.c:3189#10 parse_stream_outer (inp=inp@entry=0x7eecfc70, flag=flag@entry=2) at common/cli_hush.c:3189#11 0x000000007ff30b84 in parse_file_outer () at common/cli_hush.c:3289#12 0x000000007ff39350 in cli_loop () at common/cli.c:229#13 0x000000007ff2ec4c in main_loop () at common/main.c:69#14 0x000000007ff31238 in run_main_loop () at common/board_r.c:590#15 0x000000007ff3151c in initcall_run_list (init_sequence=0x7ffc30c0) at include/initcall.h:46#16 board_init_r (new_gd=<optimized out>, dest_addr=<optimized out>) at common/board_r.c:824#17 0x000000007ff14570 in ?? () at arch/arm/lib/crt0_64.S:140Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Before relocate
Before relocate, U-boot running with linked address. (Address you see with System.map)
In this case, you need to set a breakpoint at _start(u-boot entry), and then, you can debug it as you like.
fellowing gdb script used for gdb to stop program at _start uboot entry.
define add-symbol-file-auto# Parse .text address to temp fileshell echo set \$text_address=$(readelf -WS $arg0 | grep .text | awk '{ print "0x"$5 }') >/tmp/temp_gdb_text_address.txt# Source .text addresssource /tmp/temp_gdb_text_address.txt# Clean tempfileshell rm -f /tmp/temp_gdb_text_address.txt# Load symbol tableadd-symbol-file $arg0 $text_addressendset print prettyadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl1/bl1.elfadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl2/bl2.elfadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl31/bl31.elfadd-symbol-file ../u-boot/u-boot 0x60000000target remote:1234tb print_entry_point_infoctb print_entry_point_infocb _startc
After relocate
After relocate, Uboot will running on top of DRAM, (running address is different from linked address.)
In this case:
- setup a break point to stop after relocate copy. and before relocate code to return.
- add uboot symbol file at relocaddr.
- you can debug it now.
The following script can help you automate this step
define add-symbol-file-auto# Parse .text address to temp fileshell echo set \$text_address=$(readelf -WS $arg0 | grep .text | awk '{ print "0x"$5 }') >/tmp/temp_gdb_text_address.txt# Source .text addresssource /tmp/temp_gdb_text_address.txt# Clean tempfileshell rm -f /tmp/temp_gdb_text_address.txt# Load symbol tableadd-symbol-file $arg0 $text_addressendset print prettyadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl1/bl1.elfadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl2/bl2.elfadd-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl31/bl31.elfadd-symbol-file ../u-boot/u-boot 0x60000000target remote:1234tb print_entry_point_infoctb print_entry_point_infocb _startctb relocate_64.S:95cadd-symbol-file ../u-boot/u-boot gd->relocaddr