![链接器标志之间的差异](https://linux22.com/image/135943/%E9%93%BE%E6%8E%A5%E5%99%A8%E6%A0%87%E5%BF%97%E4%B9%8B%E9%97%B4%E7%9A%84%E5%B7%AE%E5%BC%82.png)
我正在向 Linux 内核添加 C++ 运行时和异常支持。为此,我需要提供我自己的库lib/gcc
,而lib/libstdc++
不是编译器提供的标准库。
因此,我对要传递给链接器的标志感到困惑。在普通内核的顶层Makefile中,LD = $(CROSS_COMPILE)ld
它使内核能够使用默认的标准库和启动文件。对于我的内核,我LD = $(CROSS_COMPILE)ld -nostdlib -nodefaultlibs -nostartfiles
按照文档中的说明使用。我从中了解到的海湾合作委员会文档传递-nostdlib
给链接器就是传递两者-nodefaultlibs -nostartfiles
。这些标志实际上有什么区别?
答案1
这些标志定义在GCC 的规范文件,因此确定它们之间差异的最佳方法是查看那里:
gcc -dumpspecs
相关部分是link_command
定义。这表明-nostdlib
、-nodefaultlibs
和-nostartfiles
具有以下影响:
%{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}}
— 这会根据需要添加libgcc
,libpthread
,libc
,使用libieee
宏以及lib
和libgcc
spec 字符串;%{!nostdlib:%{!nostartfiles:%S}}
— 这会添加startfile
规范字符串 ,它指定要添加以处理启动的对象文件(crti.o
等)%{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end} %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}
— 这添加了虚拟表验证libvtv
%{!nostdlib:%{!nodefaultlibs:%{mmpx:%{fcheck-pointer-bounds: %{static:--whole-archive -lmpx --no-whole-archive %:include(libmpx.spec)%(link_libmpx)} %{!static:%{static-libmpx:-Bstatic --whole-archive} %{!static-libmpx:--push-state --no-as-needed} -lmpx %{!static-libmpx:--pop-state} %{static-libmpx:--no-whole-archive -Bdynamic %:include(libmpx.spec)%(link_libmpx)}}}}%{mmpx:%{fcheck-pointer-bounds:%{!fno-chkp-use-wrappers: %{static:-lmpxwrappers} %{!static:%{static-libmpxwrappers:-Bstatic} -lmpxwrappers %{static-libmpxwrappers: -Bdynamic}}}}}}}
——这个处理libmpx
%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address): %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)} %{static:%ecannot specify -static with -fsanitize=address}} %{%:sanitize(thread): %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)} %{static:%ecannot specify -static with -fsanitize=thread}} %{%:sanitize(undefined):%{static-libubsan:-Bstatic} -lubsan %{static-libubsan:-Bdynamic} %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}} %{%:sanitize(leak): %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}}}}
— 这处理各种消毒选项%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}
— 这会添加堆栈保护选项并重复 C 链接序列(其库已在开始时指定)%{!nostdlib:%{!nostartfiles:%E}}
— 这会添加endfile
规范字符串,它指定要添加的对象文件以处理剩余内容(crtfastmath.o
等crtend.o
)
正如您从文档中了解到的,是和-nostdlib
的超集。它还禁用虚拟表验证。-nodefaultlibs
-nostartfiles
因此-nostdlib
足以禁用所有相关功能;-nodefaultlibs
并且-nostartfiles
不要向其中添加任何内容。 (但提及它们也没什么坏处。)