GCC和LD的链接有什么区别?

Wei*_*Wen 8 gcc shared-libraries ld

最近我正在创建一个可加载的模块,并发现两者

gcc -fPIC --shared -o foo.so.1 foo.c
Run Code Online (Sandbox Code Playgroud)

gcc -fPIC --shared -c foo.c
ld --shared -o foo.so.2 foo.o
Run Code Online (Sandbox Code Playgroud)

可以达到同样的效果.

我还发现foo.so.1大于foo.so.2大约3KB,并且

gcc -### -fPIC --shared -o foo.so.1 foo.c
Run Code Online (Sandbox Code Playgroud)

透露GCC将foo.c以外的东西添加到foo.so.1中(例如,crtendS.o和crtn.o):

/usr/lib/gcc/x86_64-linux-gnu/4.7/collect2 "--sysroot=/" --build-id --no-add-needed --eh-frame-hdr -m elf_x86_64 "--hash-style=both" -shared -o foo.so.1 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/4.7 -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../.. /tmp/cc3JBdCJ.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crtn.o
Run Code Online (Sandbox Code Playgroud)

由于foo.so.1和foo.so.2都可以通过dlopen加载,我想知道:

  1. 这两种链接方法有什么区别?
  2. crtendS.o和crtn.o对创建的库中的函数有什么影响吗?

AnT*_*AnT 6

原则上没有区别.当你"通过gcc链接"它实际上调用ld.如果您在"通过gcc链接"链接阶段收到消息,您将立即看到它实际上来自ld.如果要将一些特定于ld的命令行选项传递给ld,gcc的命令行界面具有专门用于此目的的功能(-Xlinker-Wl选项).

至于其他对象文件......它们可能包含编译器隐式添加的全局加载时库初始化/去初始化代码.(请求标准库?)您可以在此处找到有关它的一些信息:https://gcc.gnu.org/onlinedocs/gccint/Initialization.html