diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b26f0f5..dfb8e7b 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_handler]](panic-handler.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-handler.md b/src/panic-handler.md new file mode 100644 index 0000000..b06707b --- /dev/null +++ b/src/panic-handler.md @@ -0,0 +1,83 @@ +## #[panic_handler] + +`#[panic_handler]` is used to define the behavior of `panic!` in `#![no_std]` applications. +The `#[panic_handler]` 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]: ../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_handler]`. +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, ignore +// crate: panic-semihosting -- log panic messages to the host stderr using semihosting + +#![no_std] + +use core::fmt::{Write, self}; +use core::panic::PanicInfo; + +struct HStderr { + // .. +# _0: (), +} +# +# impl HStderr { +# fn new() -> HStderr { HStderr { _0: () } } +# } +# +# impl fmt::Write for HStderr { +# fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) } +# } + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + let mut host_stderr = HStderr::new(); + + // logs "panicked at '$reason', src/main.rs:27:4" to the host stderr + writeln!(host_stderr, "{}", info).ok(); + + loop {} +} +``` + +``` rust, ignore +// crate: panic-halt -- halt the thread on panic; messages are discarded + +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} +``` + +``` rust, ignore +// crate: app + +#![no_std] + +// dev profile +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +// release profile +#[cfg(not(debug_assertions))] +extern crate panic_halt; + +// omitted: other `extern crate`s + +fn main() { + // .. +} +```