简要说明下影响库搜索的命令及变量问题。
符号问题 readelf -wa /path/to/elf/exe
用以下的命令可以看到链接关系: readelf -d /path/to/elf/exe
--------------------------------------------------------------------------
动态链接器对共享库的查找顺序:
LD_LIBRARY_PATH
、-L
和-rpath
;/etc/ld.so.cache
;- 默认共享库目录:
/usr/lib
、/lib
;
-------------------------------------------------------------------------
链接时路径与运行时路径:
链接器ld的选项有 -L,-rpath 和 -rpath-link,看了下 man ld,大致是这个意思:
-L: “链接”的时候,去找的目录,也就是所有的 -lFOO 选项里的库,都会先从 -L 指定的目录去找,然后是默认的地方。编译时的-L选项并不影响环境变量LD_LIBRARY_PATH,-L只是指定了程序编译连接时库的路径,并不影响程序执行时库的路径,系统还是会到默认路径下查找该程序所需要的库,如果找不到,还是会报错,类似cannot open shared object file。
-rpath-link:这个也是用于“链接”的时候的,例如你显式指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。
-rpath: “运行”的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找。对于交叉编译,交叉编译链接器需已经配置 --with-sysroot 选项才能起作用。
总结 :
-rpath指定的路径会被记录在生成的可执行程序中,用于运行时查找需要加载的动态库。
-rpath-link 则只用于链接时查找。
--------------------------------------------------------------------------------------------------------------------
- 简单的路径依赖关系
通常,系统默认使用 /lib, /usr/lib, /usr/lib64,/usr/loca/lib/ 等位置搜索so文件, 如果我们需要添加其它路径,可以在 /etc/ld.conf.d/下写一个新的配置文件,比如 xx.conf , 然后在里面每行写一个路径,重启或ldconfig重新读取路径即可
2. 强制指定
但是好多时候我们需要让程序自己能查找路径而不是外部设置so搜索设置,这个时候需要链接命令中指定路径,这些路径包括:
--Wl, -rpath=xx/xx/lib
--Wl, -rpath=$$ORIGIN/xx/lib
之类,我们就需要好好说道了。 $$ORIGIN 会在运行时被替换为程序当前路径。
3. 程序相对路径
RUNPATH , 由--rpath指定的路径,运行时会被替换为运行时的路径(相对或绝对)
LD_LIBRARY_PATH 全局搜索路径(可用,但是不建议用)
使用 readelf -a /path/to/lib |grep path 可以看到rpath之类信息。
4 :高优先级路径
LD_PRELOAD 设置此路会强制搜索里面的文件并用来替换同名函数,说白了就是用实现apihook
5 调试
LD_DEBUG
LD_DEBUG=libs,symbols a.out #显式指定需要打印的信息
ldconfig /path/to/lib 强制将/path/to/lib添加到搜索路径中 但是不永久生效