GCC 4.5 против 4.4 связывание с зависимостями - PullRequest
8 голосов
/ 04 января 2012

Я наблюдаю разницу при попытке выполнить одну и ту же операцию в 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());
    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

Это мой вывод с различными версиями 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
$ 

Может кто-нибудь объяснить, что происходит?Еще одна дополнительная информация - ldd на libb.so показывает liba.so на GCC 4.4, но не на GCC 4.5.

EDIT

Я изменил test.shк следующему:

$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

Это дало следующий вывод с 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

1 Ответ

11 голосов
/ 04 января 2012

Кажется, произошли изменения в том, как DT_NEEDED библиотеки обрабатываются при связывании ld.Вот соответствующая часть текущего man ld:

С --copy-dt-needed-entries динамическими библиотеками, упомянутыми в командной строке, будет производиться рекурсивный поиск, после их тегов DT_NEEDED для других библиотек, для разрешения символов, требуемыхбинарный выход.Однако при настройке по умолчанию поиск динамических библиотек, которые следуют за ним, будет остановлен самой динамической библиотекой.Ссылки DT_NEEDED не будут проходить для разрешения символов.

(часть раздела --copy-dt-needed-entries).

Некоторое время между GCC 4.4 и GCC 4.5 (очевидно, см. Некоторые ссылки здесь - не могу найти ничего действительно авторитетного), значение по умолчанию было изменено с рекурсивного поиска на отсутствие рекурсивного поиска (как вы видите в более новых GCC).

В любом случае,вы можете (и должны) это исправить, указав liba в своем последнем шаге ссылки:

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

Вы можете проверить, что этот параметр компоновщика действительно (по крайней мере, часть) проблемы, запустив новую версиюкомпиляторы и эта командная строка:

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