Ld (Linker)
GNU ld ist der Linker der GNU Toolchain, der für die Verknüpfung von Objektdateien und Bibliotheken zu einer ausführbaren Datei, einem dynamischen Shared Object (DSO) oder einer Bibliothek verwendet wird. Der Linker spielt eine entscheidende Rolle in der Build-Pipeline eines C/C++-Projekts, indem er verschiedene Kompilierungsoutputs zusammenführt und externe Symbole auflöst.
Hauptaufgaben des GNU Linkers (ld)
Zusammenführung von Objektdateien
Der Linker kombiniert verschiedene Objektdateien (`.o`-Dateien), die durch den Compiler erzeugt wurden, zu einem einzigen Programm oder einer Bibliothek. Dabei werden die Objektdateien nacheinander eingelesen und ihre Symbole verknüpft.
Auflösen von Symbolen
Während des Verlinkungsvorgangs löst der Linker Symbole auf. Symbole sind Funktionen, Variablen und Objekte, die in den Objektdateien und Bibliotheken definiert oder referenziert werden. Der Linker stellt sicher, dass alle externen Verweise auf Symbole (wie Funktionsaufrufe oder globale Variablen) auf eine gültige Definition verweisen.
Erstellen von ausführbaren Dateien
Der GNU ld-Linker erstellt die endgültige ausführbare Datei aus den verknüpften Objektdateien und Bibliotheken. Dies kann eine statische oder dynamische Verknüpfung sein:
- Statische Verknüpfung: Alle notwendigen Bibliotheksinhalte werden direkt in die ausführbare Datei eingefügt, wodurch sie unabhängig von externen Bibliotheken ausgeführt werden kann.
- Dynamische Verknüpfung: Die ausführbare Datei enthält Referenzen auf externe, zur Laufzeit zu ladende dynamische Bibliotheken (Shared Libraries, z.B. `.so`-Dateien auf Unix-Systemen oder `.dll` auf Windows).
Bibliotheken verlinken
Der Linker kann sowohl statische Bibliotheken (`.a` in Unix/Linux) als auch dynamische Bibliotheken (`.so`) verknüpfen. Abhängig von den Verknüpfungsoptionen kann der Linker:
- Statische Bibliotheken in die endgültige ausführbare Datei aufnehmen.
- Dynamische Bibliotheken zur Laufzeit verwenden, sodass die Bibliothek erst geladen wird, wenn das Programm ausgeführt wird.
Verwalten von Speicheradressen und Abschnitten
Der GNU ld verwaltet die Speicherabschnitte (Text, Daten, BSS) der einzelnen Objektdateien und legt fest, welche Speicherbereiche für verschiedene Datenarten verwendet werden. Die Speicherorganisation umfasst:
- Textsegment: Enthält den ausführbaren Maschinencode.
- Datensegment: Enthält initialisierte globale und statische Variablen.
- BSS-Segment: Enthält uninitialisierte globale und statische Variablen.
Außerdem kann der Linker die Startadresse des Programms festlegen und das Layout der Speichersegmente konfigurieren.
Laden von Startcode und dynamischen Loadern
Der Linker integriert den notwendigen Startcode (wie den C-Runtime-Startcode) und erstellt den Einstiegspunkt der ausführbaren Datei (normalerweise die Funktion `main()` für C-Programme). Bei dynamisch gelinkten Programmen sorgt er für die Integration des dynamischen Loaders, der für das Laden der Shared Libraries zur Laufzeit verantwortlich ist.
Verknüpfungsprozess: Statische und Dynamische Verknüpfung =
Statische Verknüpfung
Hierbei wird der gesamte Code aus den Bibliotheken direkt in die ausführbare Datei eingebettet. Dies führt zu größeren Binärdateien, aber die ausführbare Datei kann eigenständig ohne externe Abhängigkeiten laufen. Der Befehl könnte folgendermaßen aussehen:
gcc -o meinprogramm main.o libmylib.a
Dynamische Verknüpfung
Bei der dynamischen Verknüpfung referenziert das Programm zur Laufzeit externe Shared Libraries (`.so`-Dateien). Die ausführbare Datei ist kleiner, benötigt jedoch, dass die benötigten Bibliotheken zur Laufzeit verfügbar sind:
gcc -o meinprogramm main.o -lmylib
GNU ld-Optionen
Der GNU Linker bietet zahlreiche Optionen, um den Verknüpfungsvorgang zu steuern. Hier sind einige häufig verwendete:
-o: Legt den Namen der Ausgabedatei fest:
ld -o meinprogramm start.o main.o
-L: Gibt den Pfad zu Verzeichnissen an, in denen nach Bibliotheken gesucht werden soll:
ld -L/path/to/libs -lmylib
-l: Verknüpft eine Bibliothek (ohne den Präfix `lib` und die Erweiterung `.a` oder `.so`):
ld -o meinprogramm main.o -lmylib # Verknüpft libmylib.a oder libmylib.so
-rpath: Gibt an, wo zur Laufzeit nach dynamischen Bibliotheken gesucht werden soll:
ld -o meinprogramm main.o -lmylib -rpath /usr/local/lib
-static: Erzwingt statische Verknüpfung, selbst wenn dynamische Bibliotheken verfügbar sind:
gcc -o meinprogramm main.o -static -lmylib
-T: Ermöglicht die Verwendung eines Linker-Skripts, um den Verknüpfungsvorgang genauer zu steuern. Mit einem Linker-Skript kannst du Speicherlayouts, Startadressen und Speichersegmentierung definieren.
ld -T linkerskript.ld -o meinprogramm main.o
Verwendung eines Linker-Skripts
Linker-Skripte geben dem Entwickler präzise Kontrolle über das Layout der erzeugten Binärdatei. Ein einfaches Linker-Skript könnte folgendermaßen aussehen:
SECTIONS { .text 0x1000 : { *(.text) } .data 0x8000 : { *(.data) } .bss 0xA000 : { *(.bss) } }
Dieses Skript spezifiziert, dass das Textsegment bei der Adresse `0x1000`, das Datensegment bei `0x8000` und das BSS-Segment bei `0xA000` beginnen sollen. Der GNU ld-Linker nutzt dieses Skript, um die Speicheraufteilung des Programms genau zu kontrollieren.
Debugging und Fehlerbehebung
Der Linker bietet nützliche Werkzeuge zur Fehlersuche:
- Undefinierte Symbole: Wenn ein Symbol, auf das verwiesen wird, nicht gefunden wird, meldet ld einen Fehler. Dies passiert häufig, wenn Bibliotheken in der falschen Reihenfolge angegeben werden oder wenn eine Bibliothek fehlt.
- Verbose-Modus: Mit der Option `-v` oder `--verbose` kannst du den Linker dazu bringen, detaillierte Informationen über den Verknüpfungsvorgang auszugeben:
ld --verbose
Zusammenfassung
Der GNU Linker (ld) ist ein leistungsstarkes Tool, das essenziell für die Erstellung von ausführbaren Dateien und Bibliotheken ist. Es vereint Objektdateien, löst Symbole auf, verknüpft Bibliotheken und erstellt die endgültige Binärdatei. Durch seine Flexibilität bei der statischen und dynamischen Verknüpfung, seine Fähigkeit zur Nutzung von Linker-Skripten und seine erweiterbaren Optionen ist ld ein unverzichtbares Werkzeug für Entwickler in der GNU-Umgebung.
| < Zurück (GNU Debugger) | < Hauptseite > | Weiter (objdump) > |