Alexander Dahl | e276400 | 2024-06-26 12:47:18 +0200 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0+ |
| 2 | .. Copyright (c) 2024 Alexander Dahl |
| 3 | |
| 4 | Debugging U-Boot with GDB |
| 5 | ========================= |
| 6 | |
| 7 | Using a JTAG adapter it is possible to debug a running U-Boot with GDB. |
| 8 | A common way is to connect a debug adapter to the JTAG connector of your |
| 9 | board, run a GDB server, connect GDB to the GDB server, and use GDB as usual. |
| 10 | |
| 11 | Similarly QEMU can provide a GDB server. |
| 12 | |
| 13 | Preparing build |
| 14 | --------------- |
| 15 | |
| 16 | Building U-Boot with with reduced optimization (-Og) and without link time |
| 17 | optimization is recommended for easier debugging:: |
| 18 | |
| 19 | CONFIG_CC_OPTIMIZE_FOR_DEBUG=y |
| 20 | CONFIG_LTO=n |
| 21 | |
| 22 | Otherwise build, install, and run U-Boot as usual. |
| 23 | |
| 24 | Using OpenOCD as GDB server |
| 25 | --------------------------- |
| 26 | |
| 27 | `OpenOCD <https://openocd.org/>`_ is an open source tool supporting hardware |
| 28 | debug probes, and providing a GDB server. It is readily available in major Linux |
| 29 | distributions or you can build it from source. |
| 30 | |
| 31 | Here is example of starting OpenOCD on Debian using a J-Link adapter and a |
| 32 | board with an AT91 SAMA5D2 SoC: |
| 33 | |
| 34 | .. code-block:: console |
| 35 | |
| 36 | $ openocd -f interface/jlink.cfg -f target/at91sama5d2.cfg -c 'adapter speed 4000' |
| 37 | Open On-Chip Debugger 0.12.0 |
| 38 | Licensed under GNU GPL v2 |
| 39 | For bug reports, read |
| 40 | http://openocd.org/doc/doxygen/bugs.html |
| 41 | Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'. |
| 42 | adapter speed: 4000 kHz |
| 43 | |
| 44 | Info : Listening on port 6666 for tcl connections |
| 45 | Info : Listening on port 4444 for telnet connections |
| 46 | Info : J-Link V10 compiled Jan 30 2023 11:28:07 |
| 47 | Info : Hardware version: 10.10 |
| 48 | Info : VTarget = 3.244 V |
| 49 | Info : clock speed 4000 kHz |
| 50 | Info : JTAG tap: at91sama5d2.cpu tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5) |
| 51 | Info : at91sama5d2.cpu_a5.0: hardware has 3 breakpoints, 2 watchpoints |
| 52 | Info : at91sama5d2.cpu_a5.0: MPIDR level2 0, cluster 0, core 0, mono core, no SMT |
| 53 | Info : starting gdb server for at91sama5d2.cpu_a5.0 on 3333 |
| 54 | Info : Listening on port 3333 for gdb connections |
| 55 | |
| 56 | Notice that OpenOCD is listening on port 3333 for GDB connections. |
| 57 | |
| 58 | Using QEMU as GDB server |
| 59 | ------------------------ |
| 60 | |
| 61 | When running U-Boot on QEMU you can used the '-gdb' parameter to provide a |
| 62 | GDB server: |
| 63 | |
| 64 | qemu-system-riscv64 -M virt -nographic -gdb tcp::3333 -kernel u-boot |
| 65 | |
| 66 | Running a GDB session |
| 67 | ---------------------- |
| 68 | |
| 69 | You need a GDB suited for your target. This can be the GDB coming with your |
| 70 | toolchain or *gdb-multiarch* available in your Linux distribution. |
| 71 | |
| 72 | .. prompt:: bash $ |
| 73 | |
| 74 | gdb-multiarch u-boot |
| 75 | |
| 76 | In the above command-line *u-boot* is the U-boot binary in your build |
| 77 | directory. You may need to adjust the path when calling GDB. |
| 78 | |
| 79 | Connect to the GDB server like this: |
| 80 | |
| 81 | .. code-block:: console |
| 82 | |
| 83 | (gdb) target extended-remote :3333 |
| 84 | Remote debugging using :3333 |
| 85 | 0x27fa9ac6 in ?? () |
| 86 | (gdb) |
| 87 | |
| 88 | This is fine for debugging before U-Boot relocates itself. |
| 89 | |
| 90 | For debugging U-Boot after relocation you need to indicate the relocation |
| 91 | address to GDB. You can retrieve the relocation address from the U-Boot shell |
| 92 | with the command *bdinfo*: |
| 93 | |
| 94 | .. code-block:: console |
| 95 | |
| 96 | U-Boot> bdinfo |
| 97 | boot_params = 0x20000100 |
| 98 | DRAM bank = 0x00000000 |
| 99 | -> start = 0x20000000 |
| 100 | -> size = 0x08000000 |
| 101 | flashstart = 0x00000000 |
| 102 | flashsize = 0x00000000 |
| 103 | flashoffset = 0x00000000 |
| 104 | baudrate = 115200 bps |
| 105 | relocaddr = 0x27f7a000 |
| 106 | reloc off = 0x0607a000 |
| 107 | Build = 32-bit |
| 108 | current eth = ethernet@f8008000 |
| 109 | ethaddr = 00:50:c2:31:58:d4 |
| 110 | IP addr = <NULL> |
| 111 | fdt_blob = 0x27b36060 |
| 112 | new_fdt = 0x27b36060 |
| 113 | fdt_size = 0x00003e40 |
| 114 | lmb_dump_all: |
| 115 | memory.cnt = 0x1 / max = 0x10 |
| 116 | memory[0] [0x20000000-0x27ffffff], 0x08000000 bytes flags: 0 |
| 117 | reserved.cnt = 0x1 / max = 0x10 |
| 118 | reserved[0] [0x27b31d00-0x27ffffff], 0x004ce300 bytes flags: 0 |
| 119 | devicetree = separate |
| 120 | arch_number = 0x00000000 |
| 121 | TLB addr = 0x27ff0000 |
| 122 | irq_sp = 0x27b36050 |
| 123 | sp start = 0x27b36040 |
| 124 | Early malloc usage: cd8 / 2000 |
| 125 | |
| 126 | Look out for the line starting with *relocaddr* which has the address |
| 127 | you need, ``0x27f7a000`` in this case. |
| 128 | |
| 129 | On most architectures (not sandbox, x86, Xtensa) the global data pointer is |
| 130 | stored in a fixed register: |
| 131 | |
| 132 | ============ ======== |
| 133 | Architecture Register |
| 134 | ============ ======== |
| 135 | arc r25 |
| 136 | arm r9 |
| 137 | arm64 x18 |
| 138 | m68k d7 |
| 139 | microblaze r31 |
| 140 | mips k0 |
| 141 | nios2 gp |
| 142 | powerpc r2 |
| 143 | riscv gp |
| 144 | sh r13 |
| 145 | ============ ======== |
| 146 | |
| 147 | On these architecture the relocation address cat be determined by |
| 148 | dereferencing the global data pointer stored in register, *r9* in the example: |
| 149 | |
| 150 | .. code-block:: console |
| 151 | |
| 152 | (gdb) p/x (*(struct global_data*)$r9)->relocaddr |
| 153 | $1 = 0x27f7a000 |
| 154 | |
| 155 | In the GDB shell discard the previously loaded symbol file and add it once |
| 156 | again with the relocation address like this: |
| 157 | |
| 158 | .. code-block:: console |
| 159 | |
| 160 | (gdb) symbol-file |
| 161 | Discard symbol table from `/home/adahl/build/u-boot/v2024.04.x/u-boot'? (y or n) y |
| 162 | No symbol file now. |
| 163 | (gdb) add-symbol-file u-boot 0x27f7a000 |
| 164 | add symbol table from file "u-boot" at |
| 165 | .text_addr = 0x27f7a000 |
| 166 | (y or n) y |
| 167 | Reading symbols from u-boot... |
| 168 | (gdb) |
| 169 | |
| 170 | You can now use GDB as usual, setting breakpoints, printing backtraces, |
| 171 | inspecting variables, stepping through the code, etc. |