Quiz Entry - updated: 2026.07.10
What is the Procedure Linkage Table (PLT) and how does lazy binding work?
The Procedure Linkage Table defers resolving an imported function until its first call (lazy binding), then caches the real address in the GOT so later calls go straight there.
* The first call pays the resolver once and caches the real address in the GOT; every later call is a direct jump through that cached entry. *
Why lazy binding?
- Programs may not call all imported functions
- Resolving all symbols at startup is slow
- Only pay the resolution cost when actually needed
PLT structure:
PLT[0]: Call dynamic linker resolver
PLT[1]: Entry for function #1
PLT[2]: Entry for function #2
...
First call to printf:
1. Call PLT[printf]
2. PLT jumps to GOT[printf]
3. GOT initially points back to PLT (resolver code)
4. Resolver finds real printf address
5. Updates GOT[printf] with real address
6. Jumps to real printf
Subsequent calls:
1. Call PLT[printf]
2. PLT jumps to GOT[printf]
3. GOT now has real address - go directly there!
Disable lazy binding:
# Resolve all at startup
$ LD_BIND_NOW=1 ./program
# Link-time option
$ gcc -Wl,-z,now -o prog ...
Security: Full RELRO (RELocation Read-Only) marks GOT as read-only after resolution, preventing GOT overwrite attacks.
Go deeper:
Eli Bendersky — the PLT and lazy binding — the trampoline that resolves an imported call on first use.