动态链接库的RPATH和RUNPATH解惑

最近在使用SPP网络框架进行业务开发的时候,遭遇动态库搜索路径问题,为了避免其他同学继续在这方面浪费精力,简单整理了相关知识点。

【背景知识】

这里不打算深入链接器内部,简明扼要给出链接器进行动态库搜索的一些规则。

以上是man ld结果部分截图,这里着重澄清两个基本概念:"link time"(链接时)和"runtime"(运行时),比如常用的-L选项属于链接时,而-rpath,LD_LIBRARY_PATH都属于运行时。

很多运维同学倾向于使用LD_LIBRARY_PATH,但是个人认为这并不是一种好方法,因为LD_LIBRARY_PATH作用于全局,可能对其他程序造成未预期的影响。有兴趣的同学可以读一读《Why
LD_LIBRARY_PATH is bad
》,这篇文章有比较全面的分析。

【实践检验】

目录文件:

// main.c
#include <dlfcn.h>

typedef void (*FuncA)(void);

int main(int argc, char *argv[])
{
    void *plugin = dlopen("./libfunc_a.so", RTLD_LAZY);
    FuncA func = (FuncA)dlsym(plugin, "FuncA");
    func();
    return 0;
}
// func_a.c
#include <stdio.h>

void FuncB(void);

void FuncA(void)
{
    printf("[%s]%s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    FuncB();
}
// func_b_sys.c
// func_b_user.c
#include <stdio.h>

void FuncB(void)
{
    printf("[%s]%s:%d\n", __FUNCTION__, __FILE__, __LINE__);
}
# Makefile
all:
    gcc -g -Wall -fPIC -shared -o libfunc_b_sys.so func_b_sys.c
    gcc -g -Wall -fPIC -shared -o libfunc_b_user.so func_b_user.c
    ln -sf /data/warezhou/test/ld/libfunc_b_sys.so /usr/lib64/libfunc_b.so
    ln -sf /data/warezhou/test/ld/libfunc_b_user.so ./lib/libfunc_b.so
    gcc -g -Wall -fPIC -shared -o libfunc_a.so func_a.c -lfunc_b
    gcc -g -Wall -o main main.c -ldl
    gcc -g -Wall -o main_rpath main.c -ldl -Wl,--rpath=./lib,--disable-new-dtags
    gcc -g -Wall -o main_rpath_runpath main.c -ldl -Wl,--rpath=./lib,--enable-new-dtags

clean:
    rm main main_rpath main_rpath_runpath
    rm -rf *.so
    rm -rf /usr/lib64/libfunc_b.so
    rm -rf ./lib/*

实验结果:

【原因分析】

上图关于动态库搜索路径的总结来自qt工程师的blog,有兴趣的同学可以阅读原文。简单来说,当可执行文件同时设置RPATH和RUNPATH时,两者同时失效。

查看SPP源码后,发现Makefile里面没有显式指定disable-new-dtags,而这个选项的默认值是平台相关的,我们公司老的suse默认关闭,而新的tlinux默认开启。所以导致发行包里的可执行文件同时设置了RPATH和RUNPATH,最终导致业务模块.so依赖的第三方.so查找不到。

当然,上述问题,通过设置libfunc_a.so的RPATH也是可以解决问题的,有兴趣的同学可以试一试,因为整个搜索过程是递归向上执行的。

时间: 2024-10-11 21:12:25

动态链接库的RPATH和RUNPATH解惑的相关文章

RPATH与RUNPATH

RPATH与RUNPATH 时间 2011-11-01 21:46:44 Qt Labs China 原文  http://labs.qt.nokia.com.cn/2011/11/01/rpath-and-runpath/ 主题 Qt 原文链接: ckamm - RPATH and RUNPATH DT_RPATH通常设置在这样一种可执行程序中,它依赖的库无法在默认位置中被找到.举例来说,Qt Creator自带一个Qt库的副本,而且有一个指向库文件所在目录的rpath.当你构建自己的Qt库而

探讨CMake中关于RPATH的使用

最近研究CMake,发现CMake对于RPATH的管理也非常人性化.官方说法是当动态库的编译也和执行档在同级目录下的时候,CMake会自动给执行档加入适当的RPATH.具体可以通过readelf -d executable来查看相关的RPATH路径.所以有的时候用QMake编译之后还得手动加一把LD_LIBRARY_PATH,而用CMake编译之后,直接执行执行档就可以了. 相关rpath的说明,同学可以自行google学习,简单来说,RPATH就是在LD_LIBRARY_PATH之前,会优先让

Linux动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序, 动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执 行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以 整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. //elfhash.h #include <stdio.h> unsign

Linux 动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序,动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //elf

linux动态库加载的秘密

摘自http://gotowqj.iteye.com/blog/1926734 摘自http://www.360doc.com/content/14/0313/13/12747488_360246417.shtml linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识. 基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库,使用ldd命令查看 # ldd /bin/ls linux-vdso.so.1 =

lua curl动态链接库编译安装

关于lua curl的资料网上并不是很多.找来找去就那么几个,所以我绝得很有必要把我的经验记下来,以防下次忘记 ---好记性不如烂笔头. 如果在网上(当然是Google)搜索挂关键字“lua curl”或“luacurl”,你搜索的头两条数据很可能是不一样.因为关于lua的curl库有两个:luacurl和Lua-cURL. 如果你打开了这个网址“http://curl.haxx.se/libcurl/lua/”,你就会看这样一段话: There are two different effort

g++ 编译动态链接库和静态链接库

现在我有hello1.cpp和hello2.cpp两个文件,现在我要生成动态链接库libhello.so和静态链接库libhello.a.以下为步骤: 1.生成动态链接库: g++ -m32 hello1.cpp hello2.cpp -fPIC -shared -o ../lib/linux32/libhello.so -m32为生成32位的动态链接库,-m64位生成64位的动态链接库. 2.生成静态链接库: g++ -m32 hello1.cpp -c -o hello1.o  //编译he

c/c++编译时,指定程序运行时查找的动态链接库路径

http://blog.csdn.net/tsxw24/article/details/10220735 c/c++编译时,指定程序运行时查找的动态链接库路径 分类: c/c++ linux 2013-08-23 14:04 1117人阅读 评论(0) 收藏 举报 [plain] view plaincopy $ g++ -Wl,-rpath,/usr/local/lib/ -oevh libevent_http.cpp -levent -Wl,-rpath,  用于指定程序运行时查找动态链接库

Linux下的动态链接库包含漏洞

说明 Nebula是一个用于Linux下提权漏洞练习的虚拟机,其第15关Level15提供了这样一个有漏洞的程序flag15 sh-4.2$ ls -l total 7 -rwsr-x--- 1 flag15 level15 7161 2011-11-20 21:22 flag15 sh-4.2$ whoami level15 要求利用该setuid程序的漏洞,从用户level15提权到用户flag15,执行/bin/getflag. 2. 漏洞挖掘 这道题是一个经典的动态链接库劫持题目,首先用