From 13174b030367a772e83d9a5a991a7c1f091ca230 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 21 May 2024 14:35:11 +0000 Subject: [PATCH 1/3] Add link_section = ".HardFault.user" to _HardFault Without that link_section, I get the following error when using a HardFault handler with trampoline enabled: ``` error: linking with `rust-lld` failed: exit status: 1 | = note: LC_ALL="C" PATH="/home/jan/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/jan/bin:/home/jan/.local/bin:/home/jan/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" VSLANG="1033" "rust-lld" "-flavor" "gnu" "/tmp/rustco5o3sY/symbols.o" "/tmp/hf/target/thumbv6m-none-eabi/release/deps/hf-60e327b1df262da6.hf.b796e35f6a1db46-cgu.0.rcgu.o" "--as-needed" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/deps" "-L" "/tmp/hf/target/release/deps" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/build/hf-ff0c4c84ae595cf3/out" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/build/cortex-m-a49cc6d3fe1b56bb/out" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/build/cortex-m-rt-92c9f0977947feec/out" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/build/defmt-f49fb1c33a63ef3f/out" "-L" "/tmp/hf/target/thumbv6m-none-eabi/release/build/rp2040-pac-b75ed87cecd188ac/out" "-L" "/home/jan/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "-Bstatic" "/tmp/rustco5o3sY/libcortex_m-e77ad2852f31030c.rlib" "/home/jan/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcompiler_builtins-94a92625991d7a16.rlib" "-Bdynamic" "--eh-frame-hdr" "-z" "noexecstack" "-L" "/home/jan/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "-o" "/tmp/hf/target/thumbv6m-none-eabi/release/deps/hf-60e327b1df262da6" "--gc-sections" "-O1" "--nmagic" "-Tlink.x" "-Tdefmt.x" = note: rust-lld: error: /tmp/hf/target/thumbv6m-none-eabi/release/deps/hf-60e327b1df262da6.hf.b796e35f6a1db46-cgu.0.rcgu.o:(function HardFault: .HardFault.user+0xc): relocation R_ARM_THM_JUMP11 out of range: -7055 is not in [-2048, 2047]; references '_HardFault' >>> referenced by hf.b796e35f6a1db46-cgu.0 >>> defined in /tmp/hf/target/thumbv6m-none-eabi/release/deps/hf-60e327b1df262da6.hf.b796e35f6a1db46-cgu.0.rcgu.o ``` This commit also moves the trampoline from .HardFault.user to .HardFaultTrampoline. This is not strictly necessary, but is consistent with previous (cortex-m-rt <= 0.7.3) usage. Alternatively, `*(.HardFaultTrampoline)` could be removed from link.x. --- cortex-m-rt/macros/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cortex-m-rt/macros/src/lib.rs b/cortex-m-rt/macros/src/lib.rs index 04774051..be4dcf3d 100644 --- a/cortex-m-rt/macros/src/lib.rs +++ b/cortex-m-rt/macros/src/lib.rs @@ -368,6 +368,10 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { #(#attrs)* #[doc(hidden)] #[export_name = "_HardFault"] + // Only emit link_section when building for embedded targets, + // because some hosted platforms (used to check the build) + // cannot handle the long link section names. + #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] unsafe extern "C" fn #tramp_ident(frame: &::cortex_m_rt::ExceptionFrame) { #ident(frame) } @@ -379,7 +383,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { // Depending on the stack mode in EXC_RETURN, fetches stack from either MSP or PSP. core::arch::global_asm!( ".cfi_sections .debug_frame - .section .HardFault.user, \"ax\" + .section .HardFaultTrampoline, \"ax\" .global HardFault .type HardFault,%function .thumb_func From b3edd1565281077c8260481b22deff901d0192b5 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 21 May 2024 20:00:56 +0000 Subject: [PATCH 2/3] Add test case for proper placement of hard fault handler and trampoline --- cortex-m-rt/examples/hard-fault-trampoline.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 cortex-m-rt/examples/hard-fault-trampoline.rs diff --git a/cortex-m-rt/examples/hard-fault-trampoline.rs b/cortex-m-rt/examples/hard-fault-trampoline.rs new file mode 100644 index 00000000..995e7ce2 --- /dev/null +++ b/cortex-m-rt/examples/hard-fault-trampoline.rs @@ -0,0 +1,31 @@ +//! This is not an example; this is a linker test that ensures +//! that the jump from HardFault to _HardFault doesn't exceed +//! the 2kB limit of the branch instruction. + +#![deny(warnings)] +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate panic_halt; + +use core::arch::asm; +use cortex_m_rt::{entry, exception, ExceptionFrame}; + +// This defines both `HardFault` and `_HardFault`. Both should have +// link_section attributes placing them at the end of the .text section, +// close to each other. If one of them is missing that attribute, they +// will end up separated by `foo`, which will make the linker fail. +#[exception(trampoline = true)] +unsafe fn HardFault(_ef: &ExceptionFrame) -> ! { + loop {} +} + +#[entry] +fn foo() -> ! { + unsafe { + // 2kB of NOP instructions to make the function artificially larger + asm!(".fill 1024,2,0xbf00",); + } + loop {} +} From 94bd9c8b08f4962085fa72e85e0069c0fa2e90e3 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 21 May 2024 20:12:22 +0000 Subject: [PATCH 3/3] Actually test hard-fault-trampoline in CI --- cortex-m-rt/ci/script.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh index 60e88d7d..713121c7 100755 --- a/cortex-m-rt/ci/script.sh +++ b/cortex-m-rt/ci/script.sh @@ -21,6 +21,7 @@ main() { divergent-default-handler divergent-exception entry-static + hard-fault-trampoline main minimal override-exception