为什么在_start之前调用glibc的csu / init-first.c中的_init,即使_start是ELF入口点?

我在玩GDB的rbreak .时候首先注意到了它rbreak . ,然后做了个小例子:

 (gdb) file hello_world.out Reading symbols from hello_world.out...done. (gdb) b _init Breakpoint 1 at 0x4003e0 (gdb) b _start Breakpoint 2 at 0x400440 (gdb) run Starting program: /home/ciro/bak/git/cpp/cheat/gdb/hello_world.out Breakpoint 1, _init (argc=1, argv=0x7fffffffd698, envp=0x7fffffffd6a8) at ../csu/init-first.c:52 52 ../csu/init-first.c: No such file or directory. (gdb) continue Continuing. Breakpoint 2, 0x0000000000400440 in _start () (gdb) continue Continuing. Breakpoint 1, 0x00000000004003e0 in _init () (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> breakpoint already hit 2 times 1.1 y 0x00000000004003e0 <_init> 1.2 y 0x00007ffff7a36c20 in _init at ../csu/init-first.c:52 2 breakpoint keep y 0x0000000000400440 <_start> breakpoint already hit 1 time 

请注意,有2个_init :一个在csu/init-first.c ,另一个似乎来自sysdeps/x86_64/crti.S 我正在谈论的是一个。

是不是_start应该是由链接器设置的入口点,并存储在ELF头? 什么机制使_init先运行? 它的目的是什么?

testing了GCC 4.8,glibc 2.19,GDB 7.7.1和Ubuntu 14.04。

Solutions Collecting From Web of "为什么在_start之前调用glibc的csu / init-first.c中的_init,即使_start是ELF入口点?"

在你的例子中,调试器首先停止的地方不是这个过程的真正开始。

在ELF标题中有程序解释器(动态链接器)的条目。 在Linux 64位上,它的值是/lib64/ld-linux-x86-64.so.2 。 内核将初始指令指针设置为该程序解释器的入口点。 它的符号名也是_start ,就像程序_start

动态链接程序完成其工作后,调用程序中的函数,如glibc中的_init ,它调用程序的入口点。

_start中的断点对动态链接器不起作用,因为它只接受程序_start的地址。

您可以使用readelf -h /lib64/ld-linux-x86-64.so.2找到入口点地址。

你也可以在_dl_start设置一个断点,然后打印回溯,看看这个函数是从动态链接器的_start调用的。

如果你下载了glibc的当前源代码,你可以从121行开始在glibc-2.21/sysdeps/x86_64/dl-machine.h找到动态加载器的入口点。