在可执行二进制文件中更改一个特定的共享库

我在这方面是新手,所以和我一起裸照。 这里写的curlftpfs是非常缓慢的,因为最新的libcurl3-gnutls的bug。 由于此软件包具有较大的反向依赖关系(可通过apt-cache showpkg libcurl3-gnutls:amd64apt-cache rdepends libcurl3-gnutls:amd64进行validation),因此不build议降级。 所以我决定以不同的方式降级。 我已经检查存储库中的可用版本:

 $ apt-cache policy libcurl3-gnutls:amd64 libcurl3-gnutls: Installed: 7.43.0-1ubuntu2.1 Candidate: 7.43.0-1ubuntu2.1 Version table: *** 7.43.0-1ubuntu2.1 0 500 http://sk.archive.ubuntu.com/ubuntu/ wily-updates/main amd64 Packages 500 http://security.ubuntu.com/ubuntu/ wily-security/main amd64 Packages 100 /var/lib/dpkg/status 7.43.0-1ubuntu2 0 500 http://sk.archive.ubuntu.com/ubuntu/ wily/main amd64 Packages 

然后我已经下载并提取了比安装的版本旧的版本:

 $ apt-get install -d libcurl3-gnutls=7.43.0-1ubuntu2 $ sudo mv /var/cache/apt/archives/libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb . $ dpkg -x libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb extracted_deb 

然后,我备份了原始二进制文件,并在共享库中search了一些常用名称:

 $ cp $(which curlftpfs) . $ ldd ./curlftpfs | grep curl libcurl-gnutls.so.4 => /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 (0x00007fcac4443000) $ readelf -d ./curlftpfs | grep -i curl 0x0000000000000001 (NEEDED) Shared library: [libcurl-gnutls.so.4] 

下面的步骤只是certificate链接的文件完全属于libcurl3-gnutls包,而curlftpfs依赖于libcurl3-gnutls

 $ dpkg -S /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 libcurl3-gnutls:amd64: /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 $ apt-cache depends curlftpfs curlftpfs Depends: libc6 Depends: libcurl3-gnutls Depends: libfuse2 Depends: libglib2.0-0 Depends: fuse Conflicts: curlftpfs:i386 

另外提取和安装libcurl3-gnutls包的内容看起来完全一样:

 $ dpkg -L libcurl3-gnutls:amd64 | sort /. /usr /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0 /usr/share /usr/share/doc /usr/share/doc/libcurl3-gnutls /usr/share/doc/libcurl3-gnutls/changelog.Debian.gz /usr/share/doc/libcurl3-gnutls/copyright /usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz /usr/share/lintian /usr/share/lintian/overrides /usr/share/lintian/overrides/libcurl3-gnutls $ find extracted_deb/ | sort extracted/ extracted/usr extracted/usr/lib extracted/usr/lib/x86_64-linux-gnu extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3 extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0 extracted/usr/share extracted/usr/share/doc extracted/usr/share/doc/libcurl3-gnutls extracted/usr/share/doc/libcurl3-gnutls/changelog.Debian.gz extracted/usr/share/doc/libcurl3-gnutls/copyright extracted/usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz extracted/usr/share/lintian extracted/usr/share/lintian/overrides extracted/usr/share/lintian/overrides/libcurl3-gnutls 

我的问题是如何重写包含在ldd输出中的path,并将其指向我已经提取的文件? 我已经读了关于rpathpatchelfchrpath 在这里和这里,但我想这不是我的情况,因为下面的命令返回没有用:

 $ readelf -d ./curlftpfs | grep -i rpath $ $ chrpath -l ./curlftpfs ./curlftpfs: no rpath or runpath tag found. $ $ patchelf --print-rpath ./curlftpfs $ 

所以看起来rpath不被使用。 我还读了$LD_LIBRARY_PRELOAD但我想它会改变给定的二进制文件的所有共享库path不只是一个特定的(在我的情况下/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 )所以我需要有整个图书馆的树。 还有解决scheme,build议更改加载器(在我的例子/lib64/ld-linux-x86-64.so.2我猜):

 $ patchelf --print-interpreter ./curlftpfs /lib64/ld-linux-x86-64.so.2 $ $ ldd ./curlftpfs | grep ld-linux /lib64/ld-linux-x86-64.so.2 (0x0000564966b64000) $ $ ls -laL /lib/x86_64-linux-gnu/ld-2.21.so -rwxr-xr-x 1 root root 154376 Mar 26 2015 /lib/x86_64-linux-gnu/ld-2.21.so 

但说实话,我没有明白这一点。 你能帮助吗?

我的问题是如何重写包含在ldd输出中的路径,并将其指向我已经提取的文件?

看来你想要的只是覆盖旧版本的libcurl-gnutls.so库的功能。 正如在您提供的最后一个链接中所暗示的那样,您可以使用LD_PRELOAD环境变量来覆盖标准库函数。

假设您的手动安装(降级)版本的libcurl-gnutls具有动态库文件/usr/local/lib/libcurl-gnutls.so.4.4.0。 然后你可以做如下的事情: LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 curlftpfs [some_arguments...]

不要忘记/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4和/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3只是到主库的符号链接libcurl-gnutls文件。 复制这些符号链接可能没有预期的效果。 您需要长名为SO的文件,如libcurl-gnutls.so.4.4.0。

额外的笔记

您可以通过执行以下操作来测试此重写: LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 ldd $(which curlftpfs)

对于手动安装,/ usr / local / lib可能不是一个放置动态库的好地方,您不希望干扰其他二进制文件。 这是因为/etc/ld.so.conf.d/libc.conf可能指向自动库的/ usr / local / lib。 (我的Debian机器)

要查看LD_环境变量的定义,请查看ld.so(8)手册页( man ld.so )。