我正在阅读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
。难道不应该是
_start
到main
吗?为什么不?如果我删除了对40077f
和40008f0
的两个调用并替换为nop
,会发生什么?基本上,要求libc有什么意义? 最佳答案
/* 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/