Concepts
generalGOT & PLT (dynamic linking)
How ELF programs call functions in shared libraries: the Procedure Linkage Table trampolines, the Global Offset Table holds resolved addresses, and lazy binding fills them in on first call.
When an ELF program calls a function from a shared library (printf, malloc,
…), it doesn't know that function's address at link time — the library could be
loaded anywhere (see PIE & ASLR). Two tables bridge the
gap:
- GOT — Global Offset Table: a writable array of data slots that, at runtime, hold the resolved absolute addresses of external symbols.
- PLT — Procedure Linkage Table: a block of tiny code stubs (trampolines), one per imported function, that jump through the GOT.
What a call to an imported function looks like
The compiler emits a call to the PLT stub, not to the real function:
call printf@plt ; call the trampoline, not libc directlyThe stub itself is essentially an indirect jump through the function's GOT slot:
printf@plt:
jmp QWORD PTR [rip + printf@GOTPCREL] ; jump to whatever the GOT holds
; (first-call resolver path follows)Lazy binding
By default the GOT slot for a function does not start with its real address.
Instead it points back into the PLT resolver, so that on the first call the
dynamic linker (ld.so) looks up the symbol, writes the real address into the
GOT slot, and jumps to it. Every subsequent call reads the now-patched slot and
goes straight to the function. This "resolve on first use" is lazy binding;
LD_BIND_NOW=1 / full RELRO resolves everything up front instead.
Reverse-engineering & security notes
call something@plttells you instantly thatsomethingis an imported library function — a fast way to find I/O, crypto, networking and anti-debug calls without analysing library internals.- The GOT is writable, which historically made it an exploitation target:
overwrite a GOT entry (e.g.
free's) and the next call jumps to attacker-controlled code — the GOT overwrite. The RELRO mitigation (-z relro -z now) maps the GOT read-only after startup to stop this; check withreadelf -l/checksec. - A leaked GOT entry also leaks a libc address, defeating ASLR for the library — the start of many ret2libc chains.
- The Windows analogue is the IAT (Import Address Table) reached via the import directory; the concept — a patched table of resolved imports — is the same.
See also: PIE & ASLR · CALL / RET · Memory protection (NX / W^X).