从相对于加载可执行文件的目录加载 .so

Posted

技术标签:

【中文标题】从相对于加载可执行文件的目录加载 .so【英文标题】:Load .so from directory relative to loading executable 【发布时间】:2015-10-13 19:00:46 【问题描述】:

由于各种原因,主要与惯性有关,我们没有make install 目标。

相反,我们将大型 C++ 代码库直接构建到类似 FHS 的树中;

output/
  bin/
  lib/
  etc/
  ...

我们最近将一些第三方库切换到动态链接,因此我们将一些 .so 库推送到 lib/

现在,我们习惯于从bin/ 启动我们的可执行文件,但这不再有效,因为加载程序不会搜索我们的lib/ 目录。

LD_LIBRARY_PATH 可以解决这个问题,但我们不希望在每次可执行调用之前都提供它,并且我们不想将它粘在 shell 环境中,因为我们通常会在许多不同的构建之间切换树在同一个壳里。

我们考虑在生成的 ELF 中添加一个 rpath 条目,但相对路径通常根据 $PWD 解析,而不是可执行文件的目录名。

有没有办法让加载程序在 dirname(argv[0])/../lib 中查找 .so 库?

基本上,我知道有很多方法可以改变我们的习惯来完成这项工作(并且可能应该),但我们现在不想这样做,所以我们可以强制 Linux so 加载程序做我们想做的事?谢谢!

【问题讨论】:

【参考方案1】:

是的,可以使用rpath$ORIGIN 宏,它们在运行时被ld.so 识别。

来自man ld.so

ld.so understands certain strings in an rpath specification 
(DT_RPATH or DT_RUNPATH); those strings are substituted as follows

$ORIGIN (or equivalently $ORIGIN)
    This expands to the directory containing the application executable.

更多变量可用。你不需要强迫加载器做任何事情。它具有适合您的功能。 :)

【讨论】:

很好,谢谢!我不认为即使没有rpath 也有办法实现这一目标? Windows 有一个清单文件的概念,您可以将它们放在可执行文件旁边,以控制此类内容。如果ld,so 有类似的带外机制,那就太好了。 最流行的解决方案是提供设置环境和调用二进制文件的包装器外壳脚本。很多大项目都是这样做的。 IntelliJ IDEAandroid Studio 是两个值得注意的例子。 有道理,谢谢。我们希望不必再教育一群在肌肉记忆中拥有所有可执行文件名称的开发人员。无论如何,很好的答案,谢谢! 在这种情况下,我会将bin/app 移动到bin/app.bin 并将包装脚本放入bin/app。没有人会看到区别。 Firefox 和 Thunderbird 使用了这种方法。不要忘记传递所有参数不变。 :)

以上是关于从相对于加载可执行文件的目录加载 .so的主要内容,如果未能解决你的问题,请参考以下文章

.net 自动装配解决加载重复装配

Android 逆向函数拦截原理 ( 可执行程序基本结构 | GOT 全局偏移表 | 可执行程序函数调用步骤 )

Xcode:如何将当前工作目录设置为可执行文件的相对路径?

在 RAMDisk 上执行二进制文件是不是会将可执行文件重新加载到内存中?

GCC编译器原理------编译原理一:ELF文件

Ubuntu linux设置从当前目录下加载动态库so文件