From a0c1de174abda5bc5655ed27b0c5741a1a48a92e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 20 Jun 2018 14:16:51 -0500 Subject: [PATCH 1/4] document #[panic_implementation] --- src/SUMMARY.md | 2 ++ src/beneath-std.md | 10 ++++++ src/panic-implementation.md | 70 +++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/beneath-std.md create mode 100644 src/panic-implementation.md 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() { + // .. +} +``` From c005be94939cdb80a130ce5b8ebb7d786168637b Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 7 Sep 2018 18:52:02 +0200 Subject: [PATCH 2/4] panic_implementation -> panic_handler; remove unstable features --- src/SUMMARY.md | 2 +- ...nic-implementation.md => panic-handler.md} | 25 ++++++++----------- 2 files changed, 11 insertions(+), 16 deletions(-) rename src/{panic-implementation.md => panic-handler.md} (69%) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index a513456..dfb8e7b 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -57,4 +57,4 @@ * [Implementing Arc and Mutex](arc-and-mutex.md) * [FFI](ffi.md) * [Beneath `std`](beneath-std.md) - * [#[panic_implementation]](panic-implementation.md) + * [#[panic_handler]](panic-handler.md) diff --git a/src/panic-implementation.md b/src/panic-handler.md similarity index 69% rename from src/panic-implementation.md rename to src/panic-handler.md index 963a853..8c9a43e 100644 --- a/src/panic-implementation.md +++ b/src/panic-handler.md @@ -1,7 +1,7 @@ -## #[panic_implementation] +## #[panic_handler] -`#[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) +`#[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]. @@ -9,7 +9,7 @@ crate. The API of `PanicInfo` can be found in the [API docs]. 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]`. +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. @@ -20,32 +20,27 @@ whether is compiled using the dev profile (`cargo build`) or using the release p ``` rust // crate: panic-semihosting -- log panic message to the host stderr using semihosting -#![feature(core_intrinsics)] -#![feature(panic_implementation)] #![no_std] -#[panic_implementation] +#[panic_handler] fn panic(info: &PanicInfo) -> ! { let host_stderr = /* .. */; + // logs "panicked at '$reason', src/main.rs:27:4" to the host stderr writeln!(host_stderr, "{}", info).ok(); - core::intrinsics::breakpoint(); - loop {} } ``` ``` rust -// crate: panic-abort -- abort on panic! +// crate: panic-halt -- halt the thread on panic; messages are discarded -#![feature(core_intrinsics)] -#![feature(panic_implementation)] #![no_std] -#[panic_implementation] +#[panic_handler] fn panic(info: &PanicInfo) -> ! { - unsafe { core::intrinsics::abort() } + loop {} } ``` @@ -60,7 +55,7 @@ extern crate panic_semihosting; // release profile #[cfg(not(debug_assertions))] -extern crate panic_abort; +extern crate panic_halt; // omitted: other `extern crate`s From 5f36fc705b6943db3917554328cc061db92baf12 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 7 Sep 2018 20:18:36 +0200 Subject: [PATCH 3/4] make link relative --- src/panic-handler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panic-handler.md b/src/panic-handler.md index 8c9a43e..6a22d72 100644 --- a/src/panic-handler.md +++ b/src/panic-handler.md @@ -5,7 +5,7 @@ The `#[panic_handler]` attribute must be applied to a function with signature `f -> !` 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 +[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 From 676e7d1aaa82fa9e1ba4de789ca904c6c0cda8d6 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 7 Sep 2018 20:39:53 +0200 Subject: [PATCH 4/4] ignore tests mdbook doesn't support no_std code --- src/panic-handler.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/panic-handler.md b/src/panic-handler.md index 6a22d72..b06707b 100644 --- a/src/panic-handler.md +++ b/src/panic-handler.md @@ -17,14 +17,30 @@ Below is shown an example where an application has a different panicking behavio 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 +``` 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 host_stderr = /* .. */; + let mut host_stderr = HStderr::new(); // logs "panicked at '$reason', src/main.rs:27:4" to the host stderr writeln!(host_stderr, "{}", info).ok(); @@ -33,18 +49,20 @@ fn panic(info: &PanicInfo) -> ! { } ``` -``` rust +``` 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) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` -``` rust +``` rust, ignore // crate: app #![no_std]