Stackdump Capture
This crate defines stackdump capture functions for the platforms it is compiled for.
Also see the main repo readme.
Platform detection is done automatically in the build.rs file. This only helps with capturing the stack and the registers. If you want to capture the heap or any static data, then you'll have to do that yourself.
The crate is built on the stackdump-core
crate.
To get stack traces, feed the captured data into the stackdump-trace
crate.
Cortex m
The cortex m capture comes in two variants:
- Without FPU
- Only captures and returns the core registers
- With FPU
- Also captures and returns the fpu registers
The fpu registers are automatically captured if the compilation target supports it. This does change the capture return type.
Example
With fpu:
use ArrayMemoryRegion;
use ArrayRegisterData;
let mut stack_capture = default;
let mut core_registers = default;
let mut fpu_registers = default;
capture;
For use when crashing (using cortex m as example target)
You probably want to do a stack dump when there's a crash so that you can send it to the server after a reboot.
To do that, you do need to do some setup yourself still. Because the stack capture can be quite big, you have to give a reference to it in the capture function. The registers are returned directly.
We need to be able to persist all the data across the reboot. If you have a filesystem or something similar, you could write it to there. But most embedded systems have got some SRAM so we could keep it in uninitialized memory.
use MaybeUninit;
use ArrayMemoryRegion;
use ArrayRegisterData;
static mut STACK_CAPTURE: = uninit;
static mut CORE_REGISTERS_CAPTURE: = uninit;
static mut FPU_REGISTERS_CAPTURE: = uninit;
We also need to be able to detect at bootup if a stackdump has been captured. The best way is to have an uninitialized integer present that can have a specific value to indicate the dump has been made.
use MaybeUninit;
static mut CAPTURE_INDICATOR: = uninit;
const CAPTURE_INDICATOR_TRUE: u32 = 0xC0DED1ED; // Code died
Now we can capture a everything in e.g. a panic.
!
In our main we can then check if there is a stackdump and send it to the server. Actually transporting the data is the responsibility of the user, but the memory regions and register data have an iter function so you can iterate over the bytes.