我正在按照教程为我自己的操作系统移植 NewLib 。
它说一旦我完成了我的 crt0,我必须“将它作为第一个对象链接”。我怎样才能做到这一点?
我正在按照教程为我自己的操作系统移植 NewLib 。
它说一旦我完成了我的 crt0,我必须“将它作为第一个对象链接”。我怎样才能做到这一点?
它说一旦我完成了我的 crt0,我必须“将它作为第一个对象链接”。
这正是所说的。当您的操作系统的应用程序被链接时,crt0 必须是链接器命令行上的第一个目标文件:在任何其他目标文件之前。
传统上,UNIX 链接器通过从第一个对象/库循环到最后一个对象/库开始查找来解析符号。放置crt0
为第一个目标文件确保系统符号(函数、变量)是从 crt0 文件中挑选出来的,而不是从其他文件中挑选出来的。
此外,正如 R.. 所指出的,传统的链接器假定应用程序的入口点位于代码段的开头。这也适用于链接页面上的源代码:代码中的第一个符号是_start
,程序入口点的常用名称。
例如,gcc -v a.c -o a
在我的 Debian 上运行(注意-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
。
在跳转到 之前main()
,c 运行时需要做初始化,这个工作由cert{i,n,0}
.
至少用于测试的一种方法是将 crt0.o 作为编译器或链接器命令行上的第一个文件。
对于生产,您可以将其放在链接器命令文件中。