Search code examples
gdbembeddedopenocd

OpenOCD stacktrace


I am trying to get a stacktrace from a Telnet connection to OpenOCD.

There seems to be remainders off a stacktrace command which does nothing anymore. Litterally nothing. No message saying the command has been removed or deprecated, no message saying it does not exist.

Sample telnet session:

~ $ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt      
[atsame70n21.cpu] halted due to debug-request, current mode: Thread 
xPSR: 0x41010000 pc: 0x00406290 msp: 0x2040a6d8
> stacktrace
> bt
invalid command name "bt"

Like we can see, stacktrace is empty, with no error whatsoever, and since I'm not in a gdb session, bt is not valid.

However, gdb still manages to get a stack trace:

~ $ gdb build/executable.elf
> target extended-remote :3333
> interrupt
> bt
0  0x00406384 in time_keeper_get_time_ticks () at hal_sam/drivers/time_keeper.c:450
#1  0x004062b4 in time_keeper_get_micros () at library/hal_sam/drivers/time_keeper.c:421
#2  0x004067e0 in time_keeper_delay_micros (microseconds=300000) at library/hal_sam/drivers/time_keeper.c:488
#3  0x00406906 in time_keeper_delay_ms (milliseconds=300) at library/hal_sam/drivers/time_keeper.c:510
#4  0x00400e2c in task_sleepA (arg=0x0) at src/tasks.c:84
#5  0x00401fa0 in scheduler_update (scheduler=0x204038d8 <main_tasks>) at library/runtime/scheduler.c:195
#6  0x0040049e in main () at src/main.c:29

So how does it do it? What command does gdb use to get the stacktrace from openocd? Does it read the stack pointer and find the callers? That seems highly impractical to me since even it's hard to know which variable on the stack is a function pointer?


Solution

  • GDB does indeed build the stack trace by examining the underlying machine state combined with knowledge extracted from the debug information and an understanding of the architectures ABI. It is the debug information that allows GDB to know the types of local variables and function arguments.

    So GDB will build the backtrace using a combination of register and memory reads.

    OpenOCD couldn't do any better, and often OpenOCD wont even have access to a binary with debug information and so would have to rely entirely on building the backtrace using entirely ABI knowledge, this is often fine for simple cases, but when compilers perform aggressive optimisation, e.g. merging function prologues into the function body, or inlining functions entirely, ABI knowledge alone is not enough to build an accurate backtrace.