WebFreak001 / code-debug

Native debugging for VSCode
The Unlicense
401 stars 114 forks source link

UI out of sync with gdb status #399

Closed aleeraser closed 7 months ago

aleeraser commented 1 year ago

gdb-version: 11.2

I'm trying to debug the bootloader code of a device. The bootloader is U-Boot.

The gdb server is provided via OpenOCD/JTAG interface to the device. The server is started manually, separately. I have a suitable gdb binary targeted for this particular device (arm based). I have Visual Studio Code placed in U-Boot source directory. After I compile U-Boot with make, the binary is in the top-level directory.

Using gdb via command line, I'm able to do everything I need: load symbols and set breakpoints. I can see from the serial console attached to the device that the bootloader stops at the right moment if I set a breakpoint. If I hit next, the execution goes forward of one function/line as expected, backtrace is using the correct symbols, and so on. Therefore, I assume the .elf file is correct, gdb configuration is correct, and the setup is working.

Instead, I wasn't able to make this extension work so far.

This is my configuration:

{
    "name": "U-Boot (attach to server)",
    "type": "gdb",
    "request": "attach",
    "target": "localhost:3334",
    "executable": "${workspaceRoot}/u-boot",
    "remote": true,
    "stopAtConnect": true,
    "cwd": "${workspaceRoot}",
    "gdbpath": "[CUSTOM_PATH]/arm-ccp-linux-gnueabi-gdb",
    "valuesFormatting": "parseText",
    "autorun": [
        "monitor bp [ADDRESS] 0 hw",
        "monitor reset halt",
        "load",
    ]
}

The two monitor ... commands are needed to restart the device and stop before U-Boot starts. Then, load loads the U-Boot bin to the device.

With this configuration, I can see that the device correctly restarts, stops at the right moment and U-Boot is loaded. If I use the UI to set a breakpoint in the code, I can see the device correctly stops at that point:

The issue is that the UI is completely unaware that the breakpoint was hit. The relevant line is not highlighted, and I can see that the execution wasn't stopped.

I hope I provided enough details.

GitMensch commented 1 year ago

It looks like the extension is not aware that that the inferior stopped. It may is reported different than expected in this case. Can you please do a run with "showDevDebugOutput": true, "printCalls": true,?

aleeraser commented 1 year ago

Below the full log.

