HardFaultTrampoline, relocation R_ARM_THM_JUMP11 out of range
Closed this issue · 5 comments
On a Cortex-M0 running Hubris OS with link time optimizations temporarily disabled for debugging, I find linking often fails with the following:
= note: rust-lld: error: /target/thumbv6m-none-eabi/release/deps/libcortex_m_rt-30b54eec0d9b4b99.rlib(cortex-m-rt.o):(function HardFaultTrampoline: .HardFaultTrampoline+0xc): relocation R_ARM_THM_JUMP11 out of range: -5547 is not in [-2048, 2047]; references 'HardFault'
I suppose this is why the Trampolines were made optional.
Is any guidance available for this issue. I believe there are two paths: either disabling the trampolines (I'm not sure what effect that has) or manually coaxing the linker into placing sections closer together?
looking at the source:
cortex-m/cortex-m-rt/macros/src/lib.rs
Line 387 in 9177271
I guess I could fork the library and maybe try to edit the assembly to work around the usage of the B instruction (BX would work better although it modifies the return address). Although that is a bit of a pain.
What linker script are you using? In the one provided with cortex-m-rt, HardFaultTrampoline should always come immediately before HardFault for this specific reason, so I'm not sure what's going wrong here - maybe a different linker script or maybe some new bug in cortex-m-rt that's causing the functions to not go into the correct sections?
cortex-m/cortex-m-rt/link.x.in
Lines 102 to 105 in 9177271
I'm using https://github.com/oxidecomputer/hubris/blob/master/build/kernel-link.x
It appears to do what is shown in your example
/* ### .text */
.text _stext :
{
__stext = .;
/* place these 2 close to each other or the `b` instruction will fail to link */
*(.PreResetTrampoline);
*(.Reset);
*(.text .text.*);
/* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`,
so must be placed close to it. */
*(.HardFaultTrampoline);
*(.HardFault.*);
. = ALIGN(4);
__etext = .;
} > FLASH
However, disabling link time optimizations does reproduce the issue 80% of the time, at least on my project.
When I dump the symbols for a build with optimizations enabled, I notice that HardFaultTrampoline is placed after HardFault.
$ nm -C kernel | grep -i hard
080060cd T HardFault
0800673b T HardFaultTrampoline
I wonder if it is possible that the certain linker expressions might be capturing either more or less than expected?
I think the script is trying to place HardFaultTrampoline before HardFault, yet when I compile it gets placed after. Which makes it sensitive to size and vulnerable to failing when optimizations are disabled.
edit: I fiddled with the linker script with no success, hard to debug "which lines are pulling in what"
Which version of cortex-m-rt is this? With 0.7.5, there should not be a symbol called HardFaultTrampoline. The symbol that's getting placed in section .HardFaultTrampoline is called HardFault:
core::arch::global_asm!(
".cfi_sections .debug_frame
.section .HardFaultTrampoline, \"ax\"
.global HardFault
.type HardFault,%function
.thumb_func
.cfi_startproc
HardFault:",
I guess it may be 0.6.12, as that's the version referenced by https://github.com/oxidecomputer/hubris/blob/master/Cargo.toml?
And then, which version of hybris are you using?
This relatively recent change seems to be relevant:
oxidecomputer/hubris@134b7d7#diff-f5c9d3c68205bc09ad754c71a08e8892e47c9e25af57e32de4a143864b999607
It places the HardFault symbol defined in sys/kern/src/arch/arm_m.rs at the right location. Without that, it'll be thrown somewhere into the .text section.
Closing because I just realized I am using an out of date version!
I need to investigate this after I go through the process of getting the project up to date.