如果目标文件是由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
![](https://img.haomeiwen.com/i211722/7475c813ef4c4f0a.png)
网友评论