为什么使用 ld-linux.so 运行程序和使用 patchelf 更改解释器时会得到不同的结果?

为什么使用 ld-linux.so 运行程序和使用 patchelf 更改解释器时会得到不同的结果?


使用 ld + --library-path 运行程序和使用 patchelf 更改加载程序有什么区别?

为了说明这一点,下面是一个无法按原样运行的二进制文件,可能是因为缺少最新版本的库:

$ ~/DOWNLOADS/APPS/magick
/tmp/.mount_magickXiWzgy/usr/bin/magick: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /tmp/.mount_magickXiWzgy/usr/lib/libMagickCore-7.Q16HDRI.so.10)
/tmp/.mount_magickXiWzgy/usr/bin/magick: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /tmp/.mount_magickXiWzgy/usr/lib/libMagickCore-7.Q16HDRI.so.10)
/tmp/.mount_magickXiWzgy/usr/bin/magick: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /tmp/.mount_magickXiWzgy/usr/lib/liblcms2.so.2)
...
$

我尝试使用其他 3 个加载器和库路径(core18、core20 和 core22)来运行它。每次 ELF 文件 ABI 版本都无效。

$ /snap/core18/current/lib64/ld-linux-x86-64.so.2 --library-path /snap/core18/current/usr/lib/x86_64-linux-gnu/  ~/DOWNLOADS/APPS/magick
/home/ychaouche/DOWNLOADS/APPS/magick: error while loading shared libraries: /home/ychaouche/DOWNLOADS/APPS/magick: ELF file ABI version invalid
$ /snap/core20/current/lib64/ld-linux-x86-64.so.2 --library-path /snap/core20/current/usr/lib/x86_64-linux-gnu/  ~/DOWNLOADS/APPS/magick
/home/ychaouche/DOWNLOADS/APPS/magick: error while loading shared libraries: /home/ychaouche/DOWNLOADS/APPS/magick: ELF file ABI version invalid
$ /snap/core22/current/lib64/ld-linux-x86-64.so.2 --library-path /snap/core22/current/usr/lib/x86_64-linux-gnu/  ~/DOWNLOADS/APPS/magick
/home/ychaouche/DOWNLOADS/APPS/magick: error while loading shared libraries: /home/ychaouche/DOWNLOADS/APPS/magick: ELF file ABI version invalid
$

然后,当我在使用 patchelf 直接在二进制文件中更改加载程序和 rpath 后尝试运行它时,出现了分段错误,
如下所示:

$ patchelf --set-interpreter /snap/core18/current/lib64/ld-linux-x86-64.so.2 --set-rpath /snap/core18/current/usr/lib/x86_64-linux-gnu/  magick
$ ./magick
Segmentation fault
$ ldd magick
        not a dynamic executable
$

即使 ldd 也无法将其识别为动态可执行文件,尽管 readelf 可以读取它。

这是 @user10489 请求的 ldd 输出

$ file DOWNLOADS/APPS/magick
DOWNLOADS/APPS/magick: ELF 64-bit LSB  executable, x86-64, version 1, dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=9fdbc145689e0fb79cb7291203431012ae8e1911, stripped
$

我的问题是,为什么从命令行指定加载器时 ELF 文件 ABI 版本无效,并且在更改二进制文件内的加载器(和 rpath)时出现分段错误?

答案1

库版本控制的全部目的是防止库的 ABI 更改时出现问题,并允许应用程序找到与其期望的 ABI 匹配的库。

通过强制使用库版本,您已强制可执行文件尝试调用 ABI 与其预期不同的函数。结果充其量会因错误而失败,最坏的情况会以不可预测的方式崩溃。

如果您想将程序与特定库一起使用,则需要找到为该库编译的版本,或者从源代码重新编译它(假设 API 可以匹配)。

相关内容