From 284b0666f09b779e4fc1e6553a74fde55fb1de3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Wed, 19 Mar 2025 16:21:29 +0100 Subject: [PATCH] Force spill registers to fix missing backtrace (#3272) --- esp-backtrace/CHANGELOG.md | 1 + esp-backtrace/src/xtensa.rs | 41 +++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/esp-backtrace/CHANGELOG.md b/esp-backtrace/CHANGELOG.md index eb6497de4..3cdd15195 100644 --- a/esp-backtrace/CHANGELOG.md +++ b/esp-backtrace/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Stack traces no longer stop at recursive functions (#3270) +- ESP32/S2/S3: Fixed an issue where the backtrace wasn't correctly captured in some cases (#3272) ### Removed diff --git a/esp-backtrace/src/xtensa.rs b/esp-backtrace/src/xtensa.rs index 071005622..f176cbf85 100644 --- a/esp-backtrace/src/xtensa.rs +++ b/esp-backtrace/src/xtensa.rs @@ -357,15 +357,40 @@ F15=0x{:08x}", } } -/// Get an array of backtrace addresses. -pub fn backtrace() -> [Option; MAX_BACKTRACE_ADDRESSES] { - let sp = unsafe { - let mut _tmp: u32; - asm!("mov {0}, a1", out(reg) _tmp); - _tmp - }; +/// This function returns the caller's frame pointer. +#[inline(never)] +#[cold] +fn sp() -> u32 { + let mut sp: u32; + unsafe { + asm!( + "mov {0}, a1", // current stack pointer + // Spill registers, otherwise `sp - 12` will not contain the previous stack pointer + "add a12,a12,a12", + "rotw 3", + "add a12,a12,a12", + "rotw 3", + "add a12,a12,a12", + "rotw 3", + "add a12,a12,a12", + "rotw 3", + "add a12,a12,a12", + "rotw 4", + out(reg) sp + ); + } - backtrace_internal(sp, 1) + // current frame pointer, caller's stack pointer + unsafe { ((sp - 12) as *const u32).read_volatile() } +} + +/// Get an array of backtrace addresses. +#[inline(never)] +#[cold] +pub fn backtrace() -> [Option; MAX_BACKTRACE_ADDRESSES] { + let sp = sp(); + + backtrace_internal(sp, 0) } pub(crate) fn remove_window_increment(address: u32) -> u32 {