sframe
Stack walking: space and time trade-offs
On most Linux platforms (except AArch32, which uses .ARM.exidx), DWARF .eh_frame is required for C++ exception handling and stack unwinding to restore callee-saved registers.
While .eh_frame can be used for call trace recording, it is often criticized for its runtime overhead.
As an alternative, developers can enable frame pointers, or adopt SFrame, a newer format designed specifically for profiling.
This article examines the size overhead of enabling non-DWARF stack walking mechanisms when building several LLVM executables.
Runtime performance analysis will be added in a future update.
…Remarks on SFrame
SFrame is a new stack walking format for userspace profiling, inspired by Linux's in-kernel ORC unwind format.
While SFrame eliminates some .eh_frame CIE/FDE overhead, it sacrifices functionality (e.g., personality, LSDA, callee-saved registers) and flexibility, and its stack offsets are less compact than .eh_frame's bytecode-style CFI instructions.
In llvm-project executables I've tested on x86-64, .sframe section is 20% larger than .eh_frame.
It also remains significantly larger than highly compact schemes like Windows ARM64 unwind codes.
SFrame describes three elements for each function:
- Canonical Frame Address (CFA): The base address for stack frame calculations
- Return address
- Frame pointer
An .sframe section follows a straightforward layout:
- Header: Contains metadata and offset information
- Auxiliary header (optional): Reserved for future extensions
- Function Descriptor Entries (FDEs): Array describing each function
- Frame Row Entries (FREs): Arrays of unwinding information per function