如果目標文件是由C代碼編譯生成的,整個程序的入口點是crt1.o中提供的_start,它首先做一些初始化工作(以下稱為啟動例程, Startup Routine),然后調用C代碼中提供的main函數。所以,以前我們說main函數是程序的入口點其實不準確, _start才是真正的入口點,而main函數是被_start調用的。在gcc編譯過程中,其默認的 鏈接過程
$ ld /usr/lib/crt1.o /usr/lib/crti.o main.o -o main -lc -dynamiclinker /lib/ld-linux.so.2
//也就是說,除了crt1.o之外其實還有crti.o,這兩個目標文件和我們的main.o鏈接在一起生成可執行文件main。
//-lc表示需要鏈接libc庫,-dynamic-linker /lib/ld-linux.so.2指定動態鏈接器是/lib/ld-linux.so.2
那么crt1.o和crti.o里面都有什么呢?我們可以用readelf命令查看。在這里我們只關心符號表,如果只看符號表,可以用readelf命令的-s選項,也可以用nm命令
C程序的鏈接過程如下
$ nm /usr/lib/crt1.o
00000000 R _IO_stdin_used
00000000 D __data_start
U __libc_csu_finic //U undefined
U __libc_csu_init
U __libc_start_main
00000000 R _fp_hw
00000000 T _start
00000000 W data_start
U main$ nm /usr/lib/crti.o
U _GLOBAL_OFFSET_TABLE_
w __gmon_start__00000000
T _fini00000000
T _init
Paste_Image.png