使用GNU ld,如何强制使用特定(外部)符号的地址而不会出现“重定位截断”错误?

时间:2013-05-09 12:42:43

标签: mips linker-errors ld relocation linker-scripts

我有两个功能,a()b(),它们都具有特定的,固定的加载/运行时地址。我自己正在编译a(),而b()已经提供(例如在ROM中)。

文件a.c如下:

extern void b(void);

void a(void) {
    b();
}

这将生成以下汇编代码:

00000000 <a>:
   0:   08000000       j 0 <a>
                       0: R_MIPS_26 b
   4:   00000000       nop

所以它将26位重定位到那里b()(调用的目标是与调用指令本身的地址相差26位)。假设ab的具体地址分别为0x80001000和0x80002000。那应该没事; b很容易达到a

所以在我的链接器脚本中,我有类似的东西:

SECTIONS {
    a = 0x80001000;
    b = 0x80002000;

    .text : AT(0x80000000) {
        *(.text)
    }
}

但是,将a.o与此脚本相关联会产生以下错误:

a.o: In function 'a':
(.text+0x0): relocation truncated to fit: R_MIPS_26 against `b`

据推测,这是因为链接器试图将完整的32位值(0x80002000)拟合到跳转目标的26位空间中。我的链接器脚本出了什么问题?

1 个答案:

答案 0 :(得分:1)

尝试使用long_call属性:

__attribute__((long_call))
extern void b(void);

所有MIPS属性的手册均为here