Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #41 from esp-rs/hint-on-stack-overflow
Browse files Browse the repository at this point in the history
Hint on detected stack-overflow
  • Loading branch information
bjoernQ authored Dec 11, 2023
2 parents db2bb85 + 5536ad7 commit b9abee1
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 41 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ features = ["esp32c3", "panic-handler", "exception-handler", "print-uart"]
esp-println = { version = "0.7.0", optional = true, default-features = false }

[features]
default = [ "colors" ]

# You must enable exactly one of the below features to support the correct chip:
esp32 = ["esp-println?/esp32"]
esp32c2 = ["esp-println?/esp32c2"]
Expand All @@ -34,3 +36,4 @@ print-uart = ["esp-println/uart"]
exception-handler = ["esp-println"]
panic-handler = ["esp-println"]
halt-cores = []
colors = []
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ When using this together with `esp-println` make sure to use the same output kin
| print-uart | Use UART to print messages\* |
| print-jtag-serial | Use JTAG-Serial to print messages\* |
| print-rtt | Use RTT to print messages\* |
| colors | Print messages in red\* |
| halt-cores | Halt both CPUs on ESP32 / ESP32-S3 in case of a panic or exception |

\* _only used for panic and exception handlers_
Expand Down
99 changes: 66 additions & 33 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#![no_std]
#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))]

const MAX_BACKTRACE_ADRESSES: usize = 10;
const MAX_BACKTRACE_ADDRESSES: usize = 10;

#[cfg(feature = "colors")]
const RESET: &str = "\u{001B}[0m";
#[cfg(feature = "colors")]
const RED: &str = "\u{001B}[31m";

#[cfg_attr(target_arch = "riscv32", path = "riscv.rs")]
#[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")]
Expand All @@ -12,6 +17,9 @@ pub mod arch;
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
use esp_println::println;

#[cfg(feature = "colors")]
println!("{}", RED);

println!(" ");
println!(" ");

Expand Down Expand Up @@ -39,6 +47,9 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
}
}

#[cfg(feature = "colors")]
println!("{}", RESET);

halt();
}

Expand All @@ -48,6 +59,9 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) {
use esp_println::println;

#[cfg(feature = "colors")]
println!("{}", RED);

println!("\n\nException occured '{:?}'", cause);
println!("{:?}", context);

Expand All @@ -62,6 +76,9 @@ unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context)
println!("");
println!("");

#[cfg(feature = "colors")]
println!("{}", RESET);

halt();
}

Expand All @@ -74,45 +91,61 @@ fn exception_handler(context: &arch::TrapFrame) -> ! {
let code = context.mcause & 0xff;
let mtval = context.mtval;

let code = match code {
0 => "Instruction address misaligned",
1 => "Instruction access fault",
2 => "Illegal instruction",
3 => "Breakpoint",
4 => "Load address misaligned",
5 => "Load access fault",
6 => "Store/AMO address misaligned",
7 => "Store/AMO access fault",
8 => "Environment call from U-mode",
9 => "Environment call from S-mode",
10 => "Reserved",
11 => "Environment call from M-mode",
12 => "Instruction page fault",
13 => "Load page fault",
14 => "Reserved",
15 => "Store/AMO page fault",
_ => "UNKNOWN",
};
println!(
"Exception '{}' mepc=0x{:08x}, mtval=0x{:08x}",
code, mepc, mtval
);
println!("{:x?}", context);

let backtrace = crate::arch::backtrace_internal(context.s0 as u32, 0);
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 {
println!("0x{:x}", addr);
#[cfg(feature = "colors")]
println!("{}", RED);

if code == 14 {
println!();
println!(
"Stack overflow detected at 0x{:x} called by 0x{:x}",
mepc, context.ra
);
println!();
} else {
let code = match code {
0 => "Instruction address misaligned",
1 => "Instruction access fault",
2 => "Illegal instruction",
3 => "Breakpoint",
4 => "Load address misaligned",
5 => "Load access fault",
6 => "Store/AMO address misaligned",
7 => "Store/AMO access fault",
8 => "Environment call from U-mode",
9 => "Environment call from S-mode",
10 => "Reserved",
11 => "Environment call from M-mode",
12 => "Instruction page fault",
13 => "Load page fault",
14 => "Reserved",
15 => "Store/AMO page fault",
_ => "UNKNOWN",
};

println!(
"Exception '{}' mepc=0x{:08x}, mtval=0x{:08x}",
code, mepc, mtval
);
println!("{:x?}", context);

let backtrace = crate::arch::backtrace_internal(context.s0 as u32, 0);
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 {
println!("0x{:x}", addr);
}
}
}

println!("");
println!("");
println!("");

#[cfg(feature = "colors")]
println!("{}", RESET);

halt();
}

Expand Down
8 changes: 4 additions & 4 deletions src/riscv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::arch::asm;

use crate::MAX_BACKTRACE_ADRESSES;
use crate::MAX_BACKTRACE_ADDRESSES;

/// Registers saved in trap handler
#[doc(hidden)]
Expand Down Expand Up @@ -104,7 +104,7 @@ MTVAL=0x{:08x}
/// Get an array of backtrace addresses.
///
/// This needs `force-frame-pointers` enabled.
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADRESSES] {
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let fp = unsafe {
let mut _tmp: u32;
asm!("mv {0}, x8", out(reg) _tmp);
Expand All @@ -117,7 +117,7 @@ pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADRESSES] {
pub(crate) fn backtrace_internal(
fp: u32,
suppress: i32,
) -> [Option<usize>; MAX_BACKTRACE_ADRESSES] {
) -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let mut result = [None; 10];
let mut index = 0;

Expand Down Expand Up @@ -147,7 +147,7 @@ pub(crate) fn backtrace_internal(
result[index] = Some(address as usize);
index += 1;

if index >= MAX_BACKTRACE_ADRESSES {
if index >= MAX_BACKTRACE_ADDRESSES {
break;
}
} else {
Expand Down
8 changes: 4 additions & 4 deletions src/xtensa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::MAX_BACKTRACE_ADRESSES;
use crate::MAX_BACKTRACE_ADDRESSES;
use core::arch::asm;

#[doc(hidden)]
Expand Down Expand Up @@ -236,7 +236,7 @@ F15=0x{:08x}

/// Get an array of backtrace addresses.
///
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADRESSES] {
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let sp = unsafe {
let mut _tmp: u32;
asm!("mov {0}, a1", out(reg) _tmp);
Expand All @@ -253,7 +253,7 @@ pub(crate) fn sanitize_address(address: u32) -> u32 {
pub(crate) fn backtrace_internal(
sp: u32,
suppress: i32,
) -> [Option<usize>; MAX_BACKTRACE_ADRESSES] {
) -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let mut result = [None; 10];
let mut index = 0;

Expand Down Expand Up @@ -288,7 +288,7 @@ pub(crate) fn backtrace_internal(
result[index] = Some(address as usize);
index += 1;

if index >= MAX_BACKTRACE_ADRESSES {
if index >= MAX_BACKTRACE_ADDRESSES {
break;
}
} else {
Expand Down

0 comments on commit b9abee1

Please sign in to comment.