我基本上试图做的是让一个共享库(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 来修复它。 在您的最后一步链接中:
$ 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.outThis 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.outThis 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与依赖关系链接
发布评论