Crate unwind

source ·
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() calls continue_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 invokes continue_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 called cleanup_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.

Trait Aliases