2015-07-13 58 views
7

我首先注意到它,而與GDB的rbreak .玩,然後做了一個小例子:爲什麼在_start之前調用glibc的csu/init-first.c中的_init,即使_start是ELF入口點?

(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頭?什麼機制使_init先運行?它的目的是什麼?

測試GCC 4.8,glibc 2.19,GDB 7.7.1和Ubuntu 14.04。

+0

沒有真正的動態加載程序的入口點。 ELF中定義了init部分。看看[THIS](http://l4u-00.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node3.html)你也可以試試'readelf -d yourelf'來檢查INIT和FINI部分。無論如何,如果你用-nostdlib編譯那些部分是可以避免的。 – LPs

回答

8

在您的示例中,調試器首先停止的地方並不是過程的真正開始。

在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的電流源代碼,你可以在glibc-2.21/sysdeps/x86_64/dl-machine.h找到開始對線路121

+0

謝謝! glibc非常龐大,它還包含裝載程序。 –

相關問題