我有一个 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 上找到任何解释。 (也许我正在寻找错误的东西?)似乎如果我了解这里发生了什么,我就可以倒退以了解为什么首先没有找到图书馆。 最佳答案
与旧的 RPATH
不同,RUNPATH
仅在搜索二进制文件的直接依赖项时适用。
也就是说,如果 a.out
有 RUNPATH
的 /foo
和 NEEDED
的 libfoo.so
(位于 /foo
),那么就会找到 libfoo.so
。但是如果 libfoo.so
本身依赖于 libbar.so
(也位于 /foo
中),并且如果 libfoo.so
没有 RUNPATH
,那么 libbar.so
将不会被找到。
这种行为提倡“每个 ELF 二进制文件都应该自给自足”。在上述情况下, libfoo.so
不是自给自足的(需要 libbar.so
但没有说明在哪里可以找到它)。
如果您改用 RPATH
,则该路径将适用于每次搜索,并且会找到 libbar.so
。您可以在链接 -Wl,--disable-new-dtags
时使用 a.out
实现此目的。
关于linux - 为什么同一个可执行文件对不同的库查找使用不同的 RUNPATH?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52993692/