llvm/llvm-project
libunwind
libunwind/ is the LLVM project's implementation of the Itanium-ABI stack-unwinding library. It provides the _Unwind_* API that runtime libraries (most notably libc++abi) use to walk the stack during exception handling, and the unw_* "low-level libunwind" API for users who want direct access to frame state.
Purpose
Stack unwinding is the act of walking back through the call stack and (for exceptions) calling each frame's cleanup or catch handler. To do that without crashing, an unwinder needs to know, for every program counter, where the saved registers are — that information lives in DWARF Call Frame Information (.eh_frame or .debug_frame) on most platforms, in compact unwind tables on macOS, and in SEH/EH-funclet tables on Windows. libunwind reads those tables and steps through frames.
Directory layout
libunwind/
├── include/ # Public headers — libunwind.h, unwind.h, unwind_arm_ehabi.h, unwind_itanium.h
├── src/ # Implementation
│ ├── UnwindLevel1.c # The "level-1" _Unwind_* entry points
│ ├── UnwindLevel1-gcc-ext.c # GCC-extension exports for compatibility
│ ├── libunwind.cpp # The "low-level" unw_* C++ implementation
│ ├── DwarfInstructions.hpp # DWARF CFI interpreter
│ ├── DwarfParser.hpp # DWARF table parser
│ ├── EHHeaderParser.hpp # .eh_frame_hdr parser
│ ├── Unwind-EHABI.cpp # ARM EHABI variant
│ ├── Unwind-seh.cpp # Windows SEH variant
│ ├── Registers.hpp # Per-arch register description
│ ├── UnwindCursor.hpp # Frame-walking state machine
│ └── ...
├── test/ # lit regression tests
├── docs/
├── cmake/
└── CMakeLists.txtWhat's implemented
- The Itanium
_Unwind_*API —_Unwind_RaiseException,_Unwind_Resume,_Unwind_GetIP,_Unwind_GetCFA,_Unwind_GetLanguageSpecificData, etc. This is what compilers emit and what personalities (e.g.,__gxx_personality_v0) call. - The low-level
unw_*API —unw_init_local,unw_step,unw_get_reg,unw_resume,unw_get_proc_name. Useful for profilers and crash reporters. - DWARF CFI interpretation — including the relatively new
.eh_frame_hdrfast-lookup table and per-arch register lowerings. - ARM EHABI support, Windows SEH support, and the compact unwind format used on macOS/iOS.
How it works
graph LR
raise[_Unwind_RaiseException] --> cursor[UnwindCursor]
cursor --> findFrame[Find FDE for PC]
findFrame --> dwarf[Parse DWARF CFI]
dwarf --> regs[Compute saved registers]
regs --> personality["Call frame's personality<br/>(__gxx_personality_v0)"]
personality -->|search phase| cursor
personality -->|cleanup phase| restore[Restore registers]
restore --> jump[Jump to landing pad]The unwinder runs in two phases (per the Itanium ABI):
- Search phase — walk frames, calling each personality with
_UA_SEARCH_PHASE. Personality returns_URC_HANDLER_FOUNDif there's a catch. If we run off the stack, the unwinder fails (and the program eventuallyterminate()s). - Cleanup phase — walk frames again, this time with
_UA_CLEANUP_PHASE, restoring registers between frames and running each frame's cleanup landing pad. Stop at the catch handler.
Integration points
- libc++abi (
libcxxabi) is the headline consumer. C++ exceptions implement throw/catch entirely on top of libunwind. - Stack tracing libraries (e.g., backtrace pretty-printers, llvm-symbolizer) use the low-level
unw_*API. - The system unwinder is sometimes used instead of libunwind — Apple's
libunwind.dylib,libgcc_son Linux, the kernel-supplied unwinder in baremetal embedded environments. libunwind's contract is stable, so a system swap should be transparent.
Entry points for modification
- Adding a target architecture: extend
Registers.hppwith the arch's register set, add the per-arch CFI interpreter knobs inDwarfInstructions.hpp, add a test underlibunwind/test/. - Implementing a new unwinding format (rare): a new variant of
Unwind-EHABI.cpp/Unwind-seh.cppplus matching glue.
Reference
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.
Previous
libcxxabi
Next
polly