Click to expand ``` log 1-gdb-set target-async on 2-list-features 3-environment-directory "/home/alessandro/work/u-boot-2015.04" 4-target-select remote localhost:3334 5-interpreter-exec console "monitor bp 0x80100000 0 hw" 6-interpreter-exec console "monitor reset halt" 7-interpreter-exec console "load" GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"notify","asyncClass":"thread-group-added","output":[["id","i1"]]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Reading symbols from /home/alessandro/work/u-boot-2015.04/u-boot...\n"}]} Reading symbols from /home/alessandro/work/u-boot-2015.04/u-boot... GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Warning: 'set target-async', an alias for the command 'set mi-async', is deprecated.\n"}]} Warning: 'set target-async', an alias for the command 'set mi-async', is deprecated. GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Use 'set mi-async'.\n\n"}]} Use 'set mi-async'. GDB -> App: {"token":1,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}} GDB -> App: {"token":2,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["features",["frozen-varobjs","pending-breakpoints","thread-info","data-read-memory-bytes","breakpoint-notifications","ada-task-info","language-option","info-gdb-mi-command","undefined-command-error-code","exec-run-start-option","data-disassemble-a-option","python"]]]}} GDB -> App: {"token":3,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["source-path","/home/alessandro/work/u-boot-2015.04:$cdir:$cwd"]]}} GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"notify","asyncClass":"thread-group-started","output":[["id","i1"],["pid","42000"]]}]} GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"notify","asyncClass":"thread-created","output":[["id","1"],["group-id","i1"]]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"warning: remote target does not support file transfer, attempting to access files from local filesystem.\n"}]} warning: remote target does not support file transfer, attempting to access files from local filesystem. GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"warning: Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code."}]} warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"log","content":"\n"}]} 8-thread-info GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"board_late_init () at board/siemens/draco/board.c:307\n"}]} board_late_init () at board/siemens/draco/board.c:307 GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"307\t\tif (factory_dat.asn[0] != 0) {\n"}]} 307 if (factory_dat.asn[0] != 0) { GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"exec","asyncClass":"stopped","output":[["frame",[["addr","0x87f54800"],["func","board_late_init"],["args",[]],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","307"],["arch","armv7"]]],["thread-id","1"],["stopped-threads","all"]]}]} GDB -> App: {"token":4,"outOfBandRecord":[],"resultRecords":{"resultClass":"connected","results":[]}} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"breakpoint set at 0x80100000\n"}]} breakpoint set at 0x80100000 GDB -> App: {"token":5,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}} 9-thread-info GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"JTAG tap: am335x.jrc tap/device found: 0x2b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x2)\n"}]} JTAG tap: am335x.jrc tap/device found: 0x2b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x2) GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"JTAG tap: am335x.tap enabled\n"}]} JTAG tap: am335x.tap enabled GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"Debug regions are unpowered, an unexpected reset might have happened\n"}]} Debug regions are unpowered, an unexpected reset might have happened GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"JTAG-DP STICKY ERROR\n"}]} JTAG-DP STICKY ERROR GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"Could not initialize the APB-AP\n"}]} Could not initialize the APB-AP GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"am335x.cpu: ran after reset and before halt ...\n"}]} am335x.cpu: ran after reset and before halt ... GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"am335x.cpu: hardware has 6 breakpoints, 2 watchpoints\n"}]} am335x.cpu: hardware has 6 breakpoints, 2 watchpoints GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"target halted in ARM state due to breakpoint, current mode: Supervisor\n"}]} target halted in ARM state due to breakpoint, current mode: Supervisor GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"cpsr: 0x60000193 pc: 0x87f54800\n"}]} cpsr: 0x60000193 pc: 0x87f54800 GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"target","content":"MMU: disabled, D-Cache: disabled, I-Cache: enabled\n"}]} MMU: disabled, D-Cache: disabled, I-Cache: enabled GDB -> App: {"token":6,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .text, size 0x66e38 lma 0x87f53000\n"}]} Loading section .text, size 0x66e38 lma 0x87f53000 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} 10-break-insert -f "/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c:303" GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .rodata, size 0xece6 lma 0x87fb9e38\n"}]} Loading section .rodata, size 0xece6 lma 0x87fb9e38 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .hash, size 0x18 lma 0x87fc8b20\n"}]} Loading section .hash, size 0x18 lma 0x87fc8b20 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .data, size 0x6ca8 lma 0x87fc8b38\n"}]} Loading section .data, size 0x6ca8 lma 0x87fc8b38 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .got, size 0x178 lma 0x87fcf7e0\n"}]} Loading section .got, size 0x178 lma 0x87fcf7e0 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .got.plt, size 0xc lma 0x87fcf958\n"}]} Loading section .got.plt, size 0xc lma 0x87fcf958 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .u_boot_list, size 0x880 lma 0x87fcf964\n"}]} Loading section .u_boot_list, size 0x880 lma 0x87fcf964 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .rel.dyn, size 0x2c30 lma 0x87fd01e4\n"}]} Loading section .rel.dyn, size 0x2c30 lma 0x87fd01e4 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .dynsym, size 0x30 lma 0x87fd2e14\n"}]} Loading section .dynsym, size 0x30 lma 0x87fd2e14 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .dynstr, size 0x1 lma 0x87fd2e44\n"}]} Loading section .dynstr, size 0x1 lma 0x87fd2e44 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .dynamic, size 0x90 lma 0x87fd2e48\n"}]} Loading section .dynamic, size 0x90 lma 0x87fd2e48 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .interp, size 0x11 lma 0x87fd2ed8\n"}]} Loading section .interp, size 0x11 lma 0x87fd2ed8 GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Loading section .gnu.hash, size 0x18 lma 0x87fd2eec\n"}]} Loading section .gnu.hash, size 0x18 lma 0x87fd2eec GDB -> App: {"token":7,"outOfBandRecord":[{"isStream":false,"type":"status","asyncClass":"download","output":[]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Start address 0x87f53000, load size 524028\n"}]} Start address 0x87f53000, load size 524028 GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Transfer rate: 55 KB/sec, 12476 bytes/write.\n"}]} Transfer rate: 55 KB/sec, 12476 bytes/write. GDB -> App: {"token":7,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}} GDB -> App: {"token":8,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["args",[]],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}} GDB -> App: {"token":9,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["args",[]],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}} GDB -> App: {"token":10,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["bkpt",[["number","1"],["type","breakpoint"],["disp","keep"],["enabled","y"],["addr","0x87f547f4"],["func","board_late_init"],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["thread-groups",["i1"]],["times","0"],["original-location","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c:303"]]]]}} 11-stack-info-depth --thread 1 GDB -> App: {"token":11,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["depth","1"]]}} 12-stack-list-frames --thread 1 0 0 GDB -> App: {"token":12,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["stack",[["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]]]]]}} 13-thread-info GDB -> App: {"token":13,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["args",[]],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}} 14-thread-info GDB -> App: {"token":14,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["args",[]],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}} 15-stack-info-depth --thread 1 GDB -> App: {"token":15,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["depth","1"]]}} 16-stack-list-frames --thread 1 0 0 GDB -> App: {"token":16,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["stack",[["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]]]]]}} 17-stack-info-depth --thread 1 GDB -> App: {"token":17,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["depth","1"]]}} 18-stack-list-frames --thread 1 0 0 GDB -> App: {"token":18,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["stack",[["frame",[["level","0"],["addr","0x87f53000"],["func","_start"],["file","arch/arm/lib/vectors.S"],["fullname","/home/alessandro/work/u-boot-2015.04/arch/arm/lib/vectors.S"],["line","54"],["arch","armv7"]]]]]]}} 19-stack-list-variables --thread 1 --frame 0 --simple-values GDB -> App: {"token":19,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["variables",[]]]}} 20-exec-continue GDB -> App: {"token":20,"outOfBandRecord":[],"resultRecords":{"resultClass":"running","results":[]}} GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"exec","asyncClass":"running","output":[["thread-id","all"]]}]} GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"notify","asyncClass":"breakpoint-modified","output":[["bkpt",[["number","1"],["type","breakpoint"],["disp","keep"],["enabled","y"],["addr","0x87f547f4"],["func","board_late_init"],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["thread-groups",["i1"]],["times","1"],["original-location","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c:303"]]]]}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"\n"}]} GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"Breakpoint 1, board_late_init () at board/siemens/draco/board.c:303\n"}]} Breakpoint 1, board_late_init () at board/siemens/draco/board.c:303 GDB -> App: {"outOfBandRecord":[{"isStream":true,"type":"console","content":"303\t\tprintf(\"Machine: \" PRODUCT_MODEL_NAME \"\\n\");\n"}]} 303 printf("Machine: " PRODUCT_MODEL_NAME "\n"); GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"exec","asyncClass":"stopped","output":[["reason","breakpoint-hit"],["disp","keep"],["bkptno","1"],["frame",[["addr","0x87f547f4"],["func","board_late_init"],["args",[]],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["arch","armv7"]]],["thread-id","1"],["stopped-threads","all"]]}]} 21-thread-info GDB -> App: {"token":21,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f547f4"],["func","board_late_init"],["args",[]],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}} 22-stack-info-depth --thread 1 23-stack-info-depth --thread 1 ```
GitMensch commented 1 year ago

