40

这个页面说关于图书馆搜索的顺序ld.so

Unless loading object has RUNPATH:
    RPATH of the loading object,
        then the RPATH of its loader (unless it has a RUNPATH), ...,
        until the end of the chain, which is either the executable
        or an object loaded by dlopen
    Unless executable has RUNPATH:
        RPATH of the executable
LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs

然后建议:

发布二进制文件时,要么使用 RPATH 而不是 RUNPATH,要么确保在运行之前设置 LD_LIBRARY_PATH。

那么,使用RPATHwithRUNPATH很糟糕,因为RUNPATH某种取消RPATH,所以间接动态加载不能按预期工作?但是为什么后来RPATH被弃用了RUNPATH呢?

有人可以解释一下情况吗?

4

3 回答 3

42

当您发布二进制文件时,最好为用户提供使二进制文件适应他们自己系统的细节的方法,其中包括调整库搜索路径。

用户通常可以调整LD_LIBRARY_PATH/etc/ld.so.conf,两者的优先级都低于DT_RPATH,即您不能覆盖二进制文件中硬编码的内容,而如果您DT_RUNPATH改用 ,则用户可以使用LD_LIBRARY_PATH.

(FWIW,我认为ld.so.conf也应该优先于DT_RUNPATH,但是,无论如何,至少我们有LD_LIBRARY_PATH)。

另外,我强烈不同意上面使用DT_RPATH. IMO,最好DT_RPATH不要DT_RUNPATH在已发布的二进制文件中使用下界。

除非

您将所有依赖库与您的可执行文件一起发布,并希望确保在安装后 JustWork(tm),在这种情况下使用DT_RPATH.

于 2011-11-06T15:13:52.487 回答
30

Chill 的回答完全正确;我想简单地添加一些颜色,来自最近阅读的 glibc 源代码([master 8b0ccb2],在 2.17 中)。需要明确的是,如果在给定级别指定的位置找不到库,则尝试下一个级别。如果在给定级别找到库,则搜索停止。

动态库搜索顺序:

  1. ELF 二进制文件中的 DT_RPATH,除非设置了 DT_RUNPATH。
  2. LD_LIBRARY_PATH 条目,除非 setuid/setgid
  3. ELF 二进制文件中的 DT_RUNPATH
  4. /etc/ld.so.cache 条目,除非在链接时给出 -z nodeflib
  5. /lib, /usr/lib 除非 -z nodeflib
  6. 完成,“未找到”。
于 2013-06-04T16:21:06.103 回答
16

但是为什么 RPATH 被 RUNPATH 弃用了呢?

引入 DT_RPATH 时,它优先于所有其他参数。这使得即使出于开发目的也无法覆盖库搜索路径。因此,引入了另一个参数 LD_RUNPATH,其优先级低于 LD_LIBRARY_PATH。

更多细节可以在Ulrich Drepper编写的“如何编写共享库”工作中找到。

于 2014-01-28T14:51:39.940 回答