when the --gdb flag is passed, probe-run will spawn a GDB server when
the program panics or encounters a hardware fault (HardFault)
a GDB client can then connect to inspect the failure
blockers
[ ] AFAICT, there's no way to clean shutdown the GDB server implementation I used here. we may want to consider using gdbstub instead. another advantage of using gdbstub is that we could forbid operations like finish, step and next which don't make sense in postmortem context as it's no longer possible to continue executing the program
open questions
[ ] should we spawn a GDB server on stack overflows? a stack overflow corrupts the top frame so it becomes impossible to compute a backtrace. however, it's still possible to read CPU registers though it may be hard to map these back to meaningful variables as the frame command won't work in this context (see code block below)
$ arm-none-eabi-gdb -q target/thumbv7em-none-eabihf/debug/overflow
Reading symbols from target/thumbv7em-none-eabihf/debug/overflow...
(gdb) target remote :1337
Remote debugging using :1337
HardFaultTrampoline () at asm.S:19
19 asm.S: No such file or directory.
(gdb) backtrace
#0 HardFaultTrampoline () at asm.S:19
#1 <signal handler called>
Backtrace stopped: Cannot access memory at address 0x1ffff9a8
(gdb) frame 2
No frame at level 2.
(gdb) info registers
r0 0x7 7
r1 0x1 1
r2 0x2003fcdb 537132251
r3 0x2003fcdb 537132251
r4 0x1ffff9bc 536869308
r5 0x0 0
r6 0x0 0
r7 0x200039cc 536885708
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x200079dc 536902108
sp 0x1ffff990 0x1ffff990
lr 0xfffffff9 4294967289
pc 0x16c8 0x16c8 <HardFaultTrampoline>
cpsr 0x21000003 553648131
alternative / possible extension
allow running the GDB server and defmt logs concurrently.
the problem with this if using gdb-server is that its API is hard-coded to use std::sync::Mutex which is not guaranteed to be a fair mutex on all platforms. the defmt logs are collected in a tight loop, via RTT, and that loop also needs to access the mutex that gdb-server uses. the like outcome is that the RTT loop "hogs" the mutex and starves the gdb-server thread. a gdbstub implementation that uses a fair mutex (e.g. parking_lot::FairMutex) would not run into such problem
the downside of this feature is that the throughput of the RTT logs would go down. as the gdb feature is opt-in that may not be much of an issue as long the downside is properly documented
when the
--gdb
flag is passed,probe-run
will spawn a GDB server when the program panics or encounters a hardware fault (HardFault)a GDB client can then connect to inspect the failure
blockers
gdbstub
instead. another advantage of usinggdbstub
is that we could forbid operations likefinish
,step
andnext
which don't make sense in postmortem context as it's no longer possible to continue executing the programopen questions
backtrace
. however, it's still possible to read CPU registers though it may be hard to map these back to meaningful variables as theframe
command won't work in this context (see code block below)alternative / possible extension
gdb-server
is that its API is hard-coded to usestd::sync::Mutex
which is not guaranteed to be a fair mutex on all platforms. the defmt logs are collected in a tight loop, via RTT, and that loop also needs to access the mutex thatgdb-server
uses. the like outcome is that the RTT loop "hogs" the mutex and starves thegdb-server
thread. agdbstub
implementation that uses a fair mutex (e.g.parking_lot::FairMutex
) would not run into such problem