【问题标题】:some questions about search order of GCC linker关于GCC链接器搜索顺序的一些问题
【发布时间】:2012-05-14 14:22:41
【问题描述】:

我对 gcc 链接顺序有一些疑问。 GCC man 说链接器从左到右搜索符号,默认情况下不重复搜索。这是我的测试:

main.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
        printf("HELLO WROLD\n");
        return 0;
}

printf.c

#include <stdio.h>
#include <stdlib.h>

int printf(const char *fmt, ...)
{
        write(1, "AAA\n", 4);
}

[root@lenovo testcode]# gcc -c -fno-builtin-printf *.c
[root@lenovo testcode]# gcc -o test main.o printf.o
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test printf.o main.o
[root@lenovo testcode]# ./test
AAA


[root@lenovo testcode]# ar rcs libprintf.a printf.o
[root@lenovo testcode]# gcc -o test libprintf.a main.o
[root@lenovo testcode]# ./test 
HELLO WROLD
[root@lenovo testcode]# gcc -o test main.o libprintf.a 
[root@lenovo testcode]# ./test 
AAA


[root@lenovo testcode]# gcc -shared -o libprintf.so printf.o 
[root@lenovo testcode]# gcc -o test libprintf.so  main.o 
[root@lenovo testcode]# export LD_LIBRARY_PATH=.
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test main.o libprintf.so 
[root@lenovo testcode]# ./test 
AAA

从结果可以看出.o和.o的顺序,.o和.so没有区别,只有.o和.a的顺序有效果。但这与 gcc 手册页不一致。那为什么呢?

【问题讨论】:

  • 我用过-v,但我还是不明白为什么。你能详细解释一下吗?
  • 我不能使用-nodefaultlibs,因为crt中的一些函数比如_start应该存在。
  • 我想我是 TL;DR-ed 之前。你认为 'it' 与 gcc amn 页面有什么不一致?
  • .o 和 .o,.o 和 .so 的顺序应该很重要,这意味着它应该得到与 .o 和 .a 相同的结果。不是,从我的结果中可以看出。

标签: linux gcc linker shared-libraries static-libraries


【解决方案1】:

gcc 确实从左到右处理目标文件。当你有

gcc -o test libprintf.a main.o

gcc 看到的第一个目标文件是libprintf.a。此时输出对象没有未解析的符号,因此libprintf.a 中的任何内容都没有被使用/需要。接下来,处理main.o,链接器记下printf 未解析的事实,然后继续处理能够解析未解析in main.oprintf 符号的隐式库。

同样,当你有:

gcc -o test main.o libprintf.a 

要处理的第一个目标文件是main.o,其中指出了未解析的符号printf,下一个要处理的是libprintf.a,链接器可以从中解析printf。当libc最终被处理时,printf已经被解析,所以libc中的printf的实例没有被使用。

与 .o 文件链接时:

gcc -o test main.o printf.o

libc 库再次被视为在命令行末尾指定,因此printf 符号从定义它的第一个(从左到右)目标文件中解析。

对于libprintf.so 两种情况,libc 库再次被视为在命令行末尾指定。与静态库情况不同的是,*.so 库的从左到右的顺序决定了运行时动态符号搜索的顺序。由于此顺序在隐式libc.so 之前有libprintf.so,因此使用libprintf.soprintf 的版本。

gcc -o test libprintf.so  main.o
gcc -o test main.o libprintf.so

作为额外的实验,您可以尝试:

gcc -o test main.o -lc libprintf.so

这应该显示libc.so 使用的printf 的版本,而不是libprintf.so,因为-lc 按从左到右的顺序排在libprintf.so 之前。

【讨论】:

  • 已编辑以添加对这些案例的解释...抱歉在最初的回复中忽略了这些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 2011-11-26
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多