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