简体   繁体   English

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

[英]Linker seems to ignore library and default to older version

I've built a debug version of a shared library (OpenSSL) so I can step through a certain function with a debugger to better understand what's going on. 我已经构建了共享库(OpenSSL)的调试版本,因此可以通过调试器逐步完成某些功能,以更好地了解发生了什么。

However, I'm having a difficult time actually linking with the debug version I've built. 但是,实际上很难与我构建的调试版本链接。 For some reason, no matter what I do, the linker always ends up linking with the pre-installed system version, even though both versions are in the usr/lib directory, the soft-links are setup correctly (AFAIK), and I explicitly specify the debug lib on the command line when compiling. 出于某种原因,无论我做什么,链接器总是最终会链接到预安装的系统版本,即使两个版本都位于usr/lib目录中,软链接也已正确设置(AFAIK),并且我明确在编译时在命令行上指定调试库。

So the original (system-installed) version of the shared library is: 因此,共享库的原始版本(系统安装)为:

>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

And the debug version , which I compiled from source and configured as a shared library (using the fPIC flag for all object files), is: 我从源代码编译并配置为共享库(对于所有目标文件使用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

And it's the same with the other OpenSSL shared library, libcrypto. 其他OpenSSL共享库libcrypto也是如此。 I have a libcryptodebug.so.1.0.2 and a corresponding soft link in /usr/lib . 我在/usr/lib有一个libcryptodebug.so.1.0.2和一个相应的软链接。

So, I try to build an executable and link against the debug shared lib like this: 因此,我尝试构建可执行文件并针对调试共享库进行链接,如下所示:

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

And it compiles and links with no errors. 并且它编译和链接没有错误。

And YET... when I examine the executable with ldd , I see: 还有...当我用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)

So even though I explicitly linked with -lssldebug , and it compiled and linked with no errors, ldd still shows that the linker for some reason is linking with the non-debug version ( /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 ). 因此,即使我显式地链接了-lssldebug ,并且它已编译并没有错误地链接, ldd仍显示链接器出于某种原因正在与非调试版本( /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 )。 I also tried running ldconfig and then recompiling/linking, but it still links with the old (non-debug) version. 我也尝试过运行ldconfig ,然后重新编译/链接,但是它仍然与旧版本(非调试)链接。

So what is going on here? 那么这是怎么回事? What am I doing incorrectly that causes it to silently ignore the command line linker arguments and somehow just default to using the non-debug version (which has a completely different shared lib name!) somehow? 我做错了什么,导致它默默地忽略了命令行链接器参数,并以某种方式默认使用非调试版本(它具有完全不同的共享库名!)?

So even though I explicitly linked with -lssldebug, and it compiled and linked with no errors, ldd still shows that the linker for some reason is linking with the non-debug version (/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 因此,即使我显式地链接了-lssldebug,并且它编译并没有错误地链接,ldd仍显示链接器由于某种原因正在链接非调试版本(/ usr / lib / x86_64-linux-gnu / libssl。 so.1.0.0

You are mixing up static linking, and runtime loading (sometimes also called dynamic linking). 您正在混合静态链接和运行时加载(有时也称为动态链接)。

When you link with g++ test.cpp ... -lssldebug ... , you are linking with libssldebug.so , but (as ldd output tells you) that library is not used during runtime loading. 当您与g++ test.cpp ... -lssldebug ...链接时,您正在libssldebug.so链接,但是(如ldd输出所示)在运行时加载期间使用该库。

That is happening because libssldebug.so has a special dynamic tag DT_SONAME , which contains "libssl.so.1.0.0" , and the static linker records that name as the library to be loaded at runtime. 发生这种情况是因为libssldebug.so具有一个特殊的动态标签DT_SONAME ,其中包含"libssl.so.1.0.0" ,并且静态链接程序将该名称记录为要在运行时加载的库。

You can confirm this with: 您可以通过以下方式进行确认:

readelf -d libssldebug.so | grep SONAME

You can examine the libraries that runtime loader will try to locate for a given executable with: 您可以使用以下方法检查运行时加载程序将尝试查找给定可执行文件的库:

readelf -d ./test | grep NEEDED

Now that you understand the problem, how do you fix it? 现在您已经了解了问题,该如何解决?

One of two ways: 两种方式之一:

  1. You could change the SONAME encoded in libssldebug.so , by relinking it with -Wl,--soname=libssldebug.so.1.0.2 , and then relinking your test program. 您可以通过将它与-Wl,--soname=libssldebug.so.1.0.2-Wl,--soname=libssldebug.so.1.0.2重新链接,然后重新链接您的test程序来更改SONAME编码的libssldebug.so Use above readelf commands to verify that SONAME and NEEDED now contain "libssldebug.so.1.0.2" , and then ldd to verify that libssldebug.so.1.0.2 is what the runtime loader will use. 使用上面的readelf命令来验证SONAMENEEDED现在包含"libssldebug.so.1.0.2" ,然后使用ldd来验证libssldebug.so.1.0.2是运行时加载程序将使用的。
  2. Alternatively, it may be simpler to install libssldebug.so into a different directory (say /tmp/libssldebug ), create a symlink libssl.so.1.0.0 -> lissldebug.so in that directory, and then ask the runtime loader to search this directory first with g++ test.cpp ... -Wl,--rpath=/tmp/libssldebug . 或者,将libssldebug.so安装到另一个目录(例如/tmp/libssldebug ),在该目录中创建一个符号链接libssl.so.1.0.0 -> lissldebug.so可能更简单,然后要求运行时加载程序进行搜索首先使用g++ test.cpp ... -Wl,--rpath=/tmp/libssldebug With this solution, the executable will still search for libssl.so.1.0.0 , but it will search for it in the /tmp/libssldebug directory first , and will find your copy. 有了这个解决方案,可执行文件仍然会寻找libssl.so.1.0.0 ,但它会在搜索它/tmp/libssldebug目录第一 ,并会找到你的副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM