如果共享库链接到二进制文件,并且共享库也依赖于其他库,那么共享库的RPATH和二进制文件的RPATH的优先级(链接器搜索顺序)是什么?二进制文件的RPATH是否可以覆盖共享库中的RPATH?我在共享库RPATH中设置的$ ORIGIN是指lib位置还是二进制位置?
提前谢谢。
答案 0 :(得分:1)
根据我的观察,如果有一个应用程序main
动态加载库first.so
,而后者又动态加载库second.so
,并且main
和first.so
包含RPATH,然后动态链接程序将首先使用second.so
的RPATH搜索first.so
,将$ ORIGIN解析为first.so
的目录,并且只有在失败时,链接器将进入main
的RPATH,现在将$ ORIGIN解析为main
的目录。
这与dynamic linker doc (look for Rpath token expansion)并不矛盾:
$ ORIGIN(或等效为$ {ORIGIN}):这将扩展到包含程序或共享对象的目录。 ...
要进行检查,我创建了一个测试应用程序和两个库:分别为main
,liba
和libb
。 main
与liba
链接,而liba
与libb
链接:
main -> liba.so -> libb.so
构建的二进制文件的定位方式如下:
/cwd/main
/cwd/lib/liba.so
/cwd/lib/libb.so
main
和liba
都是使用--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.so
与liba.so
在同一目录中,因此链接程序无法使用libb.so
的RPATH找到liba.so
。之后,它会退回到main
的RPATH,并且仅使用后者,它才能成功找到libb.so
。
测试环境:Linux ubuntu 4.15.0-34-通用#37〜16.04.1-Ubuntu(64位),/ lib / x86_64-linux-gnu / ld-2.23.so。