【发布时间】:2016-09-04 14:41:04
【问题描述】:
我在嵌入式系统(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 “将代码放在任何你想要的地方,但是,相信我它实际上会从 {这里} 执行”
虽然我的代码位于 0x40101388(GCC 决定),但它最终会驻留在 0x40100050 并执行。我如何通过告诉它“将代码放在这里”来欺骗 GCC,但假装它位于“这里”
编辑:我能够解决这个问题,事实证明,我需要修改的函数单独保存在链接描述文件中。我能够在链接器脚本中将其切换出来。虽然我仍然很想知道答案,但我现在有一个变通办法。
【问题讨论】:
-
gcc 或 gas 不会重定位任何代码。它们不是链接器。而 relative 跳转根据定义是与位置无关的。不清楚你的问题是什么(以及“在另一个符号中间”是什么意思)。请参阅How to Ask,提供足够的信息。
-
您可以在
as中定义一个特定的符号,即出现在代码中的某处。链接器无法重新定位,但我不知道为什么。在我的测试中,您似乎可以重新定位完全独立的符号,例如函数,但如果它在函数中间看到某些东西,它就不会重新定位。不知道为什么。 -
您的第一段没有意义,但是如果我忽略了这一点,那么您可以通过将要复制的代码放在它自己的部分中,然后使用链接器脚本告诉它将被复制到的链接器。看来 Linux 内核确实可以看到lxr.free-electrons.com/source/arch/xtensa/kernel/vmlinux.lds.S 中的
SECTION_VECTOR宏 -
你不能修改向量表以指向你的符号吗?我觉得很奇怪,你可以在
0x40100050复制一些东西而不会造成某种损害,但你不能直接在可执行文件中指定它的内容。或者0x40100050是否有系统/默认代码,您的代码稍后会在其他地方加载?由于 jmp/call 是相对的,只要将所需的所有代码复制到0x40100050,它就应该可以正常工作。在旧的汇编器中,有org指令来生成为特定地址设计的机器代码,但在as中,.org更复杂(我认为它对你没有帮助)。 -
我还是没抓住重点,你的问题是什么。 1)由于您的所有代码都是相对的,您可以将其全部复制到
0x40100050(除非它太长而无法放在那里)。 2)0x40100050来自哪里?不是来自某个向量处理程序表吗?那么你为什么不修改表在你的地址设置新的处理程序,忘记0x40100050? 3) 如果您将该处理程序放入单独的.section并修改链接脚本以将该部分放在0x40100050中,可以吗?那部分代码也是从闪存中获取的吗?等等......你的问题是call0 4010258c吗?然后也复制该代码。
标签: c gcc assembly relocation