gcc添加到linux ELF中的功能是什么? [英] What functions does gcc add to the linux ELF?

查看:202
本文介绍了gcc添加到linux ELF中的功能是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将c(或asm)中的hello-world-like程序与 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

他们是什么和为了什么?它在某处被描述了吗?谷歌搜索没有帮助。

解决方案

其中大多数是在main程序本身之前或之后执行代码的各种方法,大多数住在 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节调用。
.eh_frame 信息库用于异常处理和类似功能(例如用 __ attribute __((cleanup(..))声明的函数) )



 

  00000000004004e0 T __libc_csu_init 
0000000000400550 T __libc_csu_fini

这些运行任何程序级初始值设定项和终结符(有点像整个程序的构造函数/析构函数)。
如果你定义了如下函数:

pre $ void $ __attribute__((构造函数))mefirst(){
/ * ...在这里做些什么... * /
}

void __attribute__((析构函数))melast(){
/ * ...在这里做些事情.. 。* /
}

它们将在 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 Jester的问题评论中的
    包含一个不错的图表和一个小样本
    程序说明这些事情的总体顺序,以及
    如何从C访问这些功能。

  • / em>'和' dtors '分别是
    '构造函数'和'析构函数'的缩写。


  • 当您的程序是由多个目标文件构建的
    时,全局构造函数/析构函数和对象文件
    构造函数/析构函数之间的差异最为明显。标记为' T '( __ libc_csu_init,__libc_csu_fini,_fini
    的符号为全局符号(外部可见),剩余者(标记为 t ')不是。

  • When linking a hello-world-like program in c (or asm) with gcc it will add some stuff into the result executable object file. I know only about runtime dynamic linker and _start entry point but what is the kind of these added functions?

    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
    

    What are they and what for? Is it described somewhere? Googling does not help.

    解决方案

    Most of these are various methods to execute code before or after the "main" program itself and most live in crtstuff.c ( https://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c ). They exist to support features of various C-like programming languages, but they can be accessed in C as well. It perhaps seems over complicated because some of these represent legacy baggage and some the variation needed to support the various different architectures that GCC runs on.

     

    From your list, one by one (or two by two):

    00000000004003f0 t deregister_tm_clones
    0000000000400430 t register_tm_clones
    

    Transactional memory is intended to make programming with threads simpler. It is an alternative to lock-based synchronization. These routines tear down and setup, respectively, a table used by the library (libitm) which supports these functions. More info on TM here https://gcc.gnu.org/wiki/TransactionalMemory and here http://pmarlier.free.fr/gcc-tm-tut.html

     

    0000000000400470 t __do_global_dtors_aux
    

    Runs all the global destructors on exit from the program on systems where .fini_array is not available.

     

    0000000000400490 t frame_dummy
    

    This function lives in the .init section. It is defined as void frame_dummy ( void ) and its whole point in life is to call __register_frame_info_bases which has arguments. Apparently calls to functions with arguments from the .init section can be unreliable, hence this function so __register_frame_info_bases doesn't get called directly from the .init section. The .eh_frame info bases are used for exception handling and similar features (e.g. functions declared with __attribute__((cleanup(..)))).

     

    00000000004004e0 T __libc_csu_init
    0000000000400550 T __libc_csu_fini
    

    These run any program-level initializers and finalizers (kind of like constructors/destructors for your whole program). If you define functions like:

    void __attribute__ ((constructor)) mefirst () {
        /* ... do something here ... */
    }
    
    void __attribute__ ((destructor)) melast () {
        /* ... do something here ... */
    }
    

    they will be called before and after main() respectively by these routines. See also https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

     

    0000000000400554 T _fini
    

    This is a now-deprecated way to run a program-level (object file-level actually) destructor (a little info on this can be found in man dlclose). The corresponding obsolete function for constructors is __init.

     

    0000000000600668 t __frame_dummy_init_array_entry
    0000000000600668 t __init_array_start
    

    These mark the end and start of the .init_array section, which contains pointers to all the program-level initializers (see __libc_csu_init above).

     

    0000000000600670 t __do_global_dtors_aux_fini_array_entry
    0000000000600670 t __init_array_end
    

    These mark the end and start of the .fini_array section, which contains pointers to all the program-level finalizers (see __libc_csu_fini above).

     

    [EDIT] Some Additional Notes:

    • The link http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html from the Jester's question comment contains a nice diagram and a small sample program illustrating the overall order these things run as well as how to access some of these features from C.

    • The terms 'ctors' and 'dtors' are abbreviations for 'constructors' and 'destructors' respectively.

    • The difference between global constructors/destructors and object-file constructors/destructors is most apparent when your program is constructed from multiple object files.

    • The symbols marked 'T' (__libc_csu_init, __libc_csu_fini, _fini) are "global" (externally visible), the remainer (marked 't') are not.

    这篇关于gcc添加到linux ELF中的功能是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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