Der Linker ist das Programm, das nach der Übersetzung mehrere Objektdateien und Bibliotheken zu einem ausführbaren Programm zusammenführt. Er ist die letzte Stufe klassischer, kompilierter Sprachen: Der C-Compiler erzeugt aus main.c und util.c die Objektdateien main.o und util.o, der Linker macht daraus eine ausführbare Datei.
Die Stellung in der Pipeline
quelltext.c --> Compiler --> Objektdatei (.o/.obj)
quelltext.c --> Compiler --> Objektdatei (.o/.obj)
\_ Linker _/ --> ausführbares Programm (ELF/PE)
+ Bibliotheken
Der Compiler endet nach der Codegenerierung bei einer Objektdatei, deren Adressen noch relativ sind. Erst der Linker löst die offenen Fragen. Wer mit gcc main.c util.c -o app übersetzt, ruft im Hintergrund den Linker ld (bzw. collect2 bei GCC) auf — Kompilieren und Linken sind also zwei getrennte Schritte.
Die Aufgaben des Linkers
- Symbolauflösung: Jede Referenz auf eine Funktion oder Variable muss eine Definition finden.
main.oruftutil_funktion()— die Definition liegt inutil.o. Fehlt eine Definition, bricht der Linker mit undefined reference ab. - Relokation: Objektdateien verwenden relative Adressen (Offset 0). Der Linker verschiebt die Sections an ihre endgültigen Speicheradressen und korrigiert alle Verweise dorthin.
- Zusammenführen: Code-, Daten- und Metadaten-Sections der Objektdateien werden zu den Sections der ausführbaren Datei (z.B. ELF unter Linux, PE unter Windows) kombiniert.
Statisches und dynamisches Linken
Bibliotheken lassen sich auf zwei Arten einbinden:
- Statisches Linken: Der Bibliothekscode wird direkt in die ausführbare Datei kopiert (
.a-Archive unter Linux,.libunter Windows). Das Programm ist eigenständig, aber größer; ein Update der Bibliothek erfordert Neulinken. - Dynamisches Linken: Die Binärdatei enthält nur Verweise auf
.so-Dateien (Linux) oder.dll-Dateien (Windows). Beim Start lädt der dynamische Lader der Runtime die Bibliotheken — das spart Speicher und erlaubt Updates ohne Neulinken, kostet aber etwas Startzeit (Library Hell ist die Kehrseite).
Link-Time Optimization (LTO)
Moderne Compiler unterstützen LTO: Vor dem eigentlichen Linken wird der Zwischencode aller Objektdateien gemeinsam optimiert, sodass der Optimierer auch über Dateigrenzen hinweg arbeiten kann (z.B. Inlining einer Funktion aus util.c in main.c).
Besonderheiten anderer Ökosysteme
Sprachen mit Bytecode brauchen keinen klassischen Linker: Die virtuelle Maschine übernimmt das Laden zur Laufzeit — die JVM lädt .class-Dateien über den ClassLoader, Python importiert Module direkt aus .py- oder .pyc-Dateien. Der Assembler auf der anderen Seite erzeugt aus Assembler-Quelltext Objektdateien, die ebenfalls erst der Linker zu einem Programm macht.