ELF文件和其他符号

时间:2014-09-21 20:38:48

标签: linux glibc elf

我正在阅读有关ELF文件格式的文章,我注意到用C ++编写的一个小型hello world测试程序在_start符号中包含一些额外的初始化:

0000000000400770 <_start>:
...
      40077f:       49 c7 c0 60 09 40 00    mov    $0x400960,%r8
      400786:       48 c7 c1 f0 08 40 00    mov    $0x4008f0,%rcx
      40078d:       48 c7 c7 5d 08 40 00    mov    $0x40085d,%rdi
...

40077f__libc_csu_fini

4008f0__libc_csu_init

40085dmain

_start main不应该只是40077f吗?为什么不?如果我刚刚删除了对40008f0nop的所有来电并替换为{{1}},会发生什么?基本上,需要libc的意义是什么?

1 个答案:

答案 0 :(得分:2)

查看glibc source code

/* These functions are passed to __libc_start_main by the startup code.
   These get statically linked into each program.  For dynamically linked
   programs, this module will come from libc_nonshared.a and differs from
   the libc.a module in that it doesn't call the preinit array.  */


void
__libc_csu_init (int argc, char **argv, char **envp)
{
  /* For dynamically linked executables the preinit array is executed by
     the dynamic linker (before initializing any shared object).  */

#ifndef LIBC_NONSHARED
  /* For static executables, preinit happens right before init.  */
  {
    const size_t size = __preinit_array_end - __preinit_array_start;
    size_t i;
    for (i = 0; i < size; i++)
      (*__preinit_array_start [i]) (argc, argv, envp);
  }
#endif

#ifndef NO_INITFINI
  _init ();
#endif

  const size_t size = __init_array_end - __init_array_start;
  for (size_t i = 0; i < size; i++)
      (*__init_array_start [i]) (argc, argv, envp);
}

/* This function should not be used anymore.  We run the executable's
   destructor now just like any other.  We cannot remove the function,
   though.  */
void
__libc_csu_fini (void)
{
#ifndef LIBC_NONSHARED
  size_t i = __fini_array_end - __fini_array_start;
  while (i-- > 0)
    (*__fini_array_start [i]) ();

# ifndef NO_INITFINI
  _fini ();
# endif
#endif
}

这允许库初始化代码运行。链接到程序中的库可以使用gcc中的__attribute__((constructor))标记函数,此机制将在main之前运行这些函数,允许库在程序启动之前初始化它们。