Closed aleeraser closed 7 months 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,
?
Below the full log.
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:
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?
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).
I think there isn't anything this extension could/should do here, right? In this case: let's close it.
Agree
gdb-version
: 11.2I'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:
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.