Using GNU ld, how can I force the address of a specific (external) symbol without getting a "relocation truncated" error?

StackOverflow https://stackoverflow.com/questions/16462044

문제

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top