ld-linux动态链接器/解释器的相对可执行路径 [英] Relative-to-executable path to ld-linux dynamic linker/interpreter
问题描述
我想运送和归档二进制文件(带有库的可执行文件),这些二进制文件应尽可能地与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
链接或通过chrpath
或patchelf
进行设置).这样可以使这些库与可执行文件一起重新定位,并且可以对除链接器本身的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:
-
$ORIGIN
技巧不起作用 - 类似于
./
的相对路径有效,但仅当当前目录与加载器本身相同时(从其他位置启动时,可执行文件崩溃并出现错误) - 我可以编写一个shell脚本来检测所有路径并使用
/my/path/ld-linux.so /my/path/myexecutable $@
启动可执行文件,但这意味着我要避免的另一层间接和开销.
- The
$ORIGIN
trick does not work - 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) - 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.6
和ld-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屋!