Go to file
Dan Gohman 67ebac869f Make the spin dependency optional.
Make the spin dependency optional so that users enabling libc, which
enables libc-based locking, don't need to depend on spin.
2021-10-03 09:40:20 -07:00
cdylib Move dummy panic handler to lib as well 2021-08-26 11:00:25 +01:00
example Add backtrace to panic-handler feature 2021-08-26 11:50:19 +01:00
src Try fde-gnu-eh-frame-hdr before fde-phdr. 2021-10-02 11:05:17 -07:00
.gitignore FDE finder 2021-08-25 02:55:49 +01:00
Cargo.toml Make the spin dependency optional. 2021-10-03 09:40:20 -07:00
LICENSE-APACHE FDE finder 2021-08-25 02:55:49 +01:00
LICENSE-MIT FDE finder 2021-08-25 02:55:49 +01:00
README.md Describe baremetal 2021-08-26 22:48:44 +01:00

Unwinding library in Rust and for Rust

This library serves two purposes:

  1. Provide a pure Rust alternative to libgcc_eh or libunwind.
  2. Provide easier unwinding support for #![no_std] targets.

Currently supports x86_64 and RV64.

Unwinder

The unwinder can be enabled with unwinder feature. Here are the feature gates related to the unwinder:

Feature Default Description
unwinder Yes The primary feature gate to enable the unwinder
fde-phdr Yes Use dl_iterator_phdr to retrieve frame unwind table. Depends on libc.
fde-registry Yes Provide __register__frame and others for dynamic registration
fde-static No Use __executable_start, __etext and __eh_frame to retrieve frame unwind table. The former two symbols are usually provided by the linker, while the last one would need to be provided by the user via linker script.
dwarf-expr Yes Enable the dwarf expression evaluator. Usually not necessary for Rust
hide-trace Yes Hide unwinder frames in back trace

If you want to use the unwinder for other Rust (C++, or any programs that utilize the unwinder), you can build the unwind_dyn crate provided, and use LD_PRELOAD to replace the system unwinder with it.

cd cdylib
cargo build --release
# Test the unwinder using rustc. Why not :)
LD_PRELOAD=`../target/release/libunwind_dyn.so` rustc +nightly -Ztreat-err-as-bug

If you want to link to the unwinder in a Rust binary, simply add

extern crate unwind;

Personality and other utilities

The library also provides Rust personality function. This can work with the unwinder described above or with a different unwinder. This can be handy if you are working on a #![no_std] binary/staticlib/cdylib and you still want unwinding support.

Here are the feature gates related:

Feature Default Description
personality No Provides #[lang = eh_personality]
print No Provides (e)?print(ln)?. This is really only here because panic handler needs to provide things. Depends on libc.
panic No Provides begin_panic and catch_unwind. Only stack unwinding functionality is provided and no printing is done, because this feature does not depend on libc.
panic-handler No Provides #[panic_handler]. Provides similar behaviour on panic to std, with RUST_BACKTRACE support as well. Stack trace won't have symbols though. Depends on libc.
system-alloc No Provides a global allocator which calls malloc and friends. Provided for convience.

If you are writing a #![no_std] program, simply enable personality, panic-handler and system-alloc in addition to the defaults, you instantly obtains the ability to do unwinding! An example is given in example/.

Baremetal

To use this library for baremetal projects, disable default features and enable unwinder, fde-static, personality, panic. dwarf-expr and hide-trace are optional. Modify the linker script by

/* Inserting these two lines */
. = ALIGN(8);
PROVIDE(__eh_frame = .);
/* before .eh_frame rule */
.eh_frame : { KEEP (*(.eh_frame)) *(.eh_frame.*) }

And that's it! After you ensured that the global allocator is functional, you can use unwind::panic::begin_panic to initiate an unwing and catch using unwind::panic::catch_unwind, as if you have a std.

If you have your own version of thread_local and println! working, you can port panic_handler.rs for double-panic protection and stack traces!

TODO

  • A better project name!
  • Remove dependencies on alloc.