为什么同一个可执行文件对不同的库查找使用不同的RUNPATH?

时间:2018-10-25 16:05:35

标签: linux shared-libraries

我有一个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上找到任何说明。 (也许我在搜索错误的东西?)似乎,如果我了解这里发生的事情,我将可以倒退以了解为什么首先找不到该库。

1 个答案:

答案 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来实现。