我有一个Linux C ++程序,该程序可以建立和链接(不少于-Wl,--no-undefined
),但是在尝试运行它时无法加载其所有库。我一直在尝试使用ldd
检查其依赖项,但是我不知道为什么它会在失败的库上绊倒:
$ ldd standalone_test
... lots of libraries that are found ...
libPythia6.so => not found
现在,该库 位于应该根据可执行文件中嵌入的RUNPATH
找到的地方:
$ readelf -d ./standalone_test | grep "RUNPATH"
0x000000000000001d (RUNPATH) Library runpath: [/home/jeremy/code/NOvARwgt/cmake-build-debug/src:/home/jeremy/code/genie-2.12.2/lib:/opt/genie/GENIESupport/pythia6/v6_424/lib:/opt/root/lib:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug]
$ ls /opt/genie/GENIESupport/pythia6/v6_424/lib
liblund.a libPythia6.so pydata.o
(而且可执行文件standalone_test
和库文件libPythia6.so
都是ELF64,所以我不认为这是处理器体系结构不匹配或类似的东西。)
我尝试进一步研究库加载过程中发生的情况,并且我注意到,对于同一可执行文件下的不同库的加载,报告了不同的RUNPATH
(一些是“链式”)加载可执行文件所请求的库所请求的位置)
$ LD_DEBUG=libs,files ./standalone_test 2>&1 | ack RUNPATH
# this one is the 'correct' RUNPATH (the one from the executable)
19553: search path=/opt/root/lib/tls/haswell/x86_64:/opt/root/lib/tls/haswell:/opt/root/lib/tls/x86_64:/opt/root/lib/tls:/opt/root/lib/haswell/x86_64:/opt/root/lib/haswell:/opt/root/lib/x86_64:/opt/root/lib (RUNPATH from file ./standalone_test)
# next one has been 'augmented' with processor architecture subdirs
19553: search path=/home/jeremy/code/NOvARwgt/cmake-build-debug/src/tls/haswell/x86_64:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/tls/haswell:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/tls/x86_64:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/tls:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/haswell/x86_64:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/haswell:/home/jeremy/code/NOvARwgt/cmake-build-debug/src/x86_64:/home/jeremy/code/NOvARwgt/cmake-build-debug/src:/home/jeremy/code/genie-2.12.2/lib/tls/haswell/x86_64:/home/jeremy/code/genie-2.12.2/lib/tls/haswell:/home/jeremy/code/genie-2.12.2/lib/tls/x86_64:/home/jeremy/code/genie-2.12.2/lib/tls:/home/jeremy/code/genie-2.12.2/lib/haswell/x86_64:/home/jeremy/code/genie-2.12.2/lib/haswell:/home/jeremy/code/genie-2.12.2/lib/x86_64:/home/jeremy/code/genie-2.12.2/lib:/opt/genie/GENIESupport/pythia6/v6_424/lib/tls/haswell/x86_64:/opt/genie/GENIESupport/pythia6/v6_424/lib/tls/haswell:/opt/genie/GENIESupport/pythia6/v6_424/lib/tls/x86_64:/opt/genie/GENIESupport/pythia6/v6_424/lib/tls:/opt/genie/GENIESupport/pythia6/v6_424/lib/haswell/x86_64:/opt/genie/GENIESupport/pythia6/v6_424/lib/haswell:/opt/genie/GENIESupport/pythia6/v6_424/lib/x86_64:/opt/genie/GENIESupport/pythia6/v6_424/lib:/opt/root/lib:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/tls/haswell/x86_64:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/tls/haswell:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/tls/x86_64:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/tls:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/haswell/x86_64:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/haswell:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug/x86_64:/cvmfs/nova-development.opensciencegrid.org/novasoft/releases/development/lib/Linux2.6-GCC-debug (RUNPATH from file ./standalone_test)
... more variants of these two ...
# this one contains only a single entry from the real runpath??
19553: search path=/opt/root/lib (RUNPATH from file ./standalone_test)
在最后一种情况下,没有找到库且可执行文件因cannot open shared object file: No such file or directory
错误而失败的代码,它也继续查找系统搜索路径。
我的问题是: RUNPATH
上的这些变体是如何配制的?我收集到它们已被各种要求它们的图书馆修改,但我似乎无法在googlewebs上找到任何说明。 (也许我在搜索错误的东西?)似乎,如果我了解这里发生的事情,我将可以倒退以了解为什么首先找不到该库。
答案 0 :(得分:2)
我的问题是:RUNPATH上的这些变体是如何配制的?
与较早的RPATH
不同,RUNPATH
在搜索二进制文件的 direct 依赖项时仅应用 。
也就是说,如果a.out
的{{1}}中的RUNPATH
和/foo
中的NEEDED
(位于libfoo.so
中),则{{ 1}}。但是,如果/foo
本身依赖于libfoo.so
(也位于libfoo.so
中),并且如果libbar.so
没有 有/foo
,则将找不到libfoo.so
。
此行为提倡“每个ELF二进制文件都应自给”。在上述情况下,RUNPATH
不能自给自足(需要libbar.so
,但没有说明在哪里找到它)。
如果您改用libfoo.so
,则该路径将应用于每次搜索,并且将找到libbar.so
。链接RPATH
时,可以使用libbar.so
来实现。