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:

  1. setup a break point to stop after relocate copy. and before relocate code to return.
  2. add uboot symbol file at relocaddr.
  3. 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
Contact me via :)
虚怀乃若谷,水深则流缓。