c++ - 共享库 RPATH 和二进制 RPATH 优先级

标签 c++ linux build rpath

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

最佳答案

根据我的观察,如果有一个应用程序 main 动态加载库 first.so,后者又动态加载库 second.so ,并且 mainfirst.so 都包含 RPATH,那么动态链接器将首先使用 搜索 second.so first.so 的 RPATH,将 $ORIGIN 解析为 first.so 的目录,只有当它失败时,链接器才会继续到 main的 RPATH 现在将 $ORIGIN 解析为 main 的目录。

这与 dynamic linker doc (look for Rpath token expansion) 不矛盾:

$ORIGIN (or equivalently ${ORIGIN}): This expands to the directory containing the program or shared object. ...

为了检查这一点,我创建了一个测试应用程序和两个库:分别是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 environment variable 的帮助下我检查了动态链接器如何处理 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 在同一目录中,链接器无法找到 libb.so 使用 liba.so 的 RPATH。之后它返回到 main 的 RPATH 并且仅使用后者它成功找到 libb.so

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

关于c++ - 共享库 RPATH 和二进制 RPATH 优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23006930/

相关文章:

java - 在C++中,静态变量、动态变量和局部变量存储在哪里?在 C 和 Java 中怎么样?

linux - $PATH 使用 NVM 并安装 NPM

c - seteuid(0) 之后调用 popen 失败

go - 如何正确使用构建标签?

javascript - 为 Raspberry Pi 构建 Node.js 发生了什么

c++ - 如何使用常量私有(private)变量优化类成员?

c++ - 如何将 C++ 属性绑定(bind)到 QML 属性?

c++ - 'Attempting to upgrade input file specified using deprecated transformation parameters' 是什么意思?

android - Gradle 构建运行需要很长时间

groovy - 原因:无此类属性:类org.gradle.api.plugins.Convention的sourceSets