2012-05-02 9 views
15

Eine ELF-Datei für ausführbare Dateien ein Programm (Segment) Header und einen Abschnitt Header, der durch readelf -a zu sehen ist, ist hier ein Beispiel:Welcher Teil der ELF-Datei muss in den Speicher geladen werden?

enter image description here

enter image description here

Die beiden oben genannten Abbildungen sind Abschnitt Header und Programm (Segment) Header, jeweils. Es ist ersichtlich, dass ein Segment-Header aus mehreren Abschnitts-Headern besteht, die zum Laden eines Programms in den Speicher verwendet werden.

Müssen nur .text, .rodata, .data, .bss Sektionen in den Speicher geladen werden?

Werden alle anderen Abschnitte im Segment (z. B. .ctors, .dtors .jcr im 3. Segment) zum Ausrichten verwendet?

+1

Für _aligning_? –

+0

@ Adriano, ja Ausrichtung auf die Seitengröße, so kann verschiedenen Schutz für verschiedene Teile des Programms verwendet werden, zum Beispiel .text (rx), Daten (rw-) –

Antwort

18

Abschnitte und Segmente sind zwei verschiedene Konzepte vollständig. Abschnitte betreffen die Semantik der dort gespeicherten Daten (d. H. Wofür sie verwendet werden) und sind tatsächlich irrelevant, sobald ein Programm oder eine gemeinsam genutzte Bibliothek mit Ausnahme von Debugging-Zwecken verknüpft sind. Sie könnten sogar die Abschnittsüberschriften vollständig entfernen (oder sie mit zufälligem Müll überschreiben) und ein Programm würde immer noch funktionieren.

Segmente (d. H. Programm-Header Load-Direktiven) sind, was der Kernel und/oder dynamische Linker tatsächlich beim Laden eines Programms betrachten. Zum Beispiel haben Sie in Ihrem Fall zwei Lastrichtlinien. Die erste bewirkt, dass die ersten 4 k (1 Seite) der Datei unter der Adresse 0x08048000 abgebildet werden, und zeigt an, dass nur die ersten 0x4b8 Bytes dieser Zuordnung tatsächlich verwendet werden (der Rest ist die Ausrichtung). Die zweite bewirkt, dass die ersten 8 k (2 Seiten) der Datei unter Adresse 0x08049000 gemappt werden. Die überwiegende Mehrheit davon ist Ausrichtung. Die ersten 0xf14 Bytes sind nicht Teil der Load-Direktive (Just Alignment) und werden verschwendet. Beginnend bei 0x08049f14 werden 0x108 Bytes, die aus der Datei gemappt werden, tatsächlich verwendet, und weitere 0x10 Bytes (um die MemSize von 0x118 zu erreichen) werden vom Lader (Kernel oder dynamischer Linker) mit Null gefüllt. Dies erstreckt sich bis 0x0804a02c (in der zweiten abgebildeten Seite). Der Rest der zweiten abgebildeten Seite ist unbenutzt/verschwendet (aber malloc ist möglicherweise in der Lage, sie zur Verwendung als Teil des Heaps wiederherzustellen).

Schließlich, während die Abschnitt Header überhaupt nicht verwendet werden, kann der Inhalt von vielen verschiedenen Abschnitten von Ihrem Programm verwendet werden, während es ausgeführt wird. Beachten Sie, dass die Adressbereiche .ctors und .dtors am Anfang des zweiten Load-Mappings liegen. Daher werden sie vom Programm zur Laufzeit zugeordnet und zugänglich gemacht (der Runtime-Start/Exit-Code verwendet sie, um globale Konstruktoren und Destruktoren auszuführen, wenn C++ oder "GNU C" -Code mit dem ctor/dtor-Attribut wurde verwendet). Beachten Sie auch, dass .data bei Adresse 0x0804a00c in der zweiten zugeordneten Seite beginnt. Dadurch kann die erste Seite schreibgeschützt werden, nachdem Umlagerungen angewendet wurden (die Anweisung RELRO im Programmheader).

+0

+1 für das Hervorheben von GNU_RELRO – SquareRootOfTwentyThree

+0

Hat C Konstruktoren oder Destruktoren wie C++? –

+0

Nein, aber GCC ist nicht C, es ist "GNU C". Sie können alle Arten von nicht standardmäßigen Sachen wie Ausnahmen und Konstruktoren machen. –