-
Notifications
You must be signed in to change notification settings - Fork 167
add virtual unwind info (.debug_frame / CFI) to external assembly #215
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
Comments
Having interacted with that code I would strongly suggest you not rely on it but rather use the CFI directives. There's nothing more unpleasant than debugging your debugger when it becomes confused by an especially strange stack frame and either gets lost or crashes. (Though I guess the problem might be less acute on ARMv7 than on OR1K.) |
Other crates with external assembly: |
216: Add unwind information to external assembly r=jonas-schievink a=Tiwalun Add unwind information to the external assembly files, as discussed in #215. The `.debug_frame` section is now present: ``` cortex-m.o (ex bin/thumbv6m-none-eabi.a): section size addr .text 0x0 0x0 .data 0x0 0x0 .bss 0x0 0x0 .text.__bkpt 0x4 0x0 .text.__control_r 0x6 0x0 .text.__control_w 0x6 0x0 .text.__cpsid 0x4 0x0 .text.__cpsie 0x4 0x0 .text.__delay 0x8 0x0 .text.__dmb 0x6 0x0 .text.__dsb 0x6 0x0 .text.__isb 0x6 0x0 .text.__msp_r 0x6 0x0 .text.__msp_w 0x6 0x0 .text.__nop 0x2 0x0 .text.__primask 0x6 0x0 .text.__psp_r 0x6 0x0 .text.__psp_w 0x6 0x0 .text.__sev 0x4 0x0 .text.__udf 0x2 0x0 .text.__wfe 0x4 0x0 .text.__wfi 0x4 0x0 .debug_line 0x161 0x0 .debug_info 0x22 0x0 .debug_abbrev 0x12 0x0 .debug_aranges 0xb0 0x0 .debug_str 0x30 0x0 .debug_ranges 0xa8 0x0 .debug_frame 0x140 0x0 .ARM.attributes 0x1c 0x0 Total 0x4d9 ``` Co-authored-by: Dominik Boehi <[email protected]>
@japaric Regarding the psp_w and msp_w functions: I'm not sure if it is possible to properly unwind after overwriting the stack pointer, |
The functions that overwrite the stack pointer should probably use |
This interacts with #259 – I've removed all the directives there, since rustc should generate them automatically for all Rust functions. But I don't know if that can see through inline assembly and emit unwind info for individual instructions in there. |
423: Swap to just-stabilised asm!() and global_asm!() macros r=thejpster a=adamgreig Once Rust 1.59 is released in a couple of days, the `asm!()` and `global_asm!()` macros will become stable, and we will no longer require the various precompiled binaries we've used until now in cortex-m and cortex-m-rt. cc #420. This PR uses `asm!()` in cortex-m, and removes the inline-asm feature, since I anticipate this going into cortex-m 0.8 and so we don't need to leave it behind for compatibility. In various places the previous version would call an extern C method when built for the native target, which would only fail at link time; to preserve the ability to build on x86 I've either made the whole method require the `cortex_m` configuration, or where appropriate/convenient simply skipped the `asm!()` call. This PR replaces the old gcc-preprocessed `asm.S` in cortex-m-rt with use of `global_asm!()`, although since you can't normally use `#[cfg(...)]` attributes with `global_asm!()`, there's also a slightly scary macro modified from one invented by `@Dirbaio` for a similar purpose. I considered putting the initialisation of LR behind an armv6m flag, but since we want to restore it after calling `__pre_init` it seemed better to just leave it the same on both targets. I added Cargo features to optionally set SP and VTOR at startup, which has been variously requested but would previously have required multiplicatively more pre-built binaries. Now: no problem. Relevant issues: * rust-embedded/cortex-m-rt#283 * rust-embedded/cortex-m-rt#55 * rust-embedded/cortex-m-rt#254 * rust-embedded/cortex-m-rt#102 * rust-embedded/cortex-m-rt#338 I've tested these on a couple of targets (and updated the CI): on the whole there's a small improvement in code size due to everyone getting inlined asm, especially in `cortex_m::interrupt::free()`. The major downside is we bump our MSRV from 1.42 (March 2020) to 1.59 (Feb 2022). For cortex-m, I propose putting these changes in the upcoming 0.8 release (which is technically what the master branch is already on) and not backporting. For cortex-m-rt I'm not sure: we don't have any other pending breaking changes, so we could consider a patch release. Anyway, this PR doesn't commit to any particular releases, so we can decide that later. For cortex-m-semihosting/panic-semihosting I think a patch release would be ideal, especially since we had to yank the last c-m-sh release due to conflicting prebuilt binaries (a problem that should now vanish). Also tagging these issues that I think might also benefit from new inline asm: * #265 * #215 * #406 Co-authored-by: Adam Greig <[email protected]>
virtual unwinders (*), for example based on
gimli::{DebugFrame,UnwindSection}
, are not able to unwind through external assembly subroutines like__nop
because these subroutines lack CFI (Call Frame Information), which -- when present -- gets encoded in the.debug_frame
(**) section of the ELF.For subroutines that do not touch the stack pointer or link register adding CFI with no register rules is sufficient to make virtual unwinding work. Adding that CFI looks like this:
And yeah
bx lr
does not count as "touching LR" because it does not modify LR.What needs to be done:
assemble.sh
. Some instructions that do modify SP / LR arepush
,pop
,stmia
,ldmia
,mov
/msr
where SP/LR is the destination (first argument) -- do not modify subroutines that contain those instructions (see "hard part" below)To test this part run the following command on the archives (
bin/*.a*
):You should see one "FDE" for each subroutine that now has CFI.
cortex_m_rt::HardFaultTrampoline
(*) GDB doesn't seem to require this info (
.debug_frame
) to print stack backtraces but GDB also contains a full blown disassembler so I guess it can figure out the missing info on its own(**) AFAIK, for proper stack unwinding, where stack frames are popped and destructors are called as the stack is unwound, one needs
.eh_frame
instead of.debug_frame
. But we are dealing withpanic=abort
targets (which also lack the other unwinding ingredient: "landing pads" big question mark) here so we don't need the "full" version (.eh_frame
).P.S.
cortex-m
is not the only crate that's missing this info.cortex-m-rt
,cortex-m-semihosting
, etc. also need these changes.The text was updated successfully, but these errors were encountered: