References and excerpt from: http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ http://eli.thegreenplace.net/2011/11/11/position-independent-code-pic-in-shared-libraries-on-x64/ http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/ http://eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models/ http://eli.thegreenplace.net/2012/08/13/how-statically-linked-programs-run-on-linux/
ecx : Serves as a base pointer to GOT. e.g : 0x1ff4
a value is taken from [ecx - 0x10], which is a GOT entry, and placed into eax.
The address of myglob : ecx - 0x10 = 0x1fe4 = eax
eax: address of myglob. eax address : 0x1fe4.
library that uses myglob is pointed to here.
eax type: R_386_GLOB_DAT : put the actual value of the symbol
(i.e. its address) into that offset".
eax : the value of myglob is placed into eax.
--------
Function:
lazy binding optimization:
When a shared library refers to some function, the real address of that function
is not known until load time.
Lazy binding scheme is attained by adding yet another level of indirection – the PLT.
Procedure Linkage Table (PLT):
PLT is part of the executable text section, consisting of a set of entries.
(one for each external function the shared library calls)
Each PLT entry is a short chunk of executable code.
Instead of calling the function directly, the code calls an entry in the PLT,
which then takes care to call the actual function.
This arrangement is sometimes called a "trampoline".
Each PLT entry also has a corresponding entry in the GOT which contains the actual
offset to the function, but only when the dynamic loader resolves it.
When the shared library is first loaded, the function calls have not been resolved yet:
PLT[n] => GOT[n] , GOT[n] Has the function's address
PLT[0] is different from other entry. It's a call to a resolver routine,
which is located in the dynamic loader itself.
This routine resolves the actual address of the function.
-------
Flow:
First time call:
Text call function func: -> PLT[n] -> GOT[n] -> back to next address of PLT[n]'s
call to GOT[n], which is to prepare resolver -> PLT[0] , call dynamic loader,
prepare function address and place into GOT[n] -> calls the function.
Next time call:
Text call function func: -> PLT[n] -> GOT[n] -> calls the function.
------
Lazy symbol resolution performed by the dynamic loader can be configured with
some environment variables:
LD_BIND_NOW : always perform the resolution for all symbols at start-up time.
With GDB. You’ll see that the GOT entry for ml_util_func contains its real address even before the first call to the function.
LD_BIND_NOT : not to update the GOT entry at all.
More info:
man ld.so
------
The costs of PIC:
1. extra indirection required for all external references to data and code in PIC.
2. increased register usage required to implement PIC.
it makes sense for the compiler to generate code that keeps its address in a register
(usually ebx).
------
X64:
RIP-relative addressing:
New "RIP-relative addressing mode",the default for all 64-bit mov instructions that reference memory
(it’s used for other instructions as well, such as lea).
A quote from the "Intel Architecture Manual vol 2a":
A new addressing form, RIP-relative (relative instruction-pointer) addressing, is implemented in 64-bit mode.
An effective address is formed by adding displacement to the 64-bit RIP of the next instruction.
The displacement used in RIP-relative mode is 32 bits in size.
Since it should be useful for both positive and negative offsets,
roughly +/- 2GB is the maximal offset from RIP supported by this addressing mode.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.