gcc给linux ELF增加了什么功能?

What functions does gcc add to the linux ELF?

当用 c(或 asm)链接一个类似 hello-world 的程序时 gcc 它会在结果可执行目标文件中添加一些东西。我只知道运行时动态链接器和 _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

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

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

从你的列表中,一个接一个(或两个接两个):

00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones

事务内存旨在简化线程编程。 它是 lock-based 同步的替代方法。 这些例程分别拆除和设置支持这些功能的库 (libitm) 使用的 table。 有关 TM 的更多信息,请点击此处 https://gcc.gnu.org/wiki/TransactionalMemory and here 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

这些 运行 任何 program-level 初始化器和终结器(有点像整个程序的 constructors/destructors)。 如果您定义如下函数:

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

这是 now-deprecated 到 运行 一个 program-level (对象 file-level 实际上)析构函数的方法(有关此的一些信息可以在 man dlclose). 构造函数对应的废弃函数是 __init.

0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start

这些标记 .init_array 部分的结束和开始,其中包含指向所有 program-level 初始值设定项的指针(参见上面的 __libc_csu_init ).

0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end

这些标记 .fini_array 部分的结束和开始,其中包含指向所有 program-level 终结器的指针(参见上面的 __libc_csu_fini ).

[编辑] 一些附加说明:

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

  • 术语“ctors”和“dtors”是 分别为“构造函数”和“析构函数”。

  • 全局constructors/destructors和object-file的区别 constructors/destructors 在您的程序是 从多个目标文件构建。

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