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


92

我有一个计划用于废料堆的旧可执行文件,但是还不存在。它依赖于已经从我的环境中删除的一些库,但是我在某些可以正常工作的地方有一些存根库。我想将此可执行文件指向这些存根库。是的,我可以设置LD_LIBRARY_PATH,但是许多脚本都调用了此可执行文件,许多用户也希望将其修复在一个位置。

我没有这个来源,很难得到它。我当时在想-是否可以使用支持ELF的编辑器来编辑此文件,并向rpath添加一个简单的PATH使其进入新库?这是否可能,或者一旦创建了ELF二进制文件,便将其固定在位置上并且无法移动?


3
将其包装到设置LD_LIBRARY_PATH并调用二进制文件的shellscript中。将shell脚本放在调用者的PATH中。
wildplasser

LD_LIBRARY_PATH由子进程继承。您可能不想要那样。
2016年

1
@将是的,我已经说过我不想这样做。:)
Rich Homolka

Answers:


78

有一个名为的工具chrpath可以执行此操作-您的发行版软件包中可能提供了该工具。


9
只是给Mac用户一个提示,install_name_tool可以用该-rpath标记进行操作
Kevin Tonon 2015年

10
如果收到错误:<binary>: no rpath or runpath tag found.,您不能使用chrpath它来代替它,但是patchelf在这种情况下,您可以使用:patchelf --set-rpath /path/to/libaries <binary>
phyatt

如果可能的话,我更喜欢使用chrpath,因为尽管它更通用,但patchelf有一些长期存在的错误,该错误会大大扩大您的库/可执行文件的大小。
taranaki

157

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

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

chrpath -r '$ORIGIN/../lib64' rdsamp 
rdsamp: no rpath or runpath tag found.

另一方面,

patchelf --set-rpath '$ORIGIN/../lib64' rdsamp

成功就好。


9
特别是,patchelf能够将rpath添加到不包含rpath的二进制文件中- chrpath似乎只能修改已经存在的条目。
maxschlepzig 2014年

4
一般而言,值得了解rpath和之间的细微区别runpath。基本上,一个可以覆盖LD_LIBRARY_PATH而另一个不能覆盖。有关详细信息,请参见blog.tremily.us/posts/rpath
Stuart Berg

6
令人讨厌的是,两者chrpathpatchelf它们的术语都草率。例如,patchelf上面显示的命令将更改,runpathrpath除非您也提供该--force-rpath选项,否则不会更改。
Stuart Berg

10
@superbatfish是的,但是区别通常无关紧要。CHANGELOG中的此项对此进行patchelf了解释:“ --set-rpath--shrink-rpath并且--print-rpath现在 优先DT_RUNPATHDT_RPATH,它已过时。更新时,如果两个都存在,则两个都被更新。如果仅存在DT_RPATH,则将其转换为,DT_RUNPATH除非--force-rpath指定。如果都不存在,DT_RUNPATH除非--force-rpath指定,否则添加a ,在这种情况下,将DT_RPATH添加a。” 出于兼容性原因,该选项的名称可能保持不变。
user7610 2014年

2
到目前为止,最好的答案应该是公认的答案!
肯尼斯·哈斯特

12

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

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

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

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

现在,请记住:

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

查看当前的R [UN] PATH

readelf -d <path-to-elf> | egrep "RPATH|RUNPATH"

清除R [UN] PATH

patchelf --remove-rpath <path-to-elf>

笔记:

  • 同时删除RPATHRUNPATH

将值添加到R [UN] PATH

patchelf [--force-rpath] --set-rpath "<desired-rpath>" <path-to-elf>

笔记:

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

1
-Wl,-R,<desired-rpath> -Wl,--enable-new-dtagsset DT_RUNPATH,这是大多数人应该使用的一种。RUNPATH可以被覆盖LD_LIBRARY_PATH,因此人们不应该使用--force-rpath
jww

@jww我看到我没有添加有关RPATH弃用的注释,所以我刚刚添加了一个注释。谢谢!
Daniel Trugman

注意,该示例<desired-path>使用冒号;它应该是逗号(即:)/my/libs,/my/other/libs
艾伦·德·斯梅特

@AlanDeSmet,我不知道逗号,但是冒号对我有用。
Daniel Trugman

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.