Expand description
Support for unwinding the call stack and cleaning up stack frames.
Uses DWARF debugging information (.eh_frame
and .gcc_except_table
sections) from object files.
It can also be used to generate stack traces (backtrace) using only that debug information
without using frame pointer registers.
The general flow of the unwinding procedure is as follows:
- A panic occurs, which jumps to the panic entry point.
- The panic entry point invokes the panic_wrapper, which handles said panic
by invoking
start_unwinding()
in this crate with the reason for the panic. start_unwinding()
generates an iterator over all stack frames in the call stack (the knowledge for which comes from parsing the .eh_frame section).start_unwinding()
creates an unwinding context, which contains the stack frame iterator, the reason for the panic, and a reference to the current task being unwound. It then skips the first several stack frames, which correspond to the panic and unwind handlers themselves. Note that we cannot unwind those frames because they contain resources that we are currently using for unwinding purposes.- At any point hereafter, the unwinding context must be manually cleaned up.
start_unwinding()
callscontinue_unwinding()
, which contains the bulk of the unwinding logic.continue_unwinding()
iterates to the “next” stack frame (the previous frame in the call stack), and invokes its cleanup routine (landing pad) if it has one.- Once the cleanup routine is complete, it jumps to
_Unwind_Resume
automatically. This cannot be changed and is an artifact of how unwinding routines are generated by the compiler. _Unwind_Resume
is defined alongside the panic entry pointer, and is nothing more than a simple wrapper that invokescontinue_unwinding()
here.continue_unwinding()
continues iterating up the call stack. Once it reaches the end of the call stack (or an error occurs), we invoke a finalizer routine calledcleanup_unwinding_context()
.- In
cleanup_unwinding_context()
, the unwinding context pointer is recovered and all unwinding resources are freed. Finally, the task is marked as killed so it can no longer be scheduled in.
The flow of some functions was inspired by gcc’s libunwind
and from gimli/unwind-rs/src/glue.rs
.
Structs
- A single frame in the stack, which contains unwinding-related information for a single function call’s stack frame.
- An iterator over the stack frames on the current task’s call stack, which works in reverse calling order from the current function up the call stack to the very first function on the stack, at which point it will return
None
. - This is the context/state that is used during unwinding and passed around to the callback functions in the various unwinding stages, such as in
_Unwind_Resume()
.
Functions
- This function saves the current CPU register values onto the stack (to preserve them) and then invokes the given closure with those registers as the argument.