gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 00:26:34 25 4
gpt4 key购买 nike

我在玩 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com