Do lazy PLT entries need a R_X86_64_RELATIVE?

Programming, for all ages and all languages.
Post Reply
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Do lazy PLT entries need a R_X86_64_RELATIVE?

Post by nullplan »

I suggest you read the System V ABI, AMD64 processor supplement, as it holds answers to some of your questions. But to be specific:

1. The first entry should be set to the address of the dynamic section, such as you know. For an executable, this will be the address in memory where it is loaded, and for a DSO this will be the offset from the start. The second and third entry should be empty (i.e. set to 0).

2. The relocation type for PLTGOT entries is R_X86_64_JUMP_SLOT. Here, it is helpful to read other implementations that already did this. dietlibc is the simplest libc I know that implements lazy binding, and it was a helpful read. So how this is supposed to work is like this: The dynamic section contains two relocation table definitions. The relocations defined with DT_REL, DT_RELENT, and DT_RELSZ are processed immediately, including symbol lookup, if needed. The other table, defined by DT_JMPREL, DT_PLTREL, and DT_PLTRELSZ is only rebased to the new membase, unless the LD_NOW flag is set, in which case each entry is immediately looked up.

3. Apparently yes, they are completely different tables.

Oh, and one more thing:
mariuszp wrote:But I saw some code somewhere which claimed an undocumented case where "pre-linking" (not sure what is meant by it) is indicated by pre-setting PLTGOT[1] to a nonzero value.
I'd wager this is a by-now unsupported GNU extension. Windows has some support for this, and on i386 it might have made sense. "Pre-linking" refers to linking a library with a non-zero base address. The idea is to try to layout all the shared libs in the system such that no relocation is necessary because the space will always be unused at first. Of course this doesn't work in any non-trivial case (such as LD_PRELOAD), because ELF has no notion of "importing" a function from a library. ELF only has dependencies and symbols that on their face have nothing to do with each other (the "hello world" program only declares its need for "libc.so", and then, mirabile dictu, somehow there's a "printf" symbol in the linkage. But there is no way to say "import printf from libc.so"). So the entire thing becomes incredibly fragile, and you have to relocate your libraries anyway if anything happened at all. If any lib moved, they all have to be relocated. And again, LD_PRELOAD is a thing.

And another thing I had overlooked before:
mariuszp wrote:2. Every other entry in the PLTGOT (the number of these "other" entries == the number of PLTRELA relocation entries) contains the address of the corresponding PLT entry (before it is loaded by the dynamic linker)
They should contain the offset to 6 bytes into their PLT offset. Otherwise you're currently building an infinite loop.
Carpe diem!
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Do lazy PLT entries need a R_X86_64_RELATIVE?

Post by nullplan »

Correct, the base address is added to the PLTGOT slots, but only because they are in DT_JMPREL, not because of a R_foo_RELATIVE relocation.
Carpe diem!
Post Reply