Почему GCC, скомпилированный программой C, нуждается в разделе .eh_frame?

Тест находится на 32-битной x86 Linux с gcc 4.6.3

При использовании 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 

По моему мнению, эти два раздела используются для обработки исключений, они создают таблицы, описывающие, как разматывать стек.

Но это для C++ программы, они используют eh_frame и gcc_exception_table для управления исключениями, то почему компилятор помещает eh_frame и eh_frame_hdr в ELF скомпилированные из C программы?

Прежде всего, первоначальная причина для этого была в значительной степени политическая – люди, которые добавили разворачивание на основе .eh_frame ( .eh_frame ), хотели, чтобы это была функция, которая всегда существует, поэтому ее можно использовать для реализации всех видов вещей, кроме как только исключений C ++ , в том числе:

  • backtrace()
  • __attribute__((__cleanup__(f)))
  • __builtin_return_address(n) , при n>0
  • pthread_cleanup_push , реализованный в терминах __attribute__((__cleanup__(f)))

Однако, если вам не нужны какие-либо из этих вещей, .eh_frame – это что-то вроде увеличения на 15-30% к размеру .text без каких-либо преимуществ. Вы можете отключить генерацию .eh_frame с -fno-asynchronous-unwind-tables для отдельных единиц перевода, и это в основном устраняет стоимость размера, хотя у вас все еще есть несколько оставшихся от crtbegin.o и т. Д. Вы не можете их crtbegin.o команда strip позже; так как .eh_frame – это раздел, который находится в загруженной части программы (это целая точка), зачищая его, он изменяет двоичный файл способами, которые прерывают его во время выполнения. См. https://sourceware.org/bugzilla/show_bug.cgi?id=14037 для примера того, как все может сломаться.

Обратите внимание, что таблицы DWARF также используются для отладки, но для этой цели они не обязательно должны находиться в загружаемой части программы. Использование -fno-asynchronous-unwind-tables не будет прерывать отладку, поскольку до тех пор, пока -g также передается компилятору, таблицы все равно генерируются; они просто сохраняются в отдельной, не загружаемой, удаляемой секции двоичного .debug_frame .

  • Может ли x86's MOV быть «свободным»? Почему я не могу воспроизвести это вообще?
  • Как разобрать 16-разрядный код загрузочного сектора x86 в GDB с помощью «x / i $ pc»? Он рассматривается как 32-битный
  • Имеет ли смысл использовать инструкцию LFENCE для процессоров x86 / x86_64?
  • Двоичная бомба - Фаза 4
  • В чем смысл «не временных» обращений к памяти в x86
  • Самый быстрый способ вычисления 128-битного целого по модулю 64-разрядного целого числа
  • Каковы наилучшие последовательности команд для генерации векторных констант «на лету»?
  • x86 Инструкция MUL от VS 2008/2010
  • Почему (или нет?) SFENCE + LFENCE эквивалентно MFENCE?
  • об ассемблере CF (Carry) и OF (Overflow)
  • Самый быстрый способ вычисления абсолютного значения с помощью SSE
  • Давайте будем гением компьютера.