找库顺序
动态链接器 /lib64/ld-linux-x86-64.so.2 会以以下的顺序来从路径里找库:
RPATH
LD_LIBRARY_PATH
RUNPATH(和RPATH互斥,如果有RUNPATH会忽略RPATH)
/etc/ld.so.cache (包含系统默认目录中的所有.so的位置,为了加速)
系统默认路径(通常有/lib:/lib64:/usr/lib:/usr/lib64之类的)
如果先找到了库libsomelib.so,被加载之后,后续如果还有elf依赖libsomelib.so的话,就不会继续找,直接复用(也就是说即使libotherlib.so的信息无法直接推断出他依赖的libsomelib.so的位置,如果已经有人先加载了libsomelib.so,libotherlib.so也会加载成功)。
动态链接库自身会携 RPATH和 RUNPATH 两个信息,可以通过以下命令查询
readelf -d /path/to/lib.so其中$ORIGIN代表/path/to也就是elf文件所在的目录。
可以通过patchelf来改变RPATH、RUNPATH字段:
patchelf --print-rpath /path/to/lib.so
patchelf --set-rpath "..." /path/to/lib.soRPATH 和 RUNPATH
RUNPATH 是更新的一个字段,如果elf中同时有RPATH和RUNPATH,那么RPATH会被忽略。
RPATH如果存在并且有效的话,优先级会高于LD_LIBRARY_PATH
RPATH会链式传递,假设有依赖 liba.so -> libb.so -> libc.so,那么libb.so最终的 RPATH 会同时包括两个 .so 的 RPATH。但是 RUNPATH 不会,RUNPATH的设计逻辑就是每个.so只声明自己依赖的部分(并且应当不包括依赖项libc.so的依赖)。