Warum benötigt das GCC-kompilierte C-Programm den Abschnitt .eh_frame?

Lesezeit: 4 Minuten

Test ist auf 32-Bit-x86-Linux mit gcc 4.6.3

Beim Benutzen gcc kompilieren a C programmieren und verwenden readelf Um die Abschnittsinformationen zu überprüfen, kann ich die sehen .eh_frame Abschnitt und .eh_frame_hdr Abschnitte hinein.

Hier ist zum Beispiel der Abschnitt info des Binärprogramms Perlbench.

readelf -S perlbench

There are 28 section headers, starting at offset 0x102e48:

Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .interp           PROGBITS        08048154 000154 000013 00   A  0   0  1
[ 2] .note.ABI-tag     NOTE            08048168 000168 000020 00   A  0   0  4
[ 3] .note.gnu.build-i NOTE            08048188 000188 000024 00   A  0   0  4
[ 4] .gnu.hash         GNU_HASH        080481ac 0001ac 000044 04   A  5   0  4
[ 5] .dynsym           DYNSYM          080481f0 0001f0 0007b0 10   A  6   1  4
[ 6] .dynstr           STRTAB          080489a0 0009a0 0003d6 00   A  0   0  1
[ 7] .gnu.version      VERSYM          08048d76 000d76 0000f6 02   A  5   0  2
[ 8] .gnu.version_r    VERNEED         08048e6c 000e6c 0000a0 00   A  6   2  4
[ 9] .rel.dyn          REL             08048f0c 000f0c 000028 08   A  5   0  4
[10] .rel.plt          REL             08048f34 000f34 000388 08   A  5  12  4
[11] .init             PROGBITS        080492bc 0012bc 00002e 00  AX  0   0  4
[12] .plt              PROGBITS        080492f0 0012f0 000720 04  AX  0   0 16
[13] .text             PROGBITS        08049a10 001a10 0cf86c 00  AX  0   0 16
[14] .fini             PROGBITS        0811927c 0d127c 00001a 00  AX  0   0  4
[15] .rodata           PROGBITS        081192a0 0d12a0 017960 00   A  0   0 32
[16] .eh_frame_hdr     PROGBITS        08130c00 0e8c00 003604 00   A  0   0  4
[17] .eh_frame         PROGBITS        08134204 0ec204 01377c 00   A  0   0  4
[18] .ctors            PROGBITS        08148f0c 0fff0c 000008 00  WA  0   0  4
[19] .dtors            PROGBITS        08148f14 0fff14 000008 00  WA  0   0  4
[20] .jcr              PROGBITS        08148f1c 0fff1c 000004 00  WA  0   0  4
[21] .dynamic          DYNAMIC         08148f20 0fff20 0000d0 08  WA  6   0  4
[22] .got              PROGBITS        08148ff0 0ffff0 000004 04  WA  0   0  4
[23] .got.plt          PROGBITS        08148ff4 0ffff4 0001d0 04  WA  0   0  4
[24] .data             PROGBITS        081491e0 1001e0 002b50 00  WA  0   0 32
[25] .bss              NOBITS          0814bd40 102d30 002b60 00  WA  0   0 32
[26] .comment          PROGBITS        00000000 102d30 00002a 01  MS  0   0  1
[27] .shstrtab         STRTAB          00000000 102d5a 0000ec 00      0   0  1

Nach meinem Verständnis werden diese beiden Abschnitte zur Behandlung von Ausnahmen verwendet, es werden Tabellen erstellt, die beschreiben, wie der Stapel entladen wird.

