共享库RPATH和二进制文件RPATH优先级

12

如果一个共享库链接到二进制文件,并且共享库还依赖于其他库,那么共享库的RPATH和二进制文件的RPATH的优先级(链接器搜索顺序)是什么?二进制文件的RPATH能否覆盖共享库中的RPATH?我在共享库RPATH中设置的$ORIGIN是指lib位置还是二进制位置?
谢谢。

1个回答

13
据我的观察,如果有一个应用程序main动态加载库first.so,而后者反过来又动态加载库second.so,并且mainfirst.so都包含RPATH,那么动态链接器将首先使用first.so的RPATH搜索second.so,将$ ORIGIN解析为first.so的目录,仅当失败时,链接器才会继续使用main的RPATH,现在将$ ORIGIN解析为main的目录。
这不与动态链接器文档(查找Rpath令牌扩展)相矛盾:

$ORIGIN或等效的${ORIGIN}:这将扩展为包含程序或共享对象的目录。......

为了验证这一点,我创建了一个测试应用程序和两个库:mainlibalibbmain链接到libaliba链接到libb:
main -> liba.so -> libb.so

已编译好的二进制文件位于以下位置:

/cwd/main
/cwd/lib/liba.so
/cwd/lib/libb.so

mainliba 都使用链接器标志 --rpath=\$ORIGIN/lib 进行构建:

~$ readelf -a /cwd/main | grep ORIGIN
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib]
~$ readelf -a /cwd/lib/liba.so | grep ORIGIN
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib]

通过LD_DEBUG环境变量的帮助,我已经检查了动态链接器如何处理RPATH:

~$ LD_DEBUG=libs /cwd/main
:     find library=liba.so [0]; searching
:      search path=/cwd/lib/tls/x86_64:/cwd/lib/tls:/cwd/lib/x86_64:/cwd/lib              (RPATH from file /cwd/main)
:       trying file=/cwd/lib/tls/x86_64/liba.so
:       trying file=/cwd/lib/tls/liba.so
:       trying file=/cwd/lib/x86_64/liba.so
:       trying file=/cwd/lib/liba.so
94313:
:     find library=libc.so.6 [0]; searching
:      search path=/cwd/lib                (RPATH from file /cwd/main)
:       trying file=/cwd/lib/libc.so.6
:      search cache=/etc/ld.so.cache
:       trying file=/lib/x86_64-linux-gnu/libc.so.6
94313:
:     find library=libb.so [0]; searching
:      search path=/cwd/lib/lib/tls/x86_64:/cwd/lib/lib/tls:/cwd/lib/lib/x86_64:/cwd/lib/lib              (RPATH from file /cwd/lib/liba.so)
:       trying file=/cwd/lib/lib/tls/x86_64/libb.so
:       trying file=/cwd/lib/lib/tls/libb.so
:       trying file=/cwd/lib/lib/x86_64/libb.so
:       trying file=/cwd/lib/lib/libb.so
:      search path=/cwd/lib                (RPATH from file /cwd/main)
:       trying file=/cwd/lib/libb.so

从这里我们可以看到,链接器首先遇到了需要加载liba.so并使用main二进制文件的RPATH来解决这个问题。然后它遇到了需要加载libb.so并首先使用liba.so库的RPATH来解决这个问题。但是由于RPATH是$ORIGIN/lib,而libb.soliba.so在同一个目录中,链接器无法使用liba.so的RPATH找到libb.so。此后它回退到main的RPATH,并且仅使用后者成功找到libb.so

测试环境:Linux ubuntu 4.15.0-34-generic #37~16.04.1-Ubuntu(64位),/ lib / x86_64-linux-gnu / ld-2.23.so。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接