首页 > 解决方案 > 使用静态库时,GNU ld 生成没有符号的 ELF

问题描述

我正在尝试将多个目标文件打包到ar存档中,然后将存档传递给链接器。

我的 C 源文件foo.c包含这一行:

void foo();

使用 编译gcc -c foo.c时,生成的目标文件包含以下符号:

$ nm foo.o
0000000000000000 T foo

然后我将其存档:

$ ar rcs foo.a foo.o

存档现在包含foo.o具有相同符号的文件:

$ nm foo.a
foo.o:
0000000000000000 T foo

但是链接的 ELF 不包含名为 的符号foo

$ ld foo.a
$ nm a.out
0000000000401000 A __bss_start
0000000000401000 A _edata
0000000000401000 A _end
                 U _start

为什么不存在?

我想使用这种方法,因为我正在生成多个可执行文件变体,其中一个公共部分(一个存档,为简单起见未显示)和第二部分包含main符号(中的目标文件foo.a)。

标签: gcclinkersymbolsgnuld

解决方案


静态库通常链接如下。当链接器看到一个静态库时,它会获取到目前为止尚未解析的符号集,并在库中查找每个这样的符号。只有解析这些符号的对象才会包含在最终的二进制文件中。

要覆盖此行为,gnu ld请使用 switch --whole-archive。从手册页:

对于--whole-archive 选项后命令行中提到的每个存档,在链接中包含存档中的每个目标文件,而不是在存档中搜索所需的目标文件。这通常用于将存档文件转换为共享库,强制将每个对象包含在生成的共享库中。


推荐阅读