Thanks, that looks good in general:

21-thread-info
GDB -> App: {"token":21,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f547f4"],["func","board_late_init"],["args",[]],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}}
22-stack-info-depth --thread 1
23-stack-info-depth --thread 1

So the issue is that there is no response from the remote for stack-info-depth --thread 1, which this extension waits for before sending ui updates:

https://github.com/WebFreak001/code-debug/blob/26d7d9fe64f222618c3302c323a4da2c426b71a4/src/backend/mi2/mi2.ts#L699

In theory a timeout can be added (suggestion of ChatGPT for an implementation) but the most important question is: does the remote answer other requests? What happens if you ask in the debug console for backtrace? If that works: what happens if you ask for interpreter-exec mi2 -stack-info-depth?

Note: that mi2 command was already included in at least GDB 5.1.1 (actually it is tested in GDB 4.18.2 already).

aleeraser commented 1 year ago

Unfortunately I think your guess is right.

...
GDB -> App: {"token":21,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[["threads",[[["id","1"],["target-id","Remote target"],["frame",[["level","0"],["addr","0x87f547f4"],["func","board_late_init"],["args",[]],["file","board/siemens/draco/board.c"],["fullname","/home/alessandro/work/u-boot-2015.04/board/siemens/draco/board.c"],["line","303"],["arch","armv7"]]],["state","stopped"]]]],["current-thread-id","1"]]}}
22-stack-info-depth --thread 1
23-stack-info-depth --thread 1
backtrace
24-interpreter-exec console "backtrace"
interpreter-exec mi2 -stack-info-depth
25-interpreter-exec console "interpreter-exec mi2 -stack-info-depth"

