-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backtraces in Rust on ESP-IDF #76
Comments
I have some experience with backtraces on In the |
As usual, I can't reproduce it when I need it. But I do have some screenshots from when it used to happen. By the way, another problem that I see way too often (even right now) is "corrupted" backtraces, where the bottom part of the backtrace is not available, because the stack is "corrupted". Well, I'm pretty sure there is nothing corrupted there, because the threads are running with 10K+ stack sizes, which leads me to believe that the Xtensa backtracing algorithm is simply not very reliable, especially with Rust.
But the problem is not at all how to get a backtrace on panics. At least, not with ESP-IDF that is, as the panics are handled by ESP-IDF automatically, and it dumps either a backtrace (Xtensa) or stack memory (RiscV). The problem is how to implement - programmatically - a backtracing (or stack dump actually) on demand for RiscV, as that functionality is not available. For stack dump, might be as simple as:
However, the above ideally should be an ESP-IDF API. |
And the other problem is whether the "stack memory dump" is the way forward for RiscV, and whether it will remain just a binary dump of stack memory, or whether it will be wrapped in an elf coredump executable first. The latter would allow Espressif folks to get rid of the "GDB server" approach - if you look at what they are doing with the stack memory dump in the ESP IDF monitor... |
@igrr ^^^ |
I think there are basically 3 options for this on RISC-V:
On Xtensa things are a lot easier since the ABI guarantees we can always find the previous frame, provided that no funny things like exceptions interrupt the call stack. And even then, if the exception/interrupt handler is careful enough in creating a frame on the stack, the backtrace can continue. |
Might be an option indeed, need to try out and see how much the size grows. Was hoping we won't get there.
By "GDB server" I meant this hack actually, where the app outputs either a raw stack memory dump (then the GDB server hack is necessary) or the app outputs an elf-encoded coredump which contains only one elf section - the one that contains the stack memory of the freertos task that panicked/programmatically requested the stack dump.
This implies that Rust code also needs to be compiled with What is more worrying is this GCC bug report which seems to imply that
In theory, yes. In practice, I often see partial stack frames where the bottom of the stack is lost with the infamous |
There's not much of an algorithm, really — get the SP from the current frame, use it to read the next frame, repeat until finished. Regarding the Rust compiler creating proper frames — I don't know, I was hoping that would handled by LLVM. If you manage to find a reproducer, please share it and I'll take a look. |
Might be difficult as Rust is involved, but here it goes:
Partial backtraces in debug:
Missing are the stackframes from Rust Partial backtraces + ghost frames in release:
|
Background:
Rust has a very useful utility called backtraces. Unlike Rust panics which are an abnormal situation - but still unwind the stack on big iron; for embedded, usually the panic_abort strategy is chosen -
backtraces are invoked programmatically, and allow one to capture programmatically and possibly display the stack of the thread which invoked the backtracing logic.
Usually, this is used in combination with Rust error handling, where some of the error libs, like the popular anyhow crate can be instructed to capture backtraces on first
anyhow
error construction.(Backtrace capturing is not (yet?) enabled for standard Rust STD error types though.)
Enhancement:
Ideally, we should be working on filing a PR against the backtrace-rs Rust crate (also used as a GIT submodule in Rust STD) to support IP-based backtraces under ESP-IDF. (While symbolization of backtrace IP pointers to function names and source file directly by the ESP-IDF flashed firmware is not practical due to size constraints, these can be decoded later with UART monitor filter that has access to the ELF file.)
Couple of issues with that:
esp_backtrace_get_start
andesp_backtrace_get_next_frame
, the logic seems to capture "ghost" Rust IPs, which surely do not belong to the current call stack. Could it be that these are only reliable for C/GCC-generated code?eh_frame
-based ESP-IDF configuration is advised not to be used in production due to huge code size of the flash binary)The text was updated successfully, but these errors were encountered: