Last edited 3 weeks ago

U-Boot - How to debug

Template:ArticleMainWriter

Template:ArticleApprovedVersion


1. Debug with console[edit | edit source]

Trace and error are available on the console defined in the chosen node of the device tree by the stdout-path field:

 chosen {
 	stdout-path = "serial3:115200n8";
 };

By default, the macros used by U-Boot (debug(), pr_debug()...) do not print any trace; to activate the debug traces on a specific file, you need to enable the DEBUG compilation flag and change the LOGLEVEL for the file:

  • define DEBUG before any include in the <file>.c file
 #define DEBUG
 #undef CONFIG_LOGLEVEL
 #define CONFIG_LOGLEVEL 8
  • with a Makefile
 CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8

If U-Boot fails before the console configuration (in the first stage of U-Boot execution), trace is not available.

In this case, you need to:

  • debug with GDB (see the next chapter)

or,

  • activate the debug UART feature:
    • activate CONFIG_DEBUG_UART with configure
    • board_debug_uart_init(): this is a weak function that configures the required resources (pad, clock) before initialization by the U-Boot driver.
      This function needs to be adapted for your case.

2. Debug with GDB on a Flashed device[edit | edit source]

You need to:

  1. connect GDB to the target
  2. load the symbols of the binary to be debugged (see #SPL symbol load and #U-Boot symbol load).
    The required files are available in the build directory.
  3. reset with attach the target with the gdb "monitor reset halt" command
  4. start execution with the "continue" command

2.1. SPL symbol load[edit | edit source]

To debug SPL, the GDB script just consists of loading the SPL symbols:

 (gdb) symbol-file spl/u-boot-spl

2.2. U-Boot symbol load[edit | edit source]

With U-Boot relocation, symbols are more difficult to load.

See https://www.denx.de/wiki/DULG/DebuggingUBoot

Here is an example of a GDB script to debug U-Boot:

 (gdb) thbreak *0xC0100000
 (gdb) commands
 > symbol-file u-boot
 > thbreak relocate_code
 > commands
   > print "RELOCATE U-Boot..."
   > set $offset = ((gd_t *)$r9)->relocaddr
   > print $offset
   > symbol-file
   > add-symbol-file u-boot $offset
   > thbreak boot_jump_linux
   > continue
   > end
 > continue
 > end

The U-Boot code is relocated at the end of the DDR, at gd->relocaddr.

The script uses a temporary hardware breakpoint (thbreak) to automatically load the U-Boot symbol with

  • 'u-boot' = the elf file for U-Boot
  • CONFIG_SYS_TEXT_BASE = 0xC0100000 (loading symbol only when code is executed)

3. Load code and debug with GDB[edit | edit source]

To load and debug on the target, you need to:

  1. reset and attach to the target as soon as possible: with the GDB "monitor reset halt" command, see GDB for details
  2. load the code and device-tree by using GDB (with the load command, see the following examples)
  3. execute the binary (the PC is automatically updated, execute the code with the GDB "continue" command)

Depending on the device tree location defined with one of the CONFIG_OF_* configuration flags, the scripts to load the SPL code are:

  • CONFIG_OF_SEPARATE = dtb appended at the end of the code, not present in the elf file
 (gdb) file spl/u-boot-spl
 (gdb) load
 (gdb) set $dtb =  __bss_end
 (gdb) restore spl/dt.dtb binary $dtb
  • CONFIG_OF_EMBED = dtb embedded in the elf file
 (gdb) file spl/u-boot-spl
 (gdb) load