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

How do I specify manual relocation for GCC code?

我在嵌入式系统(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 为 "put the code wherever you feel like, but, trust me it will actually execute from {here}"

尽管我的代码位于 0x40101388(GCC 决定),但它最终将从 0x40100050 驻留并执行。我如何通过告诉它 "put the code HERE" 来欺骗 GCC 但假装它位于 "HERE"

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

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

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

例如以下 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) ;
  ...
}

应该做你想做的。