我有一个 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.outRUNPATH/fooNEEDEDlibfoo.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/

10-14 14:18
查看更多