GCC 4.5 vs 4.4与依赖关系链接 [英] GCC 4.5 vs 4.4 linking with dependencies

查看:141
本文介绍了GCC 4.5 vs 4.4与依赖关系链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我试图在GCC 4.4和GCC 4.5上做同样的操作时,我观察到了不同。因为我这样做的代码是专有的,所以我无法提供它,但我观察到类似的失败,这个简单的测试用例。

我基本上试图做的是让一个共享库(libb)依赖于另一个共享库(liba)。加载libb时,我认为应该加载liba - 即使libb不一定在liba中使用符号。



我在观察的是当我编译GCC 4.4,我观察到liba被加载,但是如果我用GCC 4.5编译,libb没有加载。



我有一个包含两个文件的小测试用例,ac和bc。文件内容:

  // a.c 
int a(){
return 0;
}

//b.c
int b(){
return 0;
}
//c.c
#include< stdio.h>
int a();
int b();

int main()
{
printf(%d \ n,a()+ b());
返回0;
}
//test.sh
$ CC -o liba.so a.c -shared
$ CC -o libb.so b.c -shared -L。 -la -Wl,-rpath-link。
$ CC c.c -L。 -lb -Wl,-rpath-link。
LD_LIBRARY_PATH =。 ./a.out

这是我输出的不同版本的GCC

  $ CC = gcc-4.4 ./test.sh 
1
$ CC = gcc-4.5 ./test.sh
/tmp/cceJhAqy.o:在main函数中:
cc :(。text + 0xf):未定义引用'a'
collect2:ld返回1退出状态
。 /test.sh:第4行:./a.out:没有这样的文件或目录
$ CC = gcc-4.6 ./test.sh
/tmp/ccoovR0x.o:在函数`main' :
cc :(。text + 0xf):未定义引用'a'
collect2:ld返回1退出状态
./test.sh:第4行:./a.out:没有这样的文件或目录
$

任何人都可以解释发生了什么吗?另外一点信息是libb.so上的ldd在GCC 4.4上显示liba.so,但在GCC 4.5上显示不了。


$ b 编辑



我将test.sh更改为以下内容:

  $ CC  - 共享-o liba.so ac 
$ CC -L。 -Wl, - 不需要-Wl, - copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link。
$ CC -L。 c.c -lb -Wl,-rpath-link。
LD_LIBRARY_PATH =。 ./a.out

这给了GCC 4.5的以下输出:

  / usr / bin / ld:/tmp/cc5IJ8Ks.o:对符号'a'的未定义引用
/ usr / bin / ld:备注:'a'在DSO ./liba.so中定义,因此请尝试将其添加到链接器命令行
./liba.so:无法读取符号:操作无效
collect2:ld返回1退出状态
./test.sh:第4行:./a.out:没有这样的文件或目录


DT_NEEDED 库在 ld 。以下是当前 man ld 的相关部分:
$ b


使用 - copy-dt-needed-entries 命令
中提到的动态库将按照它们的DT_NEEDED标签递归搜索到其他库,以便解析输出所需的符号二进制文件。如果使用
默认设置,则动态库自身将停止搜索动态库。没有DT_NEEDED链接将被遍历
来解析符号。

的一部分 - copy -dt-needed-entries 部分)。



GCC 4.4和GCC 4.5之间有一段时间(显然,请参阅这里 - 找不到任何真正权威的东西),默认从递归搜索改变为无递归搜索(因为你是无论如何,你可以(也应该)通过指定 liba 来修复它。 $ b 在您的最后一步链接中:

  $ CC cc -L。 -lb -la -Wl,-rpath-link。 

您可以通过运行您的链接器设置来确认(至少是该问题的一部分)更新的编译器和这个命令行:

  $ CC cc -L。 -Wl, -  copy-dt-needed-entries -lb -Wl, -  no-copy-dt-needed-entries \ 
-Wl,-rpath-link。


I am observing a difference when trying to do the same operation on GCC 4.4 and GCC 4.5. Because the code I am doing this with is proprietary, I am unable to provide it, but I am observing a similar failure with this simple test case.

What I am basically trying to do is have one shared library (libb) depend on another shared library (liba). When loading libb, I assume that liba should be loaded as well - even though libb is not necessarily using the symbols in liba.

What I am observing is when I compile with GCC 4.4, I observe that the liba is loaded, but if I compile with GCC 4.5, libb is not loaded.

I have a small test case that consists of two files, a.c and b.c . The contents of the files:

//a.c
int a(){ 
    return 0; 
}

//b.c
int b(){
    return 0;
}
//c.c
#include <stdio.h>
int a();
int b();

int main()
{
    printf("%d\n", a()+b());
    return 0;
}
//test.sh    
$CC -o liba.so a.c -shared
$CC -o libb.so b.c -shared -L. -la -Wl,-rpath-link .
$CC c.c -L. -lb -Wl,-rpath-link .
LD_LIBRARY_PATH=. ./a.out

This is my output with different versions of GCC

$ CC=gcc-4.4 ./test.sh
1
$ CC=gcc-4.5 ./test.sh
/tmp/cceJhAqy.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$ CC=gcc-4.6 ./test.sh
/tmp/ccoovR0x.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$ 

Can anyone explain what is happening? Another extra bit of information is that ldd on libb.so does show liba.so on GCC 4.4 but not on GCC 4.5.

EDIT

I changed test.sh to the following:

$CC -shared -o liba.so a.c
$CC -L. -Wl,--no-as-needed -Wl,--copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link . 
$CC -L. c.c -lb -Wl,-rpath-link . 
LD_LIBRARY_PATH=. ./a.out

This gave the following output with GCC 4.5:

/usr/bin/ld: /tmp/cc5IJ8Ks.o: undefined reference to symbol 'a'
/usr/bin/ld: note: 'a' is defined in DSO ./liba.so so try adding it to the linker command line
./liba.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory

解决方案

There seems to have been changes in how DT_NEEDED libraries are treated during linking by ld. Here's the relevant part of current man ld:

With --copy-dt-needed-entries dynamic libraries mentioned on the command line will be recursively searched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary. With the default setting however the searching of dynamic libraries that follow it will stop with the dynamic library itself. No DT_NEEDED links will be traversed to resolve symbols.

(part of the --copy-dt-needed-entries section).

Some time between GCC 4.4 and GCC 4.5 (apparently, see some reference here - can't find anything really authoritative), the default was changed from the recursive search, to no recursive search (as you are seeing with the newer GCCs).

In any case, you can (and should) fix it by specifying liba in your final link step:

$CC c.c -L. -lb -la -Wl,-rpath-link .

You can check that this linker setting is indeed (at least part of) the issue by running with your newer compilers and this command line:

$CC c.c -L. -Wl,--copy-dt-needed-entries -lb -Wl,--no-copy-dt-needed-entries \
         -Wl,-rpath-link .

这篇关于GCC 4.5 vs 4.4与依赖关系链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