我正在阅读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
40085d是指main
难道不应该是_startmain吗?为什么不?如果我删除了对40077f40008f0的两个调用并替换为nop,会发生什么?基本上,要求libc有什么意义?

最佳答案

查看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之前运行这些函数,允许库在程序启动之前初始化自己。

关于linux - ELF文件和其他符号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25963628/

10-16 02:25