这个页面 - http://labs.qt.nokia.com/2011/10/28/rpath-and-runpath/ - 说明了ld.so中的库搜索顺序:
Unless loading object has RUNPATH:
RPATH of the loading object,
then the RPATH of its loader (unless it has a RUNPATH), ...,
until the end of the chain, which is either the executable
or an object loaded by dlopen
Unless executable has RUNPATH:
RPATH of the executable
LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs
Run Code Online (Sandbox Code Playgroud)
然后建议:
当您发送二进制文件时,要么使用RPATH而不是RUNPATH,要么确保在运行之前设置LD_LIBRARY_PATH.
因此,使用RPATHwith RUNPATH是不好的,因为RUNPATH取消了类似的RPATH间接动态加载不能按预期工作?但为什么然后RPATH被弃用RUNPATH呢?
有人可以解释一下情况吗?
我构建了一个R包,它使用Rcpp并链接到第三方共享对象(libbarraopt.so)(它也链接到其他共享对象,例如liboptsrvr.so在它自己的目录中).为了确保它能够找到它链接的那些共享对象,我将以下变量放入~/.Renviron:
BARRA_OPS_HOME=${HOME}/bin/BarraOptimizer8.5
Run Code Online (Sandbox Code Playgroud)
在包中,我创建了以下内容src/Makevars:
BARRA_LIB=$(BARRA_OPS_HOME)/lib/intel64
BARRA_INCLUDE=$(BARRA_OPS_HOME)/include
PKG_CXXFLAGS=-I$(BARRA_INCLUDE)
PKG_CFLAGS=-I$(BARRA_INCLUDE)
PKG_LIBS=-L$(BARRA_LIB) -Wl,-R,$(BARRA_LIB) -lbarraopt
Run Code Online (Sandbox Code Playgroud)
在Ubuntu 16.04下,我可以成功构建,加载和使用包,没有任何问题.但是,当我将操作系统升级到17.10时测试完全相同的软件包时,可以构建软件包,但无法加载,说:
g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I"/home/renkun/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -I/home/renkun/bin/BarraOptimizer8.5/include -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o
** libs
g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I"/home/renkun/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -I/home/renkun/bin/BarraOptimizer8.5/include -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c barraopt.cpp -o barraopt.o
g++ -std=gnu++11 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o barraopt.so RcppExports.o barraopt.o -L/home/renkun/bin/BarraOptimizer8.5/lib/intel64 -Wl,-R,/home/renkun/bin/BarraOptimizer8.5/lib/intel64 -lbarraopt -L/usr/lib/R/lib -lR
installing to /tmp/Rtmpvbb6Io/devtools_install_42a342a07f84/barraopt/libs
* DONE …Run Code Online (Sandbox Code Playgroud) 我有一个共享库,我想动态链接到几个单独的二进制货物应用程序.我使用-- -L /path/to/dir格式在链接器中包含它的位置,并且应用程序正确编译,我期望的二进制大小显着减少.但是,在使用时检查生成的二进制文件时ldd,我收到一条消息,指出无法找到该库:
casey@Gilthar-II:~/bot4/backtester/target/release$ ldd backtester
linux-vdso.so.1 => (0x00007ffc642f7000)
libalgobot_util.so => not found
Run Code Online (Sandbox Code Playgroud)
如果我将库添加到/lib/x86_64-linux-gnu目录,应用程序运行没有问题.
有没有办法让Rust在与二进制文件相同的目录中查找.so文件,或者在二进制文件目录中的lib目录中查找要在运行时加载的文件?如果那是不可能的,有没有办法至少让Rust插入它所链接的库的绝对路径?
我试过设置rpath = true没有效果.
我最近在系统升级后遇到了这个问题:使用GCC -Wl,-rpath=选项的工作方式与以前不同。
我用它来设置一些在我的项目子模块中构建的共享库的搜索路径。当时我认为它比在LD_LIBRARY_PATH系统范围内进行设置要好(我不想每次打开计算机时都进行设置)。一切正常,这两种方法似乎是等效的。
现在,它的行为-rpath已经改变。它仍然适用于直接依赖的库,但不适用于通过链接来自同一目录集的其他库的库-rpath=。导出LD_LIBRARY_PATH仍然可以像以前一样进行。
我使用来检查了编译的输出,readelf并且有所不同。升级之前(Linux Mint 18.2和GCC 5.4),“ 动态”部分具有以下内容:
0x000000000000000f (RPATH) Library rpath: [submod/lib]
Run Code Online (Sandbox Code Playgroud)
升级后(带有GCC 7.3的Linux Mint 19),该行更改为:
0x000000000000001d (RUNPATH) Library runpath: [submod/lib]
Run Code Online (Sandbox Code Playgroud)
在使用RPATH而不是RUNPATH吗?建议将RPATH替换为RUNPATH(或者说,它至少具有不同的用途,因为它的优先级较低),但是它没有给出答案为什么会影响间接链接。库本身在readelf输出中既没有RPATH也没有RUNPATH 。
所以我的问题是:为什么链接程序突然开始以-rpath=不同的方式解释选项,并且有办法强制执行旧的行为?(或者做一些不同的事情,将产生相同的结果。)
另一个问题是:是否可以告诉链接器的旧版本产生新的输出(即RUNPATH而不是RPATH)?
编辑
这不是如何设置二进制文件的RunPath的副本。-我的问题恰恰相反:我想要RPATH的行为。我知道了(感谢评论中的技巧),我将在这里回答我的问题。
我正在尝试访问“集合结构”(struct r_debug *)以便找到进程的链接图。但我不断遇到无效地址,我真的不知道发生了什么。
以下是我继续尝试找到它的方法:
1. Get the AT_PHDR value from the auxiliary vector
2. Go through the program headers until I find the PT_DYNAMIC segment
3. Try to access the vaddr of that segment (PT_DYNAMIC) to get the dynamic tags
4. Iterate through the dynamic tags until I find DT_DEBUG. If I get here I should be done
Run Code Online (Sandbox Code Playgroud)
问题是我无法通过步骤 3,因为 PT_DYNAMIC 段的 vaddr 始终指向无效地址。
我究竟做错了什么 ?我需要找到 vaddr 的重定位吗?我查看了 LLDB 来源,但我不知道他们是如何获得地址的。
更新:@EmployedRussian 是对的,我正在寻找一个与位置无关的可执行文件。他的计算搬迁的解决方案效果非常好。