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.0
make PLAT=qemu DEBUG=1 -j9
U-BOOT
git clone https://github.com/u-boot/u-boot.git -b v2022.07
make qemu_arm64_defconfig
make -j9
Prepare image
ln -sf arm-trusted-firmware/build/qemu/debug/bl1.bin bl1.bin
ln -sf arm-trusted-firmware/build/qemu/debug/bl2.bin bl2.bin
ln -sf arm-trusted-firmware/build/qemu/debug/bl31.bin bl31.bin
ln -sf u-boot/u-boot.bin bl33.bin
Boot 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 0x7ff12000
add symbol table from file "u-boot/u-boot" at
.text_addr = 0x7ff12000
(y or n) y
Reading 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:140
Backtrace 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 file
shell echo set \$text_address=$(readelf -WS $arg0 | grep .text | awk '{ print "0x"$5 }') >/tmp/temp_gdb_text_address.txt
# Source .text address
source /tmp/temp_gdb_text_address.txt
# Clean tempfile
shell rm -f /tmp/temp_gdb_text_address.txt
# Load symbol table
add-symbol-file $arg0 $text_address
end
set print pretty
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf
add-symbol-file ../u-boot/u-boot 0x60000000
target remote:1234
tb print_entry_point_info
c
tb print_entry_point_info
c
b _start
c
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 file
shell echo set \$text_address=$(readelf -WS $arg0 | grep .text | awk '{ print "0x"$5 }') >/tmp/temp_gdb_text_address.txt
# Source .text address
source /tmp/temp_gdb_text_address.txt
# Clean tempfile
shell rm -f /tmp/temp_gdb_text_address.txt
# Load symbol table
add-symbol-file $arg0 $text_address
end
set print pretty
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf
add-symbol-file-auto ../arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf
add-symbol-file ../u-boot/u-boot 0x60000000
target remote:1234
tb print_entry_point_info
c
tb print_entry_point_info
c
b _start
c
tb relocate_64.S:95
c
add-symbol-file ../u-boot/u-boot gd->relocaddr