Lazy loading, .plt / .got / .got.plt Quick notes on the topic of lazy dynamic loading, learned from "Practical Binary Analisys" by Denniss Andriesse (Section 2.3.4). The dynamic linker makes process execution faster by delaying the effective loading of library functions on their first usage. This feature can be turned off if real-time predictability is needed. Invoking a function such as 'puts' from the .text section implies a jump to the corresponding stub in the .plt (Procedure Linking Table) section. The .plt section contains read-only executable code. The first instruction of the stub is an intdirect jump to an address specified in a dedicated pointer that belongs to the .got.plt (Global Offset Table / Procedure Linking Table) section. In C pseudocode: void (*ptr)() = got_plt[x]; ptr(); Initially got_plt[x] is assigned to the instruction that follows the indirect jump, so the jump effectively results in a no-op on the first execution. The following instructions will load the parameters for the dynamic loader, and jump to a lookup procedure internal to the dynamic loader. The dynamic loader will assign got_plt[x] to the correct (now resolved) address that the code intended to jump on, before effectively jumpign to it. Subsequent calls to the same library functions will directly jump to the resolved library procedure, without invoking the dynamic linker. Security implications when an exploit can write got_plt[x]. .plt -> Executable, read-only, shared among all processes using the library, references with indirect jump the .got.plt table of the process. Corollary: all processes should map the .got.plt in the same address. .got.plt -> Data, read-write, modified by the dynamic linker. Contains function pointers to be updated with the resolved ones. .got -> Data, read-write, similar to .got.plt but involved in *data* rather than function pointers.