【问题标题】:How do I set DT_RPATH or DT_RUNPATH?如何设置 DT_RPATH 或 DT_RUNPATH?
【发布时间】:2021-07-11 20:29:49
【问题描述】:

在 Linux 上,ld.so(8) 手册页讨论了动态库的搜索顺序。它说DT_RPATH 已弃用,还提到DT_RUNPATH。没有提到-rpath 链接器选项。

ld(1) 手册页提到了-rpath-rpath-link 选项,但从未提及DT_RPATHDT_RUNPATH,除非在描述库搜索顺序时,这当然与@ 中给出的信息不匹配987654330@.

最后有一个LD_RUN_PATH 环境变量。 ld(1) 表示在未设置 -rpath-rpath-link 选项时使用,但 ld.so(8) 未提及。

我的直觉是-rpath 实际上设置了DT_RPATH,而-rpath-link 设置了DT_RUNPATH,但我无法在任何地方找到这一点。我一直用-rpath;如果它与DT_RPATH 相同,我就不应该使用它,但是我在动态链接上找到的操作方法文章说要使用它,所以我不确定它是否相同。

有人可以澄清DT_RPATHDT_RUNPATH 是如何设置的,它们是否与-rpath-rpath-link 相同?

【问题讨论】:

    标签: linux shared-libraries ld


    【解决方案1】:

    当您编译程序时,您会创建目标文件,然后将它们链接在一起。您可以使用 GNU ld(1) 链接它们,还有其他链接器,LLVM 链接器。链接器将目标文件组合成可执行文件。 GNU ld(1) 是带有documentation available here 的binutils 的一部分。

    当您执行一个已经编译好的可以使用的可执行文件时,动态链接器 ld.so(8) 会在系统上找到可执行文件所依赖的库,加载它们并执行可执行文件。 ld.so(8) 是一个共享库,通常作为 C 标准库的一部分分发,通常在 linux 上是 glibc,但也有其他的,比如 musl。

    我认为这两个程序都被命名为“链接器”令人困惑。一个类似于“编译链接器”,另一个是“可执行链接器”。

    如何设置 DT_RPATH 或 DT_RUNPATH?

    编辑 elf 文件以包含特定部分。

    当使用 GNU ld 创建 elf 文件时,现在您将 RUNPATH 部分设置为 -rpath=something。您可以使用--disable-new-dtags -rpath=something 设置RPATH 部分。 RPATH 已被弃用,因此通常-rpath 设置 RUNPATH。 https://www.javaer101.com/en/article/1127068.html *这不会在我的系统上检出,我必须使用 gcc -Wl,--enable-new-dtags -Wl,-rpath=/tmp 进行编译以设置 RUNPATH...

    您还可以在编译后在任何 ELF 文件中设置节。见Can I change 'rpath' in an already compiled binary?

    它们是否与-rpath和-rpath-link相同?

    来自ld documentation

    -rpath 和 -rpath-link 的区别在于 -rpath 选项指定的目录包含在可执行文件中并在运行时使用,而 -rpath-link 选项仅在链接时有效。

    文档还解释了-rpath-link 的工作原理。就是指定搜索依赖共享库的目录。

    终于有了 LD_RUN_PATH 环境变量

    编译一个可执行的 GNU ld(1) 也会在这个变量指定的目录中搜索库。

    【讨论】:

      【解决方案2】:

      -rpath 命令行选项用于在 .dynamic 部分中创建 DT_RPATH 条目,但由于 DT_RPATH 已被弃用以支持 DT_RUNPATH,因此现代链接器版本改用 DT_RUNPATH。这意味着在一个非常旧的链接器上使用-rpath,您将使用.d_val = DT_RPATH 创建一个动态节条目,但如果您的链接器是最新的,您将使用.d_val = DT_RUNPATH 创建一个。

      -rpath-link 选项是一个创建任何条目的选项,但用于取代正在链接的库的动态部分中存在的DT_RUNPATH 条目。因此,在编译时,您通常不需要它。您可以在man 1 ld(向下滚动到-rpath-link=)或this other answer 中找到更多信息。

      【讨论】:

      • 那么,DT_ 是什么意思?我只能看到 readelf -d xxx.so 的 (RUNPATH) 而不是 'DT_RUNPATH'
      • @vrqq 这是因为readelf 向您显示了一个更人性化的名称,而不是用于动态标签的#defineDT 代表“动态标签”。常量的全名是DT_RUNPATH,实际上就是数字29。请参阅 man 5 elf 部分“动态标签 (Dyn)”。
      猜你喜欢
      • 2019-03-23
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2018-08-22
      • 2011-08-15
      • 2021-12-11
      相关资源
      最近更新 更多