Test is on 32 bit x86 Linux with gcc
4.6.3
测试在32位x86 Linux上,使用gcc 4.6.3
When using gcc
to compile a C
program and using readelf
to check the section info, I can see the .eh_frame
section and .eh_frame_hdr
sections inside.
当使用gcc编译C程序并使用readelf检查节信息时,我可以看到.eh_frame和.eh_frame_hdr节。
For example, here is the section info of binary program Perlbench
.
例如,这里是二进制程序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
In my understanding, these two sections are used for handling exceptions, it produce tables that describe how to unwind the stack.
在我的理解中,这两个部分用于处理异常,它生成描述如何展开堆栈的表。
But it is for C++
program, they use eh_frame
and gcc_exception_table
sections to manage exceptions, then why does compiler put the eh_frame
and eh_frame_hdr
sections inside ELF
compiled from C
program?
但是对于c++程序来说,它们使用eh_frame和gcc_exception_table节来管理异常,那么为什么编译器会把eh_frame和eh_frame_hdr部分从C程序编译出来呢?
1 个解决方案
#1
40
First of all, the original reason for this was largely political - the people who added DWARF-based unwinding (.eh_frame
) wanted it to be a feature that's always there so it could be used for implementing all kinds of stuff other than just C++ exceptions, including:
首先,最初的原因主要是政治性的——添加了基于矮人的unwind (.eh_frame)的人希望它是一个始终存在的特性,以便它可以用于实现除c++异常之外的所有功能,包括:
backtrace()
- 回溯()
__attribute__((__cleanup__(f)))
- __attribute__((__cleanup__(f)))
-
__builtin_return_address(n)
, forn>0
- __builtin_return_address(n),n > 0
-
pthread_cleanup_push
, implemented in terms of__attribute__((__cleanup__(f)))
- pthread_cleanup_push,用__attribute__(__cleanup__(f))实现
- ...
- …
However if you don't need any of these things, .eh_frame
is something like a 15-30% increase to .text
size with no benefit. You can disable generation of .eh_frame
with -fno-asynchronous-unwind-tables
for individual translation units, and this mostly eliminates the size cost, although you still have a few left over coming from crtbegin.o
, etc. You cannot strip them with the strip
command later; since .eh_frame
is a section that lives in the loaded part of the program (this is the whole point), stripping it modifies the binary in ways that break it at runtime. See https://sourceware.org/bugzilla/show_bug.cgi?id=14037 for an example of how things can break.
但是,如果您不需要这些东西,.eh_frame就会增加15-30%,变成.text size,没有任何好处。您可以使用-fno-异步- un风表来为单个翻译单元禁用生成.eh_frame,这基本上消除了大小成本,尽管您仍然有一些来自crtbegin的剩余部分。o等。以后不能用命令剥夺它们;因为.eh_frame是一个位于程序加载部分(这是整个要点)的部分,它通过在运行时破坏二进制文件的方式来修改二进制文件。参见https://sourceware.org/bugzilla/show_bug.cgi?id=14037这是一个例子,说明事情是如何破裂的。
Note that DWARF tables are also used for debugging, but for this purpose they do not need to be in the loadable part of the program. Using -fno-asynchronous-unwind-tables
will not break debugging, because as long as -g
is also passed to the compiler, the tables still get generated; they just get stored in a separate, non-loadable, strippable section of the binary, .debug_frame
.
注意,DWARF表也用于调试,但是出于这个目的,它们不需要位于程序的可加载部分。使用-fno-异步-unwind-tables不会破坏调试,因为只要-g也传递给编译器,表仍然会生成;它们只是存储在二进制文件.debug_frame的一个单独的、不可加载的、可删除的部分中。
#1
40
First of all, the original reason for this was largely political - the people who added DWARF-based unwinding (.eh_frame
) wanted it to be a feature that's always there so it could be used for implementing all kinds of stuff other than just C++ exceptions, including:
首先,最初的原因主要是政治性的——添加了基于矮人的unwind (.eh_frame)的人希望它是一个始终存在的特性,以便它可以用于实现除c++异常之外的所有功能,包括:
backtrace()
- 回溯()
__attribute__((__cleanup__(f)))
- __attribute__((__cleanup__(f)))
-
__builtin_return_address(n)
, forn>0
- __builtin_return_address(n),n > 0
-
pthread_cleanup_push
, implemented in terms of__attribute__((__cleanup__(f)))
- pthread_cleanup_push,用__attribute__(__cleanup__(f))实现
- ...
- …
However if you don't need any of these things, .eh_frame
is something like a 15-30% increase to .text
size with no benefit. You can disable generation of .eh_frame
with -fno-asynchronous-unwind-tables
for individual translation units, and this mostly eliminates the size cost, although you still have a few left over coming from crtbegin.o
, etc. You cannot strip them with the strip
command later; since .eh_frame
is a section that lives in the loaded part of the program (this is the whole point), stripping it modifies the binary in ways that break it at runtime. See https://sourceware.org/bugzilla/show_bug.cgi?id=14037 for an example of how things can break.
但是,如果您不需要这些东西,.eh_frame就会增加15-30%,变成.text size,没有任何好处。您可以使用-fno-异步- un风表来为单个翻译单元禁用生成.eh_frame,这基本上消除了大小成本,尽管您仍然有一些来自crtbegin的剩余部分。o等。以后不能用命令剥夺它们;因为.eh_frame是一个位于程序加载部分(这是整个要点)的部分,它通过在运行时破坏二进制文件的方式来修改二进制文件。参见https://sourceware.org/bugzilla/show_bug.cgi?id=14037这是一个例子,说明事情是如何破裂的。
Note that DWARF tables are also used for debugging, but for this purpose they do not need to be in the loadable part of the program. Using -fno-asynchronous-unwind-tables
will not break debugging, because as long as -g
is also passed to the compiler, the tables still get generated; they just get stored in a separate, non-loadable, strippable section of the binary, .debug_frame
.
注意,DWARF表也用于调试,但是出于这个目的,它们不需要位于程序的可加载部分。使用-fno-异步-unwind-tables不会破坏调试,因为只要-g也传递给编译器,表仍然会生成;它们只是存储在二进制文件.debug_frame的一个单独的、不可加载的、可删除的部分中。