linux 全局抵销表:“指针到指针”?这是由加载程序处理的吗?

hgqdbh6s  于 2023-01-25  发布在  Linux
关注(0)|答案(1)|浏览(85)

这个问题是关于Linux(Ubuntu)可执行文件的。
我将详细说明我所理解的事情,以便更清楚地了解是否有任何问题(因此,请在适用的地方纠正我):
GOT充当额外级别的间接,以允许从需要与位置无关的文本部分访问数据,例如,因为文本部分可能是只读的,并且数据的实际地址在(静态)链接时可能是未知的。
然后GOT保存实际数据位置的地址,这在加载时是已知的,因此动态链接器(由加载器调用)能够修改适当的GOT条目并使它们指向实际数据。
最让我困惑的是--提醒你一下,这不是目前唯一的困惑:-)--这意味着文本部分中的地址现在指向一个"不同类型"的值:
如果没有GOT,我会期望这个地址(例如在RIP相对寻址模式下)指向我所要查找的实际值。但是,如果有GOT,我期望它指向适当的GOT条目,该条目依次保存我所要查找的值的地址。在这种情况下,这里需要一个额外的"解引用"。
我是不是误解了这一点?如果我使用RIP相对寻址,计算出的地址(RIP+偏移量)不应该是指令中使用的实际地址吗?因此(在AT & T语法中):

mov $fun_data(%rip), %rax

据我所知,如果没有GOT,这应该是"rax = *(rip + (fun_data - rip))",或者简而言之:rax = *fun_data.
但是,对于GOT,我希望它与rax = **fun_data等价,因为*fun_data只是 * real * fun_data的GOT条目。
我是不是搞错了,或者只是因为加载器知道如果指针指向GOT,就访问实际数据?(换句话说:我想,在PIE中,一些指针实际上变成了指针对指针?)

xu3bshqb

xu3bshqb1#

我说错了吗
没有。
或者仅仅是因为加载程序知道如果指针指向GOT就访问真实的数据?

  • 编译器 * 知道需要双重解引用。

使用和不使用-fPIC编译此源代码,并亲自观察:

extern int dddd;
int fn() { return dddd; }

如果不使用-fPIC,您将获得(预期):

movl    dddd(%rip), %eax

使用-fPIC可以实现“双重解引用”:

movq    dddd@GOTPCREL(%rip), %rax   # move pointer to dddd into RAX
movl    (%rax), %eax                # dereference it

相关问题