WebFreak001 / code-debug

Native debugging for VSCode

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

UI out of sync with gdb status

aleeraser opened this issue · comments

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 serial console stops at the right moment
  • the debug console in vscode shows that the breakpoint was hit.

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.

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,?

Below the full log.

Click to expand
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

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:

const depth: number = (await this.sendCommand(["stack-info-depth"].concat(options).join(" "))).result("depth").valueOf();

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).

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?

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.

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.

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",
    ]
}

@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?

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