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

mar*_*usm 10 linux installation elf relocation dynamic-linking

我想要发布和归档二进制文件(带有库的可执行文件),它们向后和向前兼容尽可能多的 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 加载程序?

Emp*_*ian 5

据我了解,像 libc 这样的系统库也需要提供,因为给定不同版本的 libc 时可执行文件会崩溃。

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

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

同时 libc 似乎与 ld-linux 结合在一起

正确:libc.so.6ld-linux是 GLIBC 的一部分,必须来自同一版本,任何不匹配都可能导致灾难性故障(SIGSEGVinsidelibc.so.6或 inside 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++.

但是,执行任一操作都可能会产生许可问题(但您的计划已经包括分发所有库,因此这个问题并不新鲜)。