了解__libc_init_array(understanding the __libc_init_

2019-07-21 02:54发布

我观察__libc_init_array的源代码从http://newlib.sourcearchive.com/documentation/1.18.0/init_8c-source.html 。
但我不太了解这个函数所做的事情。

我知道,这些符号

/* These magic symbols are provided by the linker.  */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
extern void (*__fini_array_start []) (void) __attribute__((weak));
extern void (*__fini_array_end []) (void) __attribute__((weak));

在链接描述文件中定义。
链接脚本的一部分可能看起来像:

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  ...

然后我搜索与ELF-V1.1,GCC 4.7.2,LD和CodeSourcery的的文档的关键“init_array”(我使用CodeSourcery的G ++精简版)只得到什么。

我在哪里可以找到这些符号的规范?

Answer 1:

这些符号相关的C / C ++构造和析构启动和拆除是之前称为码/后main() 命名段.init.ctors.preinit_array.init_array是用C / C ++对象的初始化做的,部分.fini.fini_array.dtors是推倒。 开始和结束的符号定义的开始和相关的这样的操作代码段结束,可能会从运行时支持代码其他部分引用。

.preinit_array.init_array部分包含指针数组到将在初始化时被调用的函数。 所述.fini_array是将上破坏被调用的函数的阵列。 大概的开始和结束标记用于走在这些名单。

的使用这些符号代码一个很好的例子是可以找到这里libc的源为initfini.c 。 你可以看到,在启动时, __libc_init_array()被调用,这首先要求在节中的所有函数指针.preinit_array参照起点和终点标志。 然后调用_init()函数中.init节。 最后它调用节的所有函数指针.init_array 。 之后main()是完全拆机调用__libc_fini_array()会导致所有的功能.fini_array被调用,最后调用之前_fini() 请注意,似乎是在这个代码剪切和粘贴错误时,它计算的功能计数在拆卸打电话。 据推测,他们正在处理一个实时微控制器操作系统和从来没有遇到过这个节。



Answer 2:

这些特殊符号将最终由被引用PT_DYNAMIC生成的库的部分。 PT_DYNAMIC限定使动态链接成功所需要的各种资源(库依赖性,导出的符号,符号哈希表,初始化/ FINI阵列等)。

因此,在这些列表的任何功能将最终连接到PT_DYNAMIC期间动态链接过程部分和称为在适当的时候。 你可能想咨询的来源ldd了解更多信息。



Answer 3:

规格为这些对象是ELF头文件格式规范。 至少,为什么他们在那里。

他们作出以任何方式形状手段或形式的工作,除非你打算重写GLIC lib和一切可能会谈。 总之ELF头需要一个_start功能。 没有一个它不会启动二进制文件。

在libc库中有很大一部分是用汇编不是C不考虑这一点。 预数组函数是添加此报头的方式。

检查出的glibc极小,efl.git的例子GNU-CSU文件夹。 它也将数组作为一个斜线格式化字符串。 设置两个元件如静电,argv中和init_array阵列。 这将在稍后进行检查,以确定它们是否匹配。 它也需要更多的代码比你应该增加这种功能打破了这个过程还是比是指对要被单独留在家中的任何其他。 跟你玩的冰箱。



文章来源: understanding the __libc_init_array