I have two functions, a()
and b()
, that both have specific, fixed load/run-time addresses. I am compiling a()
myself, while b()
is already provided (e.g. in ROM).
The file a.c
is as follows:
extern void b(void);
void a(void) {
b();
}
This generates the following assembly code:
00000000 <a>:
0: 08000000 j 0 <a>
0: R_MIPS_26 b
4: 00000000 nop
So it's putting a 26-bit relocation to b()
there (the target of the call is a 26-bit offset from the address of the call instruction itself). Let's say the specific addresses of a
and b
are 0x80001000 and 0x80002000, respectively. That should be fine; b
is easily within reach of a
.
So in my linker script, I have something like this:
SECTIONS {
a = 0x80001000;
b = 0x80002000;
.text : AT(0x80000000) {
*(.text)
}
}
However, linking a.o
with this script gives me the following error:
a.o: In function 'a':
(.text+0x0): relocation truncated to fit: R_MIPS_26 against `b`
Presumably, this is because the linker is trying to fit the full 32-bit value (0x80002000
) into the 26-bit space for the target of the jump. What's wrong with my linker script?
Try to use the long_call
attribute:
__attribute__((long_call))
extern void b(void);
Manual for all MIPS attributes is here.