ld-linux动态链接器/解释器的相对可执行路径 [英] Relative-to-executable path to ld-linux dynamic linker/interpreter

查看:481
本文介绍了ld-linux动态链接器/解释器的相对可执行路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想运送和归档二进制文件(带有库的可执行文件),这些二进制文件应尽可能地与Linux发行版本向后和向前兼容,并且整个软件包都可重定位. 据我了解,像libc这样的系统库也需要交付,因为在libc的其他版本下,可执行文件将崩溃.同时libc似乎与ld-linux耦合 (例如,在Debian测试中编译的二进制文件已经无法在Ubuntu 18.04 LTS上运行),因此我也需要打包ld-linux.

I want to ship and archive binaries (executables with libraries) which are backward and forward compatible with as many Linux distributions as possible and the whole package relocatable. As I understand system libraries like libc also need to be shipped because the executable will crash given a different version of libc. Meanwhile libc seems to be coupled with ld-linux (e.g. binaries compiled on Debian testing already does not work on Ubuntu 18.04 LTS), so I need to package ld-linux too.

我的解决方案是将所有可执行文件和库放入一个目录,并将rpath设置为$ORIGIN(通过与-Wl,rpath=$ORIGIN链接或通过chrpathpatchelf进行设置).这样可以使这些库与可执行文件一起重新定位,并且可以对除链接器本身的ld-linux以外的所有库工作.

My solution is to put all executables and libraries into one directory and set rpath to $ORIGIN (either by linking with -Wl,rpath=$ORIGIN or setting with chrpath or patchelf). This makes the libraries relocatable together with the executable and works for all the libraries except ld-linux which is the linker itself.

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

It is possible to change the dynamic-linker path by -Wl,--dynamic-linker=/my/path/ld-linux.so or set it with patchelf but the path has to be absolute:

  1. $ORIGIN技巧不起作用
  2. 类似于./的相对路径有效,但仅当当前目录与加载器本身相同时(从其他位置启动时,可执行文件崩溃并出现错误)
  3. 我可以编写一个shell脚本来检测所有路径并使用/my/path/ld-linux.so /my/path/myexecutable $@启动可执行文件,但这意味着我要避免的另一层间接和开销.
  1. The $ORIGIN trick does not work
  2. The relative path like ./ works but only when the current directory is the same as the loader itself (the executable crashes with errors when started from elsewhere)
  3. I can write a shell script to detect all paths and launch the executable with /my/path/ld-linux.so /my/path/myexecutable $@, but it means yet another layer of indirection and overhead I would like to avoid.

是否可以将相对于可执行文件的ld-linux路径直接设置为可执行文件?

Is there a way to set the path to ld-linux relative to the executable directly into executable?

也许有一种方法可以静态链接ld-linux加载程序?

Maybe there is a way to statically link the ld-linux loader?

推荐答案

据我了解,像libc这样的系统库也需要交付,因为在使用其他版本的libc时,可执行文件将崩溃.

As I understand system libraries like libc also need to be shipped because the executable will crash given a different version of libc.

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

That is incorrect: GLIBC guarantees backward compatibility (an executable built on an older system will continue to work on newer versions of GLIBC).

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

The only sane way to achieve what you want is to compile against the oldest version of GLIBC you wish to support.

同时libc似乎与ld-linux结合

Meanwhile libc seems to be coupled with ld-linux

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

Correct: libc.so.6 and ld-linux are part of GLIBC, must come from the same build, and any mismatch can lead to catastrophic failure (SIGSEGV inside libc.so.6, or inside ld-linux).

我也需要打包ld-linux.

I need to package ld-linux too.

这很复杂:ld-linux absolute 路径被硬编码到a.out中,并且无法更改.使可重定位的 a.out可以容忍对ld-linux路径的更改是不可能的(缺少您已经尝试过的显式加载程序调用;这对于重新执行的可执行文件效果不佳自己.)

That is complicated: the absolute path to ld-linux is hard-coded into the a.out, and can't be changed. Making a relocatable a.out that can tolerate changes to the path to ld-linux is impossible (short of explicit loader invocation you've already tried; which doesn't work well for executables that re-exec themselves).

更新:

我可以尝试在旧的Ubuntu LTS上构建并获得大多数向后兼容性,但是后来我没有获得新的C ++ 17编译器,这基本上使现代软件工程的观点无法实现.

I could try building on an old Ubuntu LTS and get most of backward compatibility, but then I would not get the new C++17 compilers, which basically defeats the whole point of modern software engineering.

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

You could install newer compiler on the older system, and get C++17 with older GLIBC.

这样做的一个困难是您可能需要更新的libstdc++.so.6.

One difficulty with that is that you may require a newer libstdc++.so.6.

好消息是-Wl,-rpath=$ORIGIN可以正常工作-只有GLIBC很难重定位.您也可以将libstdc++.a的可执行文件与--static-libstdc++链接.

The good news is that -Wl,-rpath=$ORIGIN works fine -- it's only GLIBC that is hard to relocate. You could also link the executable against libstdc++.a with --static-libstdc++.

但是,在执行任何一项操作时都可能涉及许可问题(但是同样,您的计划已经包括分发所有库,因此,这不是新问题).

However, there might be licensing implications in doing either (but then again your plan already included distributing all the libraries, so that issue is not new).

这篇关于ld-linux动态链接器/解释器的相对可执行路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