On the other hand, it looks (kind of) working in gdb cli:

...
Breakpoint 1, board_late_init () at board/siemens/draco/board.c:303
303             printf("Machine: " PRODUCT_MODEL_NAME "\n");
(gdb) backtrace
#0  board_late_init () at board/siemens/draco/board.c:303
#1  0x87faf610 in initcall_run_list (init_sequence=0x87fc8e40 <init_sequence_r>) at lib/initcall.c:27
#2  0x87f58e74 in board_init_r (new_gd=<optimized out>, dest_addr=<optimized out>) at common/board_r.c:916
#3  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#4  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#5  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#6  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#7  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#8  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#9  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#10 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#11 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
^CQuit
(gdb) interpreter-exec mi2 -stack-info-depth
^done,depth="12"

One thing I noticed though: after the first couple of lines, the backtrace command prints the same line in an infinite loop.

I'm no gdb expert, but I guess the mi2 command explores the stack as well. In fact, if I run the mi2 command before backtrace, right after the breakpoint has been hit, it does not return in a reasonable amount of time, and I need to stop it.

On the other hand though, if I run the backtrace command but stop it fairly soon (e.g. at the 10th line), the mi2 command returns a result rather quickly (as shown above).

EDIT: reading again your explanation, this looks to be exactly the problem. The mi2 command never returns an answer. What may be the root cause of this "infinite" stack trace?

GitMensch commented 1 year ago

I'm no gdb expert, but I guess the mi2 command explores the stack as well.

It tells the caller about the amount of stack elements.

The mi2 command never returns an answer. What may be the root cause of this "infinite" stack trace?

As I've understood it from your test (it isn't shown as gdb cli outout) It does return an answer with interpreter-exec mi2 -stack-info-depth - but only if you do it "in the right order"? (Note: you can also use a bt 1, maybe even a simple frame to test).

If the GDB or gdbserver is broken - one of this seems to be the case - then we either find an easy work-around, or it just won't work (possibly with any MI frontend).

Just to check: could you try with "plain GDB" on that device? This would work if it allows ssh connections and you reconfigure to use ssh debugging instead.

aleeraser commented 1 year ago

it isn't shown as gdb cli outout

The gdb cli is cut since the prior part does exactly the same as described in the post. For reference, I'm executing those commands and I cut the log right when the breakpoint is hit:

target extended-remote localhost:3334
monitor bp 0x80100000 0 hw
monitor reset halt
load
b board/siemens/draco/board.c:303
continue

It does return an answer with interpreter-exec mi2 -stack-info-depth - but only if you do it "in the right order"?

I see a weird behavior.

If I run backtrace before the mi2 command, the backtrace may go on forever if not manually stopped. After stopping it, the mi2 command will return the number of elements corresponding to when backtrace was stopped.

