假设我正在使用 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
这样的对象被链接在一起了。但是链接器如何知道这些文件应该链接在一起呢?
一个单独但类似的问题是,如果我不想使用标准 C 库,当给定一个包含这些函数定义的目标文件目录时,如何知道需要传递给的文件链接器,这样它就不会提示未知符号?
最佳答案
we could get the last line from the output which generates the ELF binary
事实上 并不是生成 ELF 二进制文件的实际命令。 collect
依次调用 ld
,那个 命令生成二进制文件。
how does the linker know that these files should be linked
事实并非如此。 GCC 告诉它(通过在命令行上提供它们)。
GCC 有一个内置的 specs
文件,这是一个特定领域的语言小程序,它告诉 GCC 它应该为链接器提供什么参数。
您可以使用 gcc -dumpspecs
检查内置的 specs
。你会看到程序其实很复杂,crtbegin.o
只在-static
和-pie
或时使用-shared
不是。 -shared
表示crtbeginS.o
,-static
表示crtbeginT.o
。
if I don't want to use the standard C library
在这种情况下使用 -nostdlib
标志。
given a directory of object files that contain the definitions of these functions, how to know the files that are needed to pass to the linker
定义您使用的函数的那些。 This可能有帮助。
关于gcc - 链接器如何知道将哪些文件链接在一起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8505682/