假设我正在使用GCC
编译一个简单的 Hello World 程序。
当使用gcc -v hello-world.c
运行时,我们可以从输出中获取生成ELF二进制文件的最后一行:
/usr/libexec/gcc/x86_64-pc-linux-gnu/4.5.3/collect2 --eh-frame-hdr -m
elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crt1.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/crtbegin.o
-L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../x86_64-pc-linux-gnu/lib
-L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../.. /tmp/ccRykv97.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crtn.o
从这个输出中我们可以看到像crtbegin.o
和crtend.o
这样的对象被链接在一起。但链接器如何知道这些文件应该链接到togeter?
一个单独但类似的问题是,如果我不想使用标准C库,当给定包含这些函数定义的目标文件目录时,如何知道传递给它们所需的文件链接器,以便它不会抱怨未知符号?
答案 0 :(得分:3)
我们可以从输出中获取生成ELF二进制文件的最后一行
实际上不是生成ELF二进制文件的实际命令。 collect
依次调用ld
,而 命令会生成二进制文件。
链接器如何知道这些文件应该链接
没有。 GCC 告诉它(通过在命令行上提供它们)。
GCC有一个编译好的specs
文件,它是一个特定于域的语言小程序,告诉GCC它应该为链接器提供什么参数。
您可以使用specs
检查内置gcc -dumpspecs
。您会发现该程序实际上非常复杂,crtbegin.o
仅在-static
和-pie
或-shared
未使用时使用。 -shared
隐含crtbeginS.o
,-static
隐含crtbeginT.o
。
如果我不想使用标准C库
在这种情况下使用-nostdlib
标志。
给定一个包含这些函数定义的目标文件目录,如何知道传递给链接器所需的文件
定义您使用的函数的那些。 This可能有帮助。