web-dev-qa-db-ja.com

GCCでコンパイルされたCプログラムに.eh_frameセクションが必要なのはなぜですか?

テストはgcc 4.6.3を使用した32ビットx86 Linuxで行われます

gccを使用してCプログラムをコンパイルし、readelfを使用してセクション情報を確認すると、.eh_frameセクションと.eh_frame_hdrセクション。

たとえば、バイナリプログラム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

私の理解では、これらの2つのセクションは例外の処理に使用され、スタックの巻き戻し方法を説明するテーブルを生成します。

しかし、それはC++プログラム、彼らはeh_frameおよびgcc_exception_tableセクションで例外を管理し、コンパイラーがeh_frameおよびeh_frame_hdrELFプログラムからコンパイルされたC内のセクション?

36
lllllllllllll

まず第一に、これの元々の理由は主に政治的なものでした-DWARFベースの巻き戻し(_.eh_frame_)を追加した人々は、それが常に存在する機能であり、それ以外のあらゆる種類の実装に使用できることを望んでいました以下を含む、C++例外のみ:

  • backtrace()
  • __attribute__((__cleanup__(f)))
  • __builtin_return_address(n)、_n>0_の場合
  • _pthread_cleanup_Push_、__attribute__((__cleanup__(f)))の観点から実装
  • ...

ただし、これらのいずれも必要ない場合、_.eh_frame_は、メリットのない_.text_サイズへの15-30%の増加のようなものです。個々の翻訳単位に対して_.eh_frame_を使用して_-fno-asynchronous-unwind-tables_の生成を無効にできます。これにより、_crtbegin.o_などからの残りがいくつか残っていますが、ほとんどの場合、サイズのコストがなくなります。 cannot後でstripコマンドで削除します。 _.eh_frame_はプログラムのロードされた部分(これが全体のポイントです)にあるセクションであるため、それを削除すると、実行時に壊れるような方法でバイナリが変更されます。物事がどのように壊れるかの例については、 https://sourceware.org/bugzilla/show_bug.cgi?id=14037 を参照してください。

DWARFテーブルはデバッグにも使用されますが、この目的のために、プログラムのロード可能な部分にある必要はありません。 _-fno-asynchronous-unwind-tables_を使用しても、デバッグが中断されることはありません。これは、_-g_もコンパイラに渡される限り、テーブルが生成されるためです。それらは、バイナリの別個のロード不可能なストリップ可能なセクション_.debug_frame_に格納されます。

50
R..