[英]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: 两种方式之一:
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
命令来验证SONAME
和NEEDED
现在包含"libssldebug.so.1.0.2"
,然后使用ldd
来验证libssldebug.so.1.0.2
是运行时加载程序将使用的。 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.