ld-linux动态链接器/解释器的相对可执行路径

问题描述 投票:1回答:1

我想发送和存档二进制文件(带有库的可执行文件),这些文件可以向后和向前兼容尽可能多的Linux发行版,并且整个包可以重定位。据我所知,像libc这样的系统库也需要发货,因为可执行文件会因为libc的不同版本而崩溃。同时libc似乎与ld-linux相结合(例如在Debian测试中编译的二进制文件已经无法在Ubuntu 18.04 LTS上运行),所以我也需要打包ld-linux

我的解决方案是将所有可执行文件和库放入一个目录并将rpath设置为$ORIGIN(通过与-Wl,rpath=$ORIGIN链接或使用chrpathpatchelf设置)。这使得库可以与可执行文件一起重新定位,并且适用于除ld-linux之外的所有库,链接器本身也是如此。

可以通过-Wl,--dynamic-linker=/my/path/ld-linux.so更改动态链接器路径,或者使用patchelf设置它,但路径必须是绝对路径:

  1. $ORIGIN技巧不起作用
  2. ./这样的相对路径可以工作,但只有当前目录与加载器本身相同时(可执行文件从其他地方启动时崩溃并出现错误)
  3. 我可以编写一个shell脚本来检测所有路径并使用/my/path/ld-linux.so /my/path/myexecutable $@启动可执行文件,但这意味着我想要避免的另一层间接和开销。

有没有办法将ld-linux的路径相对于可执行文件直接设置为可执行文件?

也许有一种方法静态链接ld-linux加载器?

linux installation elf dynamic-linking relocation
1个回答
0
投票

据我所知,像libc这样的系统库也需要发货,因为在给定不同版本的libc的情况下,可执行文件会崩溃。

这是不正确的:GLIBC保证向后兼容性(在旧系统上构建的可执行文件将继续在较新版本的GLIBC上运行)。

实现您想要的唯一理智的方法是针对您希望支持的最旧版本的GLIBC进行编译。

同时libc似乎与ld-linux相结合

正确:libc.so.6ld-linux是GLIBC的一部分,必须来自同一版本,任何不匹配都可能导致灾难性的失败(SIGSEGV内部或libc.so.6内部的ld-linux)。

我也需要打包ld-linux。

这很复杂:ld-linux的绝对路径被硬编码到a.out中,并且无法改变。制作一个可以容忍改变a.out路径的可重定位的ld-linux是不可能的(没有你已经尝试过的显式加载器调用;这对于重新执行它们的可执行文件不起作用)。

更新:

我可以尝试在旧的Ubuntu LTS上构建并获得大部分向后兼容性,但后来我不会得到新的C ++ 17编译器,这基本上打败了现代软件工程的全部要点。

您可以在较旧的系统上安装较新的编译器,并使用较旧的GLIBC获得C ++ 17。

这方面的一个难点是你可能需要更新的libstdc++.so.6

好消息是-Wl,-rpath=$ORIGIN工作正常 - 它只是很难重新安置的GLIBC。您还可以将libstdc++.a的可执行文件与--static-libstdc++相关联。

但是,在执行任何操作时可能会产生许可影响(但您的计划已经包括分发所有库,因此该问题并非新问题)。

© www.soinside.com 2019 - 2024. All rights reserved.