Компоновщик, похоже, игнорирует библиотеку и по умолчанию использует более старую версию - PullRequest
0 голосов
/ 19 октября 2018

Я создал отладочную версию совместно используемой библиотеки (OpenSSL), чтобы я мог выполнить определенную функцию с помощью отладчика, чтобы лучше понять, что происходит.

Однако у меня трудное времяна самом деле связь с отладочной версией, которую я построил.По какой-то причине, независимо от того, что я делаю, компоновщик всегда связывается с предустановленной версией системы, даже если обе версии находятся в каталоге usr/lib, программные ссылки настроены правильно (AFAIK), и я явноукажите отладочную библиотеку в командной строке при компиляции.

Итак, оригинальная (установленная система) версия общей библиотеки:

>ls /usr/lib/x86_64-linux-gnu/ -lh | grep libssl
lrwxrwxrwx 1 root root   15 Sep 23  2016 libssl.so -> libssl.so.1.0.0
-rw-r--r-- 1 root root 386K Sep 23  2016 libssl.so.1.0.0

И отладочная версия , которую я скомпилировал из исходного кода и настроил как общую библиотеку (используя флаг fPIC для всех объектных файлов):

 >ls /usr/lib/ -lh | grep libssl
lrwxrwxrwx  1 root root   29 Oct 19 11:31 libssldebug.so -> /usr/lib/libssldebug.so.1.0.2
-rwxr-xr-x  1 root root 2.3M Oct 19 00:53 libssldebug.so.1.0.2

И то же самое с другими общими OpenSSLбиблиотека, libcrypto.У меня есть libcryptodebug.so.1.0.2 и соответствующая программная ссылка в /usr/lib.

Итак, я пытаюсь создать исполняемый файл и ссылку на отладочную разделяемую библиотеку, например:

 >g++ test.cpp -o test -std=c++14 -lssldebug -lcryptodebug -I openssl-1.0.2p/include/

И он компилируется и связывается без ошибок.

И ДА ... когда я проверяю исполняемый файл с ldd, я вижу:

 >ldd test
        linux-vdso.so.1 (0x00007ffcaa39b000)
        libssl.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007ff717d37000)
        libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007ff71793b000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff717630000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff71732f000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff717119000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff716d6e000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff716b6a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff717f98000)

Так что, хотя я явносвязан с -lssldebug, и он скомпилирован и связан без ошибок, ldd по-прежнему показывает, что компоновщик по какой-то причине связывается с неотладочной версией (/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0).Я также попытался запустить ldconfig и затем перекомпилировать / связать, но он все еще связывается со старой (не отладочной) версией.

Так что здесь происходит?Что я делаю неправильно, что заставляет его молча игнорировать аргументы компоновщика командной строки и почему-то просто по умолчанию использовать не-отладочную версию (которая имеет совершенно другое общее имя библиотеки!) Каким-то образом?

1 Ответ

0 голосов
/ 20 октября 2018

Так что, хотя я явно связался с -lssldebug, и он скомпилирован и связан без ошибок, ldd по-прежнему показывает, что компоновщик по какой-то причине связывается с неотладочной версией (/ usr / lib / x86_64-linux-gnu / libssl.so.1.0.0

Вы смешиваете статическое связывание и загрузку во время выполнения (иногда также называемое динамическим связыванием).

Когда вы связываете с g++ test.cpp ... -lssldebug ..., вы связаны с libssldebug.so, но (как сообщает ldd вывод), что библиотека не используется во время загрузки во время выполнения.

Это происходитпотому что libssldebug.so имеет специальный динамический тег DT_SONAME, который содержит "libssl.so.1.0.0", и статический компоновщик записывает это имя в качестве библиотеки для загрузки во время выполнения.

Вы можете подтвердитьэто с помощью:

readelf -d libssldebug.so | grep SONAME

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

readelf -d ./test | grep NEEDED

Теперь, когда вы понимаете проблему, как ее исправитьэто?

Один из двух способов:

  1. ЙоВы можете изменить SONAME, закодированный в libssldebug.so, связав его с -Wl,--soname=libssldebug.so.1.0.2, а затем заново связав вашу test программу.Используйте приведенные выше команды readelf, чтобы убедиться, что SONAME и NEEDED теперь содержат "libssldebug.so.1.0.2", а затем ldd, чтобы убедиться, что libssldebug.so.1.0.2 - это то, что будет использовать загрузчик времени выполнения.
  2. В качестве альтернативыможет быть проще установить libssldebug.so в другой каталог (скажем, /tmp/libssldebug), создать символическую ссылку libssl.so.1.0.0 -> lissldebug.so в этом каталоге, а затем попросить загрузчика среды выполнения сначала выполнить поиск в этом каталоге с помощью g++ test.cpp ... -Wl,--rpath=/tmp/libssldebug.При таком решении исполняемый файл все равно будет искать libssl.so.1.0.0, но он будет искать его в каталоге /tmp/libssldebug first и найдет вашу копию.
...