From 02c99786f975fbb2fb06390684a2cdce6f72cd58 Mon Sep 17 00:00:00 2001 From: dimpolo <33688001+dimpolo@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:38:40 +0200 Subject: [PATCH] esp-backtrace: Add custom-pre-backtrace feature (#1822) --- esp-backtrace/CHANGELOG.md | 1 + esp-backtrace/Cargo.toml | 11 +++++----- esp-backtrace/README.md | 37 +++++++++++++++++---------------- esp-backtrace/src/lib.rs | 42 +++++++++++++++++++++++++------------- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/esp-backtrace/CHANGELOG.md b/esp-backtrace/CHANGELOG.md index f7f804a18..111839191 100644 --- a/esp-backtrace/CHANGELOG.md +++ b/esp-backtrace/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +- add custom-pre-backtrace feature (#1822) ### Changed diff --git a/esp-backtrace/Cargo.toml b/esp-backtrace/Cargo.toml index d0ecc0bfe..77373a654 100644 --- a/esp-backtrace/Cargo.toml +++ b/esp-backtrace/Cargo.toml @@ -42,11 +42,12 @@ print-float-registers = [] # TODO support esp32p4 # You may optionally enable one or more of the below features to provide # additional functionality: -colors = [] -custom-halt = [] -exception-handler = [] -halt-cores = [] -panic-handler = [] +colors = [] +custom-halt = [] +custom-pre-backtrace = [] +exception-handler = [] +halt-cores = [] +panic-handler = [] [lints.rust] unexpected_cfgs = "allow" diff --git a/esp-backtrace/README.md b/esp-backtrace/README.md index e5234705b..c6218fc63 100644 --- a/esp-backtrace/README.md +++ b/esp-backtrace/README.md @@ -17,24 +17,25 @@ When using the panic and/or exception handler make sure to include `use esp_back ## Features -| Feature | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------------------ | -| esp32 | Target ESP32 | -| esp32c2 | Target ESP32-C2 | -| esp32c3 | Target ESP32-C3 | -| esp32c6 | Target ESP32-C6 | -| esp32h2 | Target ESP32-H2 | -| esp32p4 | Target ESP32-P4 | -| esp32s2 | Target ESP32-S2 | -| esp32s3 | Target ESP32-S3 | -| panic-handler | Include a panic handler, will add `esp-println` as a dependency | -| exception-handler | Include an exception handler, will add `esp-println` as a dependency | -| println | Use `esp-println` to print messages | -| defmt | Use `defmt` logging to print messages\* (check [example](https://github.com/playfulFence/backtrace-defmt-example)) | -| colors | Print messages in red\* | -| halt-cores | Halt both CPUs on ESP32 / ESP32-S3 instead of doing a `loop {}` in case of a panic or exception | -| semihosting | Call `semihosting::process::abort()` on panic. | -| custom-halt | Invoke the extern function `custom_halt()` instead of doing a `loop {}` in case of a panic or exception | +| Feature | Description | +|----------------------|--------------------------------------------------------------------------------------------------------------------| +| esp32 | Target ESP32 | +| esp32c2 | Target ESP32-C2 | +| esp32c3 | Target ESP32-C3 | +| esp32c6 | Target ESP32-C6 | +| esp32h2 | Target ESP32-H2 | +| esp32p4 | Target ESP32-P4 | +| esp32s2 | Target ESP32-S2 | +| esp32s3 | Target ESP32-S3 | +| panic-handler | Include a panic handler, will add `esp-println` as a dependency | +| exception-handler | Include an exception handler, will add `esp-println` as a dependency | +| println | Use `esp-println` to print messages | +| defmt | Use `defmt` logging to print messages\* (check [example](https://github.com/playfulFence/backtrace-defmt-example)) | +| colors | Print messages in red\* | +| halt-cores | Halt both CPUs on ESP32 / ESP32-S3 instead of doing a `loop {}` in case of a panic or exception | +| semihosting | Call `semihosting::process::abort()` on panic. | +| custom-halt | Invoke the extern function `custom_halt()` instead of doing a `loop {}` in case of a panic or exception | +| custom-pre-backtrace | Invoke the extern function `custom_pre_backtrace()` before handling a panic or exception | \* _only used for panic and exception handlers_ diff --git a/esp-backtrace/src/lib.rs b/esp-backtrace/src/lib.rs index f5cd1c4b4..eb55daef6 100644 --- a/esp-backtrace/src/lib.rs +++ b/esp-backtrace/src/lib.rs @@ -52,6 +52,8 @@ pub mod arch; #[cfg(feature = "panic-handler")] #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { + pre_backtrace(); + #[cfg(feature = "colors")] set_color_code(RED); @@ -107,14 +109,12 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { if backtrace.iter().filter(|e| e.is_some()).count() == 0 { println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)"); } - for e in backtrace { - if let Some(addr) = e { - #[cfg(all(feature = "colors", feature = "println"))] - println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET); + for addr in backtrace.into_iter().flatten() { + #[cfg(all(feature = "colors", feature = "println"))] + println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET); - #[cfg(not(all(feature = "colors", feature = "println")))] - println!("0x{:x}", addr - crate::arch::RA_OFFSET); - } + #[cfg(not(all(feature = "colors", feature = "println")))] + println!("0x{:x}", addr - crate::arch::RA_OFFSET); } #[cfg(feature = "colors")] @@ -131,6 +131,8 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { #[no_mangle] #[link_section = ".rwtext"] unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) { + pre_backtrace(); + #[cfg(feature = "colors")] set_color_code(RED); @@ -166,6 +168,8 @@ unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) #[cfg(all(feature = "exception-handler", target_arch = "riscv32"))] #[export_name = "ExceptionHandler"] fn exception_handler(context: &arch::TrapFrame) -> ! { + pre_backtrace(); + let mepc = context.pc; let code = context.mcause & 0xff; let mtval = context.mtval; @@ -215,14 +219,12 @@ fn exception_handler(context: &arch::TrapFrame) -> ! { if backtrace.iter().filter(|e| e.is_some()).count() == 0 { println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)"); } - for e in backtrace { - if let Some(addr) = e { - #[cfg(all(feature = "colors", feature = "println"))] - println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET); + for addr in backtrace.into_iter().flatten() { + #[cfg(all(feature = "colors", feature = "println"))] + println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET); - #[cfg(not(all(feature = "colors", feature = "println")))] - println!("0x{:x}", addr - crate::arch::RA_OFFSET); - } + #[cfg(not(all(feature = "colors", feature = "println")))] + println!("0x{:x}", addr - crate::arch::RA_OFFSET); } } @@ -363,3 +365,15 @@ fn halt() -> ! { loop {} } + +#[cfg(not(feature = "custom-pre-backtrace"))] +#[allow(unused)] +fn pre_backtrace() {} + +#[cfg(feature = "custom-pre-backtrace")] +fn pre_backtrace() { + extern "Rust" { + fn custom_pre_backtrace(); + } + unsafe { custom_pre_backtrace() } +}