如何为GCC代码指定手动重定位?

时间:2016-08-12 00:45:11

标签: c gcc assembly relocation

我处于嵌入式系统(xtensa处理器)中的情况,我需要手动覆盖符号,但符号恰好位于另一个符号的中间。当我尝试使用-Wl,--wrap=symbol时,它将无效,因为符号不是它自己的东西。

我需要做的是指定代码最终会指定(最好在GCC .S中,但.c没问题)。虽然编译器会将实际符号放在某处,但我会memcpy将代码放到正确的位置。

40101388 <replacement_user_vect>: 40101388: 13d100 wsr.excsave1 a0 4010138b: 002020 esync 4010138e: 011fc5 call0 4010258c <_UserExceptionVector_1>

我的问题是GCC创建具有相对跳转的程序集,假设代码将位于闪存中,而最终位置将在中断向量中修复。我如何告诉GCC / GNU“将代码放在任何你想要的地方,但相信我它实际上会从{here}执行”

虽然我的代码是0x40101388(GCC决定)但它最终会驻留并执行0x40100050。如何通过告诉它“将代码放在这里”来欺骗GCC,但假装它位于“HERE”

编辑:我能够解决这个问题,因为事实证明,我需要修改的函数分别保存在链接描述文件中。我能够在链接器脚本中将其切换出来。虽然我仍然想知道答案,但我现在有一个解决办法。

1 个答案:

答案 0 :(得分:3)

在链接描述文件中,每个输出部分都有两个相关的地址:VMA和LMA - 代码链接的地址和代码加载的地址。

将需要重新定位的代码放入单独的部分,使用所需的VMA和LMA将输出部分添加到链接描述文件中,并将输入部分与其中的代码部分名称相匹配。

E.g。以下C代码

void f(void) __attribute__((section(".relocatable1.text")))
{
    ...
}

extern char _relocatable1_lma[];
extern char _relocatable1_vma_start[];
extern char _relocatable1_vma_end[];

void relocatable1_copy(void)
{
        memcpy(_relocatable1_vma_start, _relocatable1_lma,
               _relocatable1_vma_end - _relocatable1_vma_start);
}

与下面的ld脚本一起使用VMA替换为所需的目标代码位置

SECTIONS {
  ...
  .some_section : { ... }
  .relocatable1 VMA : AT(LOADADDR(.some_section) + SIZEOF(.some_section)) {
    _relocatable1_vma_start = . ;
    *(.relocatable1.literal .relocatable1.text) ;
    _relocatable1_vma_end = . ;
  }
  _relocatable1_lma = LOADADDR(.relocatable1) ;
  ...
}

应该做你想做的事。