我可以在已编译的二进制文件中更改"rpath"吗?

Ric*_*lka 81 linux linker elf

我有一个旧的可执行文件,它被安排在废料堆中,但它还没有.它依赖于从我的环境中删除的一些库,但我在某些地方工作正常.我想将此可执行文件指向这些存根库.是的,我可以设置LD_LIBRARY_PATH,但是这个可执行文件是从许多脚本中调用的,很多用户和我都喜欢在一个地方修复它.

我没有这方面的来源,并且很难得到它.我在想 - 我可以使用ELF识别编辑器编辑这个文件,并在rpath中添加一个简单的PATH以使其命中新的库吗?这是可能的,或者一旦你创建了一个ELF二进制文件,你就把东西固定到位置并且它们不能移动?

use*_*610 141

有一个比chrpath被称为更普遍的工具patchelf.它最初是为Nix和NixOS(包装系统和GNU/Linux发行版)制作软件包而创建的.

如果二进制文件中没有rpath(这里称为rdsamp),则chrpath失败:

chrpath -r '$ORIGIN/../lib64' rdsamp 
rdsamp: no rpath or runpath tag found.
Run Code Online (Sandbox Code Playgroud)

另一方面,

patchelf --set-rpath '$ORIGIN/../lib64' rdsamp
Run Code Online (Sandbox Code Playgroud)

成功就好了.

  • @superbatfish是的,但差异通常无关紧要.这个来自`patchelf`的CHANGELOG的条目解释了它:" - set-rpath`,`--shrink-rpath`和`--print-rpath`现在更喜欢`DT_RUNPATH`而不是`DT_RPATH`,这已经过时了.更新时,如果两者都存在,则更新两者.如果只存在DT_RPATH,则转换为"DT_RUNPATH",除非指定了`--force-rpath`.如果两者都不存在,则添加`DT_RUNPATH`,除非` - 指定了-force-rpath`,在这种情况下添加了`DT_RPATH`." 出于兼容性原因,选项的名称可能保持不变. (10认同)
  • 特别是,`patchelf`能够将rpath添加到不包含rpath的二进制文件中 - 其中`chrpath`似乎只能修改已存在的条目. (9认同)
  • 令人讨厌的是,`chrpath`和`patchelf`都是用他们的术语草率的.例如,上面显示的`patchelf`命令将改变`runpath`而不是`rpath`,除非你还提供`--force-rpath`选项. (6认同)
  • 总的来说,值得理解`rpath`和`runpath`之间的细微区别.基本上,可以覆盖`LD_LIBRARY_PATH`而另一个不能.有关详细信息,请参阅http://blog.tremily.us/posts/rpath/ (4认同)
  • 到目前为止最好的答案,这应该是接受的答案! (2认同)
  • @bruziuz `$ORIGIN` 扩展到包含程序或共享对象的目录。执行二进制文件时会发生扩展,而不是运行 `patchel` 时。为了防止运行 patchelf 时 shell 扩展,rpath 是单引号的。它在手册页中进行了解释。http://man7.org/linux/man-pages/man8/ld.so.8.html (2认同)

Tom*_*omH 69

有一个工具叫做chrpath可以做到这一点 - 它可能在您的发行版的包中可用.

  • 对于mac用户来说,只需一个注释,`install_name_tool`可以使用`-rpath`标志执行此操作 (8认同)
  • 如果你得到错误:`<binary>:找不到rpath或runpath标签.,你不能使用`chrpath`替换它,但在这种情况下你可以使用`patchelf`:`patchelf --set-rpath/path/to/libaries <binary>` (7认同)
  • _chrpath_ 有一个严重的限制:_它只能用相等或更短长度之一替换 RPATH_(rpath 版本 0.16 的手册页) (3认同)

Dan*_*man 7

就像@ user7610所说的那样,正确的方法就是使用该patchelf工具。

但是,我觉得我可以给出一个更全面的答案,涵盖一个人确切要做的所有命令。

有关此主题的全面文章,请单击此处

首先,许多开发人员都在谈论RPATH,但实际上是他们的意思RUNPATH。这是两个不同的可选动态部分,加载器对它们的处理方式非常不同。您可以在我之前提到的链接中了解有关它们之间区别的更多信息。

现在,请记住:

  • 如果RUNPATH设置,将RPATH被忽略
  • RPATH 已弃用,应避免使用
  • RUNPATH 首选,因为它可以被 LD_LIBRARY_PATH

查看当前的R [UN] PATH

readelf -d <path-to-elf> | egrep "RPATH|RUNPATH"
Run Code Online (Sandbox Code Playgroud)

清除R [UN] PATH

patchelf --remove-rpath <path-to-elf>
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 同时删除RPATHRUNPATH

将值添加到R [UN] PATH

patchelf [--force-rpath] --set-rpath "<desired-rpath>" <path-to-elf>
Run Code Online (Sandbox Code Playgroud)

笔记:

  • <desired-path> 是用逗号分隔的目录列表,例如: /my/libs:/my/other/libs
  • 如果指定--force-rpath,则设置RPATH,否则设置RUNPATH

  • RPATH 可能已被弃用,但使用 RUNPATH 可能会导致“意外”的极端情况。例如,请参阅 https://www.qt.io/blog/2011/10/28/rpath-and-runpath 。 (2认同)