diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b26f0f5..a513456 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -56,3 +56,5 @@ * [Final Code](vec-final.md) * [Implementing Arc and Mutex](arc-and-mutex.md) * [FFI](ffi.md) +* [Beneath `std`](beneath-std.md) + * [#[panic_implementation]](panic-implementation.md) diff --git a/src/beneath-std.md b/src/beneath-std.md new file mode 100644 index 0000000..2c759f0 --- /dev/null +++ b/src/beneath-std.md @@ -0,0 +1,10 @@ +# Beneath std + +This section documents (or will document) features that are provided by the standard library and +that `#![no_std]` developers have to deal with (i.e. provide) to build `#![no_std]` binary crates. A +(likely incomplete) list of such features is shown below: + +- #[lang = "eh_personality"] +- #[lang = "start"] +- #[lang = "termination"] +- #[panic_implementation] diff --git a/src/panic-implementation.md b/src/panic-implementation.md new file mode 100644 index 0000000..963a853 --- /dev/null +++ b/src/panic-implementation.md @@ -0,0 +1,70 @@ +## #[panic_implementation] + +`#[panic_implementation]` is used to define the behavior of `panic!` in `#![no_std]` applications. +The `#[panic_implementation]` attribute must be applied to a function with signature `fn(&PanicInfo) +-> !` and such function must appear *once* in the dependency graph of a binary / dylib / cdylib +crate. The API of `PanicInfo` can be found in the [API docs]. + +[API docs]: https://doc.rust-lang.org/nightly/core/panic/struct.PanicInfo.html + +Given that `#![no_std]` applications have no *standard* output and that some `#![no_std]` +applications, e.g. embedded applications, need different panicking behaviors for development and for +release it can be helpful to have panic crates, crate that only contain a `#[panic_implementation]`. +This way applications can easily swap the panicking behavior by simply linking to a different panic +crate. + +Below is shown an example where an application has a different panicking behavior depending on +whether is compiled using the dev profile (`cargo build`) or using the release profile (`cargo build +--release`). + +``` rust +// crate: panic-semihosting -- log panic message to the host stderr using semihosting + +#![feature(core_intrinsics)] +#![feature(panic_implementation)] +#![no_std] + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + let host_stderr = /* .. */; + + writeln!(host_stderr, "{}", info).ok(); + + core::intrinsics::breakpoint(); + + loop {} +} +``` + +``` rust +// crate: panic-abort -- abort on panic! + +#![feature(core_intrinsics)] +#![feature(panic_implementation)] +#![no_std] + +#[panic_implementation] +fn panic(info: &PanicInfo) -> ! { + unsafe { core::intrinsics::abort() } +} +``` + +``` rust +// crate: app + +#![no_std] + +// dev profile +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +// release profile +#[cfg(not(debug_assertions))] +extern crate panic_abort; + +// omitted: other `extern crate`s + +fn main() { + // .. +} +```