Frage

Wenn ich das richtig verstehe, die .bss Abschnitt in ELF-Dateien verwendet wird, um Speicherplatz für null-initialisierte Variablen.Unsere tool-Kette erzeugt ELF-Dateien, daher meine Frage:funktioniert die .bss Abschnitt tatsächlich enthalten alle die Nullen?Es scheint wie eine schreckliche Verschwendung von Räumen, die, wenn, sagen wir, ich weisen Sie eine Globale zehn megabyte array, es Ergebnisse in zehn Megabyte Nullen in der ELF-Datei."Was sehe ich hier falsch?

War es hilfreich?

Lösung

Wurde seit einiger Zeit arbeitete ich mit ELF.Aber ich glaube, ich erinnere mich noch an dieses Zeug.Keine, es nicht physisch enthalten Nullen.Wenn Sie einen Blick in eine ELF-Datei-Programm-header, dann werden Sie sehen, jede Kopfzeile hat zwei Nummern:Eine ist die Größe der Datei.Und die andere ist die Größe der Abschnitt hat, wenn die zugeordneten virtuellen Speicher (readelf -l ./a.out):

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00454 0x00454 R E 0x1000
  LOAD           0x000454 0x08049454 0x08049454 0x00104 0x61bac RW  0x1000
  DYNAMIC        0x000468 0x08049468 0x08049468 0x000d0 0x000d0 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

Header type LOAD sind Sie die eine, die kopiert werden in den virtuellen Speicher, wenn die Datei geladen wird, die für die Ausführung.Andere Header enthalten weitere Informationen, wie Sie die gemeinsam genutzten Bibliotheken, die benötigt werden.Wie Sie sehen, die FileSize und MemSiz wesentlich für die Kopfzeile enthält die bss Abschnitt (die zweite LOAD einer):

0x00104 (file-size) 0x61bac (mem-size)

Für dieses Beispiel-code:

int a[100000];
int main() { }

Der ELF-Spezifikation sagt, dass das Teil ein segment, das die mem-size ist größer als die Datei-Größe ist nur ausgefüllt, mit Nullen im virtuellen Speicher.Das segment Abschnitt mapping des zweiten LOAD header ist wie folgt:

03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss

So gibt es einige andere Abschnitte es auch.Für C++ - Konstruktor/Destruktor.Das gleiche gilt für Java.So enthält es eine Kopie der .dynamic Abschnitt und andere Sachen nützlich für die dynamische Verknüpfung (ich glaube, das ist der Ort, der enthält die benötigten shared libraries unter Sonstiges).Nach, dass die .data Abschnitt enthält initialisierte globals und lokale statische Variablen.Am Ende der .bss Abschnitt wird angezeigt, die gefüllt ist von Nullen auf die Ladezeit, da die Datei-Größe nicht abdecken.

Durch die Weg, Sie können sehen, in die output-Sektion ein bestimmtes symbol platziert werden, durch die Verwendung der -M linker-option.Für den gcc verwenden Sie -Wl,-M setzen Sie die option durch den linker.Das obige Beispiel zeigt, dass a zugeordnet wird innerhalb .bss.Es kann Ihnen helfen, stellen Sie sicher, dass Sie Ihr nicht initialisierte Objekte wirklich am Ende in .bss und nicht irgendwo anders:

.bss            0x08049560    0x61aa0
 [many input .o files...]
 *(COMMON) 
 *fill*         0x08049568       0x18 00
 COMMON         0x08049580    0x61a80 /tmp/cc2GT6nS.o
                0x08049580                a
                0x080ab000                . = ALIGN ((. != 0x0)?0x4:0x1) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                _end = .

GCC hält nicht initialisierte globals in einem GEMEINSAMEN Abschnitt standardmäßig für die Kompatibilität mit alten Compilern, die es ermöglichen, globals definiert zweimal in einem Programm ohne mehrfach definiert Fehler.Verwenden -fno-common machen GCC verwenden .bss-Abschnitte für die Objekt-Dateien (nicht einen Unterschied machen, der für die endgültige verknüpfte ausführbare Datei, denn wie Sie sehen, ist es gehen, um in eine .bss-Ausgabe-Bereich sowieso.Dies wird gesteuert durch linker-Skript.Zeigen Sie es mit ld -verbose).Aber das sollte nicht erschrecken, es ist nur eine interne detail.Siehe die manpage von gcc.

Andere Tipps

Der .bss Abschnitt in einer ELF-Datei für statische Daten verwendet wird, die ist nicht initialisiert programmatisch aber garantiert auf Null zur Laufzeit festgelegt werden. Hier ist ein kleines Beispiel, das die Differenz wird erklären.

int main() {
    static int bss_test1[100];
    static int bss_test2[100] = {0};
    return 0;
}

In diesem Fall bss_test1 in die .bss gelegt, da es nicht initialisiert ist. bss_test2 jedoch wird zusammen mit einer Reihe von Nullen in das .data Segment platziert. Der Runtime-loader ordnet grundsätzlich die Menge an Speicherplatz für die .bss reserviert und Nullen es aus, bevor ein Userland-Code beginnt mit der Ausführung.

Sie können den Unterschied mit objdump, nm oder ähnlichen Dienstprogramme siehe:

moozletoots$ objdump -t a.out | grep bss_test
08049780 l     O .bss   00000190              bss_test1.3
080494c0 l     O .data  00000190              bss_test2.4
Diese

ist in der Regel einer der ersten Überraschungen , dass Embedded-Entwicklern den Weg laufen ... nie explizit auf Null Statik initialisieren. Die Runtime-Loader (in der Regel) kümmert sich darum. Sobald Sie etwas explizit initialisieren, Sie erzählen die Compiler / Linker die Daten in der ausführbaren Bild aufzunehmen.

Ein .bss Abschnitt wird in einer ausführbaren Datei nicht gespeichert. Von den am häufigsten Abschnitte (.text, .data, .bss), nur .text (Ist-Code) und .data (initialisierten Daten) sind in einer ELF-Datei.

Das ist richtig, .bss physisch nicht in der Datei vorhanden ist, sondern nur die Informationen über die Größe vorhanden ist, für das dynamische Lade den .bss Abschnitt für das Anwendungsprogramm zuzuweisen. Als Faustregel gilt nur LOAD, TLS Segment den Speicher für das Anwendungsprogramm erhält, Rest für dynamische Lader verwendet werden.

über statische ausführbare Datei, bss Abschnitte wird auch Platz im execuatble gegeben

Embedded-Anwendung, wo es keine loader diese üblich ist.

Suman

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top