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

标签 c linux gcc gdb glibc

我在玩 GDB 的 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。我说的是 csu 一个。

难道 _start 应该是链接器设置的入口点,并存储在 ELF header 中吗?什么机制让 _init 首先运行?它的用途是什么?

在 GCC 4.8、glibc 2.19、GDB 7.7.1 和 Ubuntu 14.04 上测试。

最佳答案

在您的示例中,调试器首先停止的位置并不是该过程的真正开始。

在 ELF header 中有一个程序解释器(动态链接器)条目。在 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 的当前源代码,您可以在 glibc-2.21/sysdeps/x86_64/dl-machine.h 从第 121 行开始找到动态加载器的入口点。

关于c - 为什么 glibc 的 csu/init-first.c 中的 _init 在 _start 之前被调用,即使 _start 是 ELF 入口点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31379422/

相关文章:

linux - 给定一个 IP 地址,在同一子网中查找接口(interface)

FriendlyARM 的 Linux 内核编译器

c - 假设简化乘法时不会发生有符号溢出

c - 如何使用 wsdl2c 工具构建启用 SSL 的客户端代码以与 axis2 一起使用?

c - 编译成c的高级系统语言?

c - 如何在 C 中查找多维数组的维数

编译时函数执行

linux - lsof 输出大于 ulimit -Hn

linux - FTDI 设备的 udev 规则在 VMware Ubuntu 16.04 中不起作用

c++ - __PRETTY_FUNCTION__ : Can a return type contain parentheses?