2009-06-03 82 views
10

我已经用C++编写了一个“危险的”程序,它从一个栈帧来回跳转到另一个栈帧。目标是从呼叫堆栈的最低级别跳转到呼叫者,做一些事情,然后再次跳回,每次跳过所有呼叫。PIC寄存器(%ebx)是做什么的?

我通过手动改变堆栈基地址(设定%ebp)和跳跃到一个标签地址做到这一点。它完全有效,与gcc和icc都没有任何堆栈腐败。这一天的工作是一个很酷的一天。

现在,我采取同样的程序,并用C重写它,这是行不通的。具体来说,它不适用于gcc v4.0.1(Mac OS)。一旦我跳到新的堆栈帧(堆栈基址指针设置正确),就执行以下指令,就在调用fprintf之前。这里列出的最后一条指令崩溃,取消引用NULL:

lea 0x18b8(%ebx), %eax 
mov (%eax), %eax 
mov (%eax), %eax 

我做了一些调试,我已经想通了,通过手动设置%ebx寄存器当我切换堆栈帧(使用我离开之前观察到的值功能在第一位),我修复了这个错误。我读过这个注册处理gcc中的“位置独立代码”。

什么是位置无关的代码?位置独立代码如何工作?这个寄存器指向什么?

+0

您可以考虑使用setjmp/longjmp直接获取此功能而不用直接使用%ebx。 – 2009-06-04 22:57:52

+2

一般来说,是的,你是对的。 在这种情况下,我需要能够跳转到调用者,执行其他功能,然后跳回到被调用者。使用setjmp/longjmp,被调用者的堆栈将被另一个函数覆盖。 – 2009-06-09 16:16:21

回答

6

PIC是它被加载时被动态地重新定位代码。非PIC的代码具有在链接时设置的跳转和呼叫地址。 PIC有一个引用所有这些值存在的地方的表,很像.dll。

加载图像时,加载程序将动态更新这些值。其他方案引用定义“基础”的数据值,并通过在基础上执行计算来决定目标地址。基地通常由装载机再次设置。

最后,其他方案使用调用已知相对偏移各种蹦床。相对偏移量包含由加载器更新的代码和/或数据。

为什么选择不同的方案有不同的原因。有些运行速度很快,但加载速度较慢。有些加载速度很快,但运行时性能较差。

相关问题