gcc 为 linux ELF 添加了哪些功能?

Posted

技术标签:

【中文标题】gcc 为 linux ELF 添加了哪些功能?【英文标题】:What functions does gcc add to the linux ELF? 【发布时间】:2016-04-30 04:45:03 【问题描述】:

当用gcc 链接c(或asm)中的类似hello-world 的程序时,它会在结果可执行目标文件中添加一些内容。我只知道运行时动态链接器和_start 入口点,但是这些添加的函数是什么类型的?

00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones
0000000000400470 t __do_global_dtors_aux
0000000000400490 t frame_dummy
00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini
0000000000400554 T _fini
0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start
0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end

它们是什么,有什么用?在某处有描述吗?谷歌搜索没有帮助。

【问题讨论】:

见Linux x86 Program Start Up by Patrick Horgan 请注意,没有libc 的纯asm 代码不会添加这些,因为它们来自libc。 @Jester 看起来很不错,谢谢!如果它包含我问过的任何东西,你可以用这个信息来回答(当然还有一些来自那里的信息)。 【参考方案1】:

其中大部分是在“主”程序本身之前或之后执行代码的各种方法,大多数都存在于crtstuff.c(https://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c)中。 它们的存在是为了支持各种类似 C 的编程语言的特性,但它们也可以在 C 中访问。它可能看起来过于复杂,因为其中一些代表遗留包袱,而另一些则代表了支持 GCC 运行的各种不同架构所需的变体。

 

从您的列表中,一一(或二二):

00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones

事务性内存旨在简化线程编程。 它是基于锁的同步的替代方案。 这些例程分别拆除和设置支持这些功能的库 (libitm) 使用的表。 更多关于 TM 的信息在这里https://gcc.gnu.org/wiki/TransactionalMemory 和这里http://pmarlier.free.fr/gcc-tm-tut.html

 

0000000000400470 t __do_global_dtors_aux

.fini_array 不可用的系统上退出程序时运行所有全局析构函数。

 

0000000000400490 t frame_dummy

此函数位于.init 部分。它被定义为void frame_dummy ( void ),它的全部意义就是调用有参数的__register_frame_info_bases。显然,使用.init 部分的参数调用函数可能不可靠,因此这个函数因此__register_frame_info_bases 不会直接从.init section 调用。 .eh_frame 信息库用于异常处理和类似功能(例如,使用 __attribute__((cleanup(..))) 声明的函数)。

 

00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini

它们运行任何程序级的初始化器和终结器(有点像整个程序的构造器/析构器)。 如果您定义如下函数:

void __attribute__ ((constructor)) mefirst () 
    /* ... do something here ... */


void __attribute__ ((destructor)) melast () 
    /* ... do something here ... */

这些例程将分别在main() 之前和之后调用它们。 另见https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

 

0000000000400554 T _fini

这是运行程序级(实际上是对象文件级)析构函数的一种现已弃用的方法(有关此的一些信息可以在man dlclose 中找到)。 构造函数对应的过时函数是__init

 

0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start

这些标记了.init_array 部分的结束和开始,其中包含指向所有程序级初始化程序的指针(参见上面的__libc_csu_init)。

 

0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end

这些标记了 .fini_array 部分的结束和开始,其中包含指向所有程序级终结器的指针(请参阅上面的 __libc_csu_fini)。

 

[编辑]一些附加说明:

链接 http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html (wayback machine) 来自 Jester 的问题评论包含一个漂亮的图表和一个小样本 说明这些东西运行的总体顺序以及如何运行的程序 从 C 访问其中一些功能。

术语“ctors”和“dtors”是 'constructors' 和 'destructors' 分别。

全局构造函数/析构函数和对象文件的区别 当你的程序运行时,构造函数/析构函数最为明显 由多个目标文件构成。

标记为“T”的符号(__libc_csu_init、__libc_csu_fini、_fini) 是“全局的”(外部可见),其余的(标记为“t”)不是。

【讨论】:

您能否补充一些内容以澄清global destructors program-level initializers and finalizers 是什么?在我看来,这会使答案看起来更完整。 每个共享​​>对象文件,而不是每个对象文件。

以上是关于gcc 为 linux ELF 添加了哪些功能?的主要内容,如果未能解决你的问题,请参考以下文章

gcc 是不是有任何选项可以在 ELF 二进制文件中添加版本信息?

GCCARM-LINUX-GCCARM-ELF-GCC浅析

交叉编译libnpg库 ./configure CC=mipsisa32-elf-gcc --host=mipsisa32-linux 求大神给予帮助

Linux内核分析——ELF文件格式分析

为啥 Windows gcc (cygwin) 不写 ELF 标头?

.elf格式内容