Home > Enterprise >  Global Offset Table: "Pointers to Pointers"? Is this handled by the loader?
Global Offset Table: "Pointers to Pointers"? Is this handled by the loader?

Time:01-21

This question is about Linux (Ubuntu) executables.

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.
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.

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. 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. 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? So (in AT&T syntax):

mov $fun_data(%rip), %rax

To my understanding, without GOT, this should be "rax = *(rip (fun_data - rip))", or in short: 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.

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? (In other words: that in a PIE, I suppose, some pointers effectively become pointers-to-pointers?)

CodePudding user response:

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?

The compiler knows that double dereference is required.

Compile this source with and without -fPIC and observe for yourself:

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

Without -fPIC, you get (expected):

movl    dddd(%rip),            
  • Related