Aber es ist für C++ Programm, verwenden sie eh_frame und gcc_exception_table Abschnitte zum Verwalten von Ausnahmen, warum setzt der Compiler dann die eh_frame und eh_frame_hdr Abschnitte hinein ELF zusammengestellt aus C Programm?

  • x86-64 ABI-Mandate .eh frames überall genau. Dies wurde hinzugefügt, um das Abwickeln des Stapels überall zu ermöglichen, da dies in manchen Fällen systemweit erforderlich ist, z. B. in Profilierungswerkzeugen. GCC verwendet daher auf x86_64 standardmäßig die EH-Frame-Generierung und versucht, es überall genau zu machen, während es auf den meisten anderen ABIs standardmäßig nur dann auf die EH-Frame-Generierung setzt, wenn ein EH-Frame benötigt wird, und es nur an den Programmpunkten präzise ist, die EH und auslösen könnten somit abwickeln.

    – fragmisch

    10. Oktober 2014 um 14:13 Uhr

  • Ich vermute gcc verwendet sie auch zur Umsetzung __attribute__((cleanup(..))).

    – gsg

    10. Oktober 2014 um 14:57 Uhr

  • mögliches Duplikat von Wozu dient der Abschnitt .eh_frame in C-Programmen?

    – Ciro Santilli OurBigBook.com

    25. Juni 2015 um 14:00 Uhr

  • “Referenz in dieser Frage?” Ich verstehe nicht, was du meinst. Meinst du die Kommentare? Warum sind die Fragen unterschiedlich? Ich kann mich irren. Umgekehrt zu schließen ist eine weitere Möglichkeit: Dies ist etwas besser gestellt, aber die andere ist eine ältere, schwierige Wahl. Über den Benutzernamen, lassen Sie die Diskussion für Meta oder Twitter. Prost.

    – Ciro Santilli OurBigBook.com

    25. Juni 2015 um 15:57 Uhr

  • Eine kleine Korrektur: crtbegin.o enthält kein CFI, zumindest auf RedHat und Ubuntu. Die Reste würden höchstwahrscheinlich vom CFI für kommen __libc_csu_init und __libc_csu_fini. Die sind nicht drin crtbegin.o sondern im nicht gemeinsam genutzten Teil von GLIBC libc_nonshared.a

    – Christo Iljew

    10. Oktober 2014 um 15:37 Uhr

  • Hallo, ich frage mich, ob die Verwendung von eh_frame ist eine GCC-spezifizierte Funktion? Ich habe versucht zu verwenden clang und gcc um ein Stück C-Code zu kompilieren. Das eh_frame Abschnitt, der von GCC generiert wird, ist da 0x5cfc während es nur ist a4 zum clang.

    – lllllllllllll

    3. Juni 2015 um 19:28 Uhr

  • Erwähnenswert ist, dass das Entladen von Ausnahmen möglicherweise die Stack-Frames von C-Funktionen durchlaufen muss. Wenn zB eine C-Bibliothek einen Funktionszeiger auf eine Callback-Funktion oder ähnliches nimmt, kann sie am Ende erneut eine C++-Funktion aufrufen. Übrigens, -fno-omit-frame-pointer kann die eh_frame-Größe erheblich verkleinern, und gcc-Entwickler haben in Betracht gezogen, gcc dazu zu bringen, rbp als Frame-Zeiger in Funktionen zu verwenden, bei denen dies keine Verlangsamung darstellt.

    – Peter Cordes

    13. September 2016 um 23:54 Uhr

  • @PeterCordes: Das ist UB, und selbst wenn dies nicht der Fall wäre, würde es mit ziemlicher Sicherheit den Vertrag der C-Bibliothek brechen – der meiste C-Bibliothekscode, der Rückrufe verwendet, geht davon aus, dass die Rückrufe zurückgegeben werden, anstatt longjmpund das Propagieren einer Ausnahme wäre äquivalent zu longjmp. Wenn C++-Code, der Ausnahmen verwendet, als Rückruf von C aufgerufen wird, muss der Rückruf alle Ausnahmen abfangen und sie in Fehlerrückgaben an den C-Aufrufer übersetzen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. September 2016 um 1:50 Uhr

  • @PeterCordes: Nun, “C++-Ausnahmen sollte in der Lage sein, sich durch C auszubreiten, obwohl es ein undefiniertes Verhalten ist” ist eine politische Position (und IMO eine unhaltbare aus den oben beschriebenen Gründen – selbst wenn sie definiert wäre, könnte sie nur für sehr reine C-Funktionen verwendet werden, ohne dass Fehler bereinigt werden müssten).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. September 2016 um 14:31 Uhr

1414470cookie-checkWarum benötigt das GCC-kompilierte C-Programm den Abschnitt .eh_frame?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy