我正按照a tutorial为我自己的操作系统移植NewLib。
它说,一旦我完成了我的crt0,我必须“将它作为第一个对象链接”。我怎么能这样做?
答案 0 :(得分:4)
它说,一旦我完成了我的crt0,我必须“将它作为第一个对象链接”。
这恰恰意味着什么。当链接到OS的应用程序时,crt0必须是链接器命令行上的第一个目标文件:在任何其他目标文件之前。
传统上,UNIX链接器通过从第一个对象/库循环到最后一个对象/库开始查找来解析符号。将crt0
作为第一个目标文件可确保从crt0文件中选择系统符号(函数,变量),而不是其他文件。
此外,正如R ..所指出的,传统链接器假设应用程序的入口点位于代码段的开头。这也适用于链接页面上的源代码:代码中的第一个符号是_start
,是程序入口点的通常名称。
E.g。在我的Debian上运行gcc -v a.c -o a
(请注意-v
),可以看到以下链接命令(为了便于阅读,我添加了新行):
/usr/lib/gcc/i486-linux-gnu/4.4.4/collect2
--build-id
--eh-frame-hdr
-m elf_i386
--hash-style=both
-dynamic-linker /lib/ld-linux.so.2
-o a
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crti.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtbegin.o
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib
-L/lib/../lib
-L/usr/lib/../lib
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../..
/tmp/ccndJ4YV.o
-lgcc
--as-needed
-lgcc_s
--no-as-needed
-lc
-lgcc
--as-needed
-lgcc_s
--no-as-needed
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crtn.o
可以看到crt1是命令行上的第一个对象。查看我的系统-m elf_i386
上的链接描述文件(find /usr -name '*elf_i386*'
- > /usr/lib/ldscripts/elf_i386.x
- >)可以验证Linux上没有crt0
,但有: crt1
,crti
,crtbegin
,crtend
,crtn
。并且应用程序对象文件(上例中的/tmp/ccndJ4YV.o
)放在crtbegin
和crtend
之间。
答案 1 :(得分:0)
至少测试的一种方法是将crt0.o作为编译器或链接器命令行上的第一个文件。
对于生产,您将它放在链接器命令文件中。
答案 2 :(得分:0)
在跳转到main()
之前,c运行时需要进行初始化,此作业由cert{i,n,0}
处理。