链接器似乎忽略了库,默认为旧版本

时间:2018-10-19 15:43:47

标签: c++ gcc linker shared-libraries linker-errors

我已经建立了共享库(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相同。我在/usr/lib中有一个libcryptodebug.so.1.0.2和一个相应的软链接。

因此,我尝试构建可执行文件并针对调试共享库进行链接,如下所示:

 >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仍显示链接器由于某种原因正在与非调试版本链接({{1 }})。我也尝试过运行/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0,然后重新编译/链接,但是它仍然与旧的(非调试)版本链接。

那么这是怎么回事?我做错了什么,导致它默默地忽略了命令行链接器参数,并以某种方式默认使用非调试版本(具有完全不同的共享库名!)。

1 个答案:

答案 0 :(得分:1)

  

因此,即使我显式地链接了-lssldebug,并且它进行了编译和链接也没有错误,ldd仍显示链接器由于某种原因正在与非调试版本链接(/ usr / lib / x86_64-linux-gnu /libssl.so.1.0.0

您正在混淆静态链接和运行时加载(有时也称为动态链接)。

g++ test.cpp ... -lssldebug ...链接时,您与libssldebug.so链接,而,但是(正如ldd的输出告诉您),库不是 < / em>在运行时加载期间使用。

之所以会这样,是因为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命令来验证SONAMENEEDED现在包含"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 中搜索它,并找到您的副本。