简体   繁体   English

全局偏移表:“指向指针的指针”? 这是由加载程序处理的吗?

[英]Global Offset Table: "Pointers to Pointers"? Is this handled by the loader?

This question is about Linux (Ubuntu) executables.这个问题是关于 Linux (Ubuntu) 可执行文件的。

I'll detail things as I understand them to make it clearer if anything's off (so please correct me where applicable):我会按照我的理解详细说明,以便更清楚地了解是否有任何问题(因此请在适用的地方纠正我):

The GOT acts an extra level of indirection to enable accessing data from a text section which needs to be position-independent, for instance because the text section might be readonly and the actual addresses of the data may be unknown at (static) linking time. GOT 充当额外的间接级别以允许从需要与位置无关的文本部分访问数据,例如因为文本部分可能是只读的并且数据的实际地址在(静态)链接时可能是未知的。
The GOT then holds addresses to the actual data's location, which is known at loading time, and so the dynamic linker (which is invoked by the loader) is able to modify the appropriate GOT entries and make them point to the actual data. GOT 然后保存实际数据位置的地址,这在加载时是已知的,因此动态 linker(由加载程序调用)能够修改适当的 GOT 条目并使它们指向实际数据。

The main thing that confuses me – not the only one at the moment, mind you:-) – is that this means the addresses in the text section now point to a value "of a different type":让我感到困惑的主要事情——不是目前唯一的事情,请注意:-)——这意味着文本部分中的地址现在指向“不同类型”的值:
If there was no GOT, I'd have expected this address (for instance in a RIP-relative addressing mode) to point to the actual value I'm after.如果没有 GOT,我会期望这个地址(例如在 RIP 相对寻址模式下)指向我所追求的实际值。 With a GOT, though, I expect it to point to the appropriate GOT entry, which in turn holds the address to the value I'm after.但是,对于 GOT,我希望它指向适当的 GOT 条目,该条目又将地址保存为我所追求的值。 In this case, there's an extra "dereferencing" required here.在这种情况下,这里需要额外的“取消引用”。

Am I somehow misunderstanding this?我是否以某种方式误解了这一点? If I use RIP-relative addressing, shouldn't the computed address (RIP+offset) be the actual address used in the instruction?如果我使用 RIP 相对寻址,计算出的地址(RIP+偏移量)不应该是指令中使用的实际地址吗? So (in AT&T syntax):所以(在 AT&T 语法中):

mov $fun_data(%rip), %rax

To my understanding, without GOT, this should be " rax = *(rip + (fun_data - rip)) ", or in short: rax = *fun_data .据我了解,如果没有 GOT,这应该是“ rax = *(rip + (fun_data - rip)) ”,或者简而言之: rax = *fun_data
With GOT, however, I expect this to be equivalent to rax = **fun_data , since *fun_data is just the GOT entry to the real fun_data.但是,对于 GOT,我希望这等同于rax = **fun_data ,因为*fun_data只是真正fun_data 的 GOT 条目。

Am I wrong about this, or is it just that the loader somehow knows to access the real data if the pointer is into the GOT?我是不是错了,或者只是如果指针进入 GOT,加载程序就知道如何访问真实数据? (In other words: that in a PIE, I suppose, some pointers effectively become pointers-to-pointers?) (换句话说:我想在 PIE 中,一些指针实际上变成了指向指针的指针?)

Am I wrong about this我错了吗

No.不。

or is it just that the loader somehow knows to access the real data if the pointer is into the GOT?或者如果指针指向 GOT,加载程序是否知道访问真实数据?

The compiler knows that double dereference is required.编译器知道需要双重解引用。

Compile this source with and without -fPIC and observe for yourself:使用和不-fPIC编译此源代码并自行观察:

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

Without -fPIC , you get (expected):没有-fPIC ,你会得到(预期):

movl    dddd(%rip), %eax

With -fPIC you get "double dereference":使用-fPIC你会得到“双重取消引用”:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM