This page assumes nothing. Before you read the parent topic, we build every word it leans on — from "what is machine code" up to "what is the GOT". Read top to bottom; each block only uses words defined above it.
Relative addressing works because the CPU can read its own PC: "target = PC + 80". The parent's formula phrase "PC-relative offset" literally means "a distance measured from the current PC".
PC
The register holding the address of the instruction currently running; the reference point all relative addresses are measured from.
Symbols split into two flavours the parent cares about:
Internal symbol — defined inside the same library. Reachable by a plain PC-relative offset (its distance from the caller is fixed).
External symbol — defined in another library (e.g. printf lives in libc). Its distance is not fixed, because the other library loads separately. This is the hard case the GOT solves.
Once these foundations are solid, they feed directly into: Static libraries — .a .lib (the copy-in alternative), ASLR & Security (why load addresses are deliberately randomised), dlopen and Plugin Architectures (loading libraries on demand), and of course the parent topic itself.
the number of a memory "mailbox"; code and data both live at addresses.
Absolute vs relative addressing
absolute = a fixed box number baked in; relative = a distance measured from the current instruction (the PC).
Why relative addressing survives the code being moved
if the whole library slides together, distances between its own parts stay the same, so "80 boxes ahead" is still correct.
What the PC (Program Counter) holds
the address of the instruction running right now — the reference point for all PC-relative offsets.
Virtual vs physical address
virtual = each process's private illusion of the memory street; the same physical page can appear at different virtual addresses in different processes.
Why shared code bytes may contain no per-process number
because the identical physical page is seen by every sharer; any per-process value would be wrong for some of them.
Code page vs data page
code pages hold instructions (shared, read-only); data pages hold variables (private, writable) — the GOT lives on a data page.
What a symbol is
a name (like printf) for a piece of code or data; the machine ultimately needs its address.
Internal vs external symbol
internal lives in the same library (fixed distance, plain PC-relative); external lives in another library (address unknown until load — needs the GOT).
Linker vs loader
linker (build time) checks symbols exist and records dependencies; loader (run time) finds the file and patches real addresses.
What relocation does
writes the now-known real box numbers into placeholder slots — arranged to touch data pages only.
What the GOT stores and why writable
real per-process addresses of external symbols; writable so the loader can patch them without disturbing shared code.
What the PLT does / lazy binding
stubs that resolve a function's address on its first call, store it in the GOT, then jump; later calls skip resolution.
ELF vs PE
file formats for library files — ELF on Linux, PE (with an Import Address Table) on Windows.