Breakpoint 1, board_late_init () at board/siemens/draco/board.c:303
303             printf("Machine: " PRODUCT_MODEL_NAME "\n");
(gdb) backtrace
#0  board_late_init () at board/siemens/draco/board.c:303
#1  0x87faf610 in initcall_run_list (init_sequence=0x87fc8e40 <init_sequence_r>) at lib/initcall.c:27
#2  0x87f58e74 in board_init_r (new_gd=<optimized out>, dest_addr=<optimized out>) at common/board_r.c:916
#3  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#4  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#5  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#6  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#7  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#8  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#9  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#10 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#11 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#12 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#13 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#14 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#15 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#16 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#17 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#18 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#19 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#20 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#21 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#22 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#23 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#24 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#25 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#26 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#27 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#28 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#29 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#30 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#31 0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
^CQuit <----------------------------------------------- manually stopped
(gdb) interpreter-exec mi2 -stack-info-depth
^done,depth="32"

Looking at the example above, from now on the backtrace command will always stops at the 31st frame and the mi2 command will always answer correctly 32.

If however I run the mi2 command first, as I mentioned earlier I must stop it at some time, otherwise it will never return. From this moment on, the behavior is the same as the previous example: all the subsequent calls to the mi2 or backtrace command will be instant and return the value that was previously explored.

Breakpoint 1, board_late_init () at board/siemens/draco/board.c:303
303             printf("Machine: " PRODUCT_MODEL_NAME "\n");
(gdb) interpreter-exec mi2 -stack-info-depth
^C^error,msg="Quit"
(gdb) interpreter-exec mi2 -stack-info-depth
^done,depth="9"
(gdb) backtrace
#0  board_late_init () at board/siemens/draco/board.c:303
#1  0x87faf610 in initcall_run_list (init_sequence=0x87fc8e40 <init_sequence_r>) at lib/initcall.c:27
#2  0x87f58e74 in board_init_r (new_gd=<optimized out>, dest_addr=<optimized out>) at common/board_r.c:916
#3  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#4  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#5  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#6  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#7  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
#8  0x87f53d14 in _main () at arch/arm/lib/crt0.S:144
<----------------------------------------------- not manually stopped
(gdb) 

Therefore, it looks like the issue is the first exploration of the stack. As soon as it's been explored once, the subsequent times are ok.

could you try with "plain GDB" on that device

Unfortunately it's not possible. As I mentioned, I'm trying to debug the bootloader of the device, which means that I'm lucky to even have a serial console. The gdb server is provided by OpenOCD via JTAG interface to the device.

brownts commented 1 year ago

Since you are using "extended remote", you should change your "target" attribute and remove the "remote" attribute, as indicated below. That will be more in alignment with your command line. I don't know that it will fix your issue, but is one inconsistency between the command line and the Native Debug configuration.

{
    "name": "U-Boot (attach to server)",
    "type": "gdb",
    "request": "attach",
    "target": "extended-remote localhost:3334",
    "executable": "${workspaceRoot}/u-boot",
    "stopAtConnect": true,
    "cwd": "${workspaceRoot}",
    "gdbpath": "[CUSTOM_PATH]/arm-ccp-linux-gnueabi-gdb",
    "valuesFormatting": "parseText",
    "autorun": [
        "monitor bp [ADDRESS] 0 hw",
        "monitor reset halt",
        "load",
    ]
}
aleeraser commented 1 year ago

@brownts I did as you suggested, but for some reason I also had to add

file u-boot

on top of the autorun command list, otherwise I would get a complain about a missing executable (although it is specified via the executable property).

But as you already guessed, this does not solve the issue. I think, as already mentioned above, the core issue is that the stack query command never returns an answer, unless stopped manually. Is it possible that this is caused by OpenOCD's implementation of gdbserver?

GitMensch commented 1 year ago

It is not possible, it is guaranteed that this is an issue with the server implementation.

There may be workarounds (you could have a look at another extension, there is one specific that documents the use of that server).

GitMensch commented 7 months ago

I think there isn't anything this extension could/should do here, right? In this case: let's close it.

aleeraser commented 7 months ago

Agree