linux 上 rpath 规范的 @loader_path 等价物是啥?

Posted

技术标签:

【中文标题】linux 上 rpath 规范的 @loader_path 等价物是啥?【英文标题】:What is the equivalent of @loader_path for rpath specification on linux?linux 上 rpath 规范的 @loader_path 等价物是什么? 【发布时间】:2014-10-09 14:15:15 【问题描述】:

在 osx 加载器上,@loader_path 解析为通用二进制对象的位置,@executable_path 解析为可执行文件的位置。在 Linux 上,显然只有 $ORIGIN,它解析为可执行路径。 linux 加载程序中是否有隐藏功能来指定通用 ELF 对象的动态搜索路径?或者 $ORIGIN 对于这些对象的行为可能不同?

Linux 也有 $LIB 和 $PLATFORM,但它们没有提供我需要的东西。

【问题讨论】:

【参考方案1】:

$ORIGIN是被加载对象的位置,所以在可执行文件和可执行文件加载的共享库中是不同的。

编辑:这是我进行的一个小测试:

~$ mkdir /tmp/tests
~$ cd /tmp/tests
tests$ mkdir good bad
tests$ gcc -fPIC  -shared -o good/libtest.so -Wl,-rpath,\$ORIGIN -x c - <<< 'int puts(const char*); void foo()  puts("good"); '
tests$ gcc -fPIC  -shared -o bad/libtest.so -Wl,-rpath,\$ORIGIN -x c - <<< 'int puts(const char*); void foo()  puts("bad"); '
tests$ gcc -fPIC  -shared -o good/libtest2.so -Wl,-rpath,\$ORIGIN -x c - -ltest -Lgood <<< 'void foo(); void bar()  foo(); '
tests$ gcc  -o bad/a.out good/libtest2.so -x c - -Wl,-rpath,\$ORIGIN -Wl,-rpath-link,good <<< 'void bar(); int main()  bar(); '
tests$ 
tests$ readelf -d bad/* good/* | grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
tests$ 
tests$ ldd bad/a.out 
        linux-vdso.so.1 =>  (0x00007faf2f295000)
        good/libtest2.so (0x00007faf2f092000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003949800000)
        libtest.so => /tmp/tests/good/libtest.so (0x00007faf2ee66000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003949400000)
tests$ bad/a.out
good

我认为这表明它有效,所有东西都有RPATH=$ORIGIN,可执行文件明确链接到libtest2.so,它在自己的目录而不是可执行文件的目录中选择libtest.so

使用LD_DEBUG=libs bad/a.out 显示:

[...]
  17779:     find library=libtest.so [0]; searching
  17779:      search path=/tmp/tests/good/tls/x86_64:/tmp/tests/good/tls:/tmp/tests/good/x86_64:/tmp/tests/good              (RPATH from file good/libtest2.so)
[...]

即当查找good/libtest2.solibtest.so 依赖项时,搜索路径使用来自good/libtest2.so 的RPATH,它扩展为/tmp/tests/good,即来自good/libtest2.so$ORIGIN,而不是可执行文件的$ORIGIN

【讨论】:

不是根据手册页ld.so understands the string $ORIGIN (or equivalently $ORIGIN) in an rpath specification to mean the directory containing the application executable. 嗯,也许我当时正在考虑 Solaris ...它与 GNU 动态链接器在共享库中对 $ORIGIN 的解释不一致,所以也许我把它们弄错了。 我刚刚测试过它,链接到good/libtest2.so 的可执行文件bad/a.out 依赖于libtest.so 将从good 而不是bad 获取它,即它使用共享库的$ORIGIN 不是可执行文件的 完美!所以手册页不正确,或者至少不清楚。谢谢! 已在最新man-pages release进行了更正【参考方案2】:

linux 加载程序按以下顺序搜索:

DT_RPATH(在 gcc 命令行中指定,忽略 si DT_RUNPATH 存在)

LD_LIBRARY_PATH(在环境中指定)

DT_RUNPATH(在 gcc 命令行中指定)

ld.so.conf(用于在行中指定并使用 ldconfig 编译的目录)

/lib 和 /usr/lib

【讨论】:

我指的是该规范中使用的变量

以上是关于linux 上 rpath 规范的 @loader_path 等价物是啥?的主要内容,如果未能解决你的问题,请参考以下文章

LINUX/MAC的rpath,搜索依赖库时从哪里开始

Rpath handling on Linux

LINUX可以使用patchelf 修改文件的rpath

是否有一种编程方式来检查 Linux 上的当前 rpath?

linux下ld连接SO文件时如何制定绝对路径

linux 修改 elf 文件的dynamic linker 和 rpath