为什么同一个可执行文件对不同的库查找使用不同的 RUNPATH? [英] Why does the same executable use different RUNPATHs for different library lookups?

查看:42
本文介绍了为什么同一个可执行文件对不同的库查找使用不同的 RUNPATH?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Linux C++ 程序可以构建 &链接(使用 -Wl,--no-undefined,不少于)但是当我尝试运行它时无法加载它的所有库.我一直在尝试使用 ldd 检查它的依赖关系,但我不明白为什么它会被失败的库绊倒:

$ ldd standalone_test...找到了很多图书馆...libPythia6.so =>未找到

现在,这个库位于根据嵌入在可执行文件中的RUNPATH应该找到的位置:

$ readelf -d ./standalone_test |grep运行路径"0x000000000000001d (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/libliblund.a libPythia6.so pydata.o

(以及可执行文件 standalone_test 和库 libPythia6.so 都是 ELF64,所以我不认为这是处理器架构不匹配或类似的问题.)

我尝试进一步深入了解库加载过程中发生的情况,并且我注意到不同的 RUNPATH 被报告用于在同一可执行文件下加载不同的库(其中一些是'chain' 在可执行文件请求的库请求的位置加载它们):

$ LD_DEBUG=libs,files ./standalone_test 2>&1 |确认运行路径# 这是正确"的 RUNPATH(来自可执行文件的)19553:搜索路径=/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(来自文件 ./standalone_test 的 RUNPATH)# 下一个已经增强"了处理器架构子目录19553:搜索路径=/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/精灵支持/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(运行路径从文件 ./standalone_test)......这两个的更多变体......# 这个只包含来自真实运行路径的一个条目??19553:搜索路径=/opt/root/lib(来自文件 ./standalone_test 的运行路径)

在最后一种情况下,没有找到库并且可执行文件失败并显示 cannot open shared object file: No such file or directory 错误,它继续查看系统搜索路径也是如此.

我的问题是:RUNPATH 上的这些变体是如何炮制的?我认为它们是由各种以某种方式请求它们的库修改的,但我不能似乎在 googlewebs 上找不到任何解释.(也许我正在寻找错误的东西?)似乎如果我了解这里发生了什么,我就可以倒退以了解为什么没有首先找到图书馆.

解决方案

我的问题是:RUNPATH 上的这些变体是如何编造的?

与旧的 RPATH 不同,RUNPATH适用于搜索二进制文件的直接依赖项.>

也就是说,如果a.out/fooRUNPATH,以及NEEDEDlibfoo.so(位于/foo),然后会找到libfoo.so.但是如果libfoo.so本身依赖于libbar.so(也位于/foo),如果libfoo.so没有RUNPATH,那么libbar.so找不到.

这种行为提倡每个 ELF 二进制文件都应该自给自足".在上面的例子中,libfoo.so 不是自给自足的(需要 libbar.so 但没有说明在哪里可以找到它).

如果您改用 RPATH,则该路径将适用于 每个 搜索,并且会找到 libbar.so.您可以在链接 a.out 时使用 -Wl,--disable-new-dtags 实现此目的.

I have a Linux C++ program that builds & links (with -Wl,--no-undefined, no less) but fails to load all of its libraries when I try to run it. I've been trying to inspect its dependencies with ldd, but I can't figure out why it's tripping over the library that's failing:

$ ldd standalone_test
   ...  lots of libraries that are found ...
libPythia6.so => not found

Now, this library is in a place where it ought to be found according to the RUNPATH embedded in the executable:

$ 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

(and both the executable standalone_test and the library libPythia6.so are ELF64, so I don't think it's a processor architecture mismatch or something like that.)

I've tried digging further into what's going on during library loading, and I've noticed that different RUNPATHs are reported for the loading of different libraries under the same executable (some of these are 'chain' loads where they're requested by a library that was requested by the executable):

$ 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)

In the last case, the one where the library isn't located and the executable fails with a cannot open shared object file: No such file or directory error, it moves on to looking in the system search path as well.

My question is: how are these variants on RUNPATH concocted? I gather that they're modified by the various libraries that are requesting them somehow, but I can't seem to find any explanations out there on the googlewebs. (Maybe I'm searching for the wrong thing?) It seems like if I understood what was going on here, I'd be able to work backwards to understanding why the library isn't being found in the first place.

解决方案

My question is: how are these variants on RUNPATH concocted?

Unlike older RPATH, the RUNPATH applies only when searching for direct dependencies of the binary.

That is, if a.out has RUNPATH of /foo, and NEEDED of libfoo.so (located in /foo), then libfoo.so will be found. But if libfoo.so itself depends on libbar.so (also located in /foo), and if libfoo.so does not have RUNPATH, then libbar.so will not be found.

This behavior promotes "every ELF binary should be self-sufficient". In the case above, libfoo.so is not self-sufficient (needs libbar.so but doesn't say where to find it).

If you use RPATH instead, the path there would apply to every search, and libbar.so will be found. You can achieve this with -Wl,--disable-new-dtags when linking a.out.

这篇关于为什么同一个可执行文件对不同的库查找使用不同的 RUNPATH?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