为什么GCC编译的C程序需要.eh_frame部分? [英] Why GCC compiled C program needs .eh_frame section?

查看:6011
本文介绍了为什么GCC编译的C程序需要.eh_frame部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

测试是在32位x86 Linux中使用 GCC 4.6.3

Test is on 32 bit x86 Linux with gcc 4.6.3

在使用 GCC 编译 C 程序,并使用 readelf 检查部分信息,
我可以看到 .eh_frame 部分和 .eh_frame_hdr 里面的部分。

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.

例如,这里是二进制程序的部分信息 Perlbench

For example, here is the section info of binary program 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.

但它是 C ++ 程序,它们使用 eh_frame gcc_exception_table 部分来管理例外,那么为什么编译器把 eh_frame eh_frame_hdr 在<$ C $节C> ELF 从 C 程序?

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?

推荐答案

首先,原来的原因主要是政治 - 谁添加的人矮基于平仓( .eh_frame ),希望它是一个功能,总是有那么它可以用于实现各种不仅仅是C ++异常,包括其他的东西:

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:


  • 回溯()

  • __属性__((__ __清理(F)))

  • __ builtin_return_address(N) N'大于0

  • pthread_cleanup_push ,在__属性来实现的__((__清理__(F)))

  • ...

  • backtrace()
  • __attribute__((__cleanup__(f)))
  • __builtin_return_address(n), for n>0
  • pthread_cleanup_push, implemented in terms of __attribute__((__cleanup__(f)))
  • ...

然而,如果你不需要任何这些东西, .eh_frame 是一样的东西增加的.text 大小没有任何好处。你可以用 -fno异步退绕桌单独翻译单位禁止代 .eh_frame ,而这主要是消除了大小开销,虽然你仍然有一些遗留下来 crtbegin.o 来,等你的无法的使用<$ C带他们$ C>条命令后;因为 .eh_frame 是住在程序加载的一部分(这是整点)的部分,剥离它会修改在运行时打破它的方式二进制文件。见<一href=\"https://sourceware.org/bugzilla/show_bug.cgi?id=14037\">https://sourceware.org/bugzilla/show_bug.cgi?id=14037对于事情如何打破的例子。

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.

注意,矮表也用于调试,但为此目的,他们并不需要在程序的装载部。使用 -fno异步退绕桌不会打破调试,因为只要 -g 也将传递到编译器,表仍然可以产生;他们只是存储在一个单独的,非装载,二进制的剥离部分, .debug_frame

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.

这篇关于为什么GCC编译的C程序需要.eh_frame部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