【发布时间】:2016-03-31 17:23:33
【问题描述】:
我对组装比较陌生,并且正在使用 powerpc 芯片。我正在使用 gcc 交叉编译器并使用 buildroot 环境(仅用于背景)。
我正在向一些代码的 .head 部分添加代码,这些代码将创建一个 .elf 对象(为了参数,我们将其称为 target.elf),该对象将通过 buildroot 引入一个更大的二进制文件。 target.elf 被定义为从代码和本地链接器中的地址 0x0 开始,但稍后将移动到不同的地址位置。我希望从汇编代码中引用一个在汇编代码和 c 文件之间共享的全局变量。当我使用与位置无关的方式这样做时,我会遇到问题。当我使用 GOT 作为参考时(例如,symbol@got@h),我能够正确引用该符号。
这是一个问题,因为我希望创建一个中断处理程序,它不依赖于在进入时具有指向堆栈或 TOC 的有效指针,并且我需要 TOC 才能使用 GOT。
有没有办法在没有 TOC 的情况下做到这一点?
下面是一些示例代码:
不正确的结果(%r3 不包含“符号”包含的内容):
.global symbol
symbol:
.long 0
.global irq_handler
irq_handler:
addi %r3, 0, 0
ori %r3, %r3, symbol@l
ld %r3, 0(%r3)
b .
In global area of C-file:
extern uint64_t symbol;
我还尝试在 c 文件中定义符号(因此没有 extern 但仍然是全局的)并省略了 asm 文件中的定义。这也失败了。
我也采取了捷径,只加载地址的@l 部分,因为前 32 位是 0x0。
正确的结果(%r3 确实包含“符号”所包含的内容):
.global irq_handler
irq_handler:
ld %r3, symbol@got(%r2)
ld %r3, 0(%r3)
b .
请注意,在正确的示例中,TOC 在 %r2 中可用。
提前谢谢你。
【问题讨论】:
-
我不明白你怎么能拥有“不依赖于指向堆栈的有效指针的中断处理程序”
-
中断处理程序提供了一种分支到不同上下文的方法。对于这种情况,我将在分支到新上下文之前将当前上下文(寄存器)备份到已知位置。当我返回时,寄存器将处于未定义状态。当 irq 再次触发时,我将恢复原始上下文,但希望在恢复 TOC 之前引用“符号”。中断处理程序也处理其他功能,但不涉及太多细节。
-
对上述评论的澄清:再次调用相同的中断处理程序有助于从其他上下文返回。再次调用时,寄存器处于未知状态,检查“符号”后将恢复。
-
中断例程需要用自己的 TOC 库加载 R2。通常,ELF PowerPC ABI 要求函数的调用者将 R2 设置为被调用函数的 TOC 基值。显然,中断不会发生这种情况。用于设置 R2 的代码使用调用函数的 TOC,因此您不能只复制该代码,因为通常中断例程无法知道其“调用者”正在使用什么 TOC(如果有)。您可以查看 Linux 或其他 PowerPC 内核在其中断例程中的作用。
-
谢谢。我手头有一个内核供参考,并且一直在使用它。我有一些解决方法的想法,但我想我希望如果我遗漏了一些东西并且我不需要这里的 TOC,我可以做一些更清洁的事情。但听起来对于会移动的代码,我需要 TOC 来定位“符号”。非常感谢。