编译、链接、装载库问题记录

编译、链接、装载库问题记录

本篇文章用于记录在开发过程中遇到的编译、链接、装载库相关的问题及最后处理结果。

关于-rdynamic选项

问题描述:
一个应用程序app1,启动时动态加载一个动态库a.so,在调用该动态库的函数时,程序coredump。应用程序编译时链接静态库 static.a,动态库a.so同时也链接了同一个静态库 static.a。

编译环境:RHEL6.8,GCC 4.4.7

分析解决:
app1动态加载a.so(dlopen)后,调用该动态库的导出函数,函数内调用了静态库static.a中的函数func1,该函数func1未载入动态符号表中,导致寻址失败,直接coredump。
编译链接应用程序app1时应该加上链接选项-rdynamic,该选项指明的解释如下:

-rdynamic
Pass the flag ‘-export-dynamic’ to the ELF linker, on targets that support
it. This instructs the linker to add all symbols, not only used ones, to the
dynamic symbol table. This option is needed for some uses of dlopen or to
allow obtaining backtraces from within a program.

默认情况下,非动态库文件内定义的非静态函数,是不放到动态符号表中的,链接时只有加上-rdynamic才能将所有非静态函数加到动态符号表中,加上参数-rdynamic,将指示连接器把所有符号(而不仅仅只是程序已使用到的外部符号,但不包括静态符号,比如被static修饰的函数)都添加到动态符号表(即.dynsym表)里,以便那些通过dlopen()或backtrace()(这一系列函数使用.dynsym表内符号)这样的函数使用。

该问题在RHEL7.5,GCC4.8.5中不存在,可能在更高级的编译器中,默认链接选项带有-rdynamic。

关于-Wl,Bsymbolic选项

问题描述:
一个应用程序app1,编译时链接静态库 static.a(v1版本),启动时动态加载一个动态库a.so,动态库a.so也链接了同一静态库 static.a(v2版本),app1调用该动态库的导出函数,该导出函数会调用静态库中的函数func1,该func1在静态库static.a的v1版本和v2版本实现不同,预期结果是,func1应该调用动态库a.so链接的static.a(v2版本)中的实现,但实际结果变成调用了app1链接的static.a(v1版本)中的实现。

编译环境:RHEL6.8,GCC 4.4.7

分析解决:
根据问题描述,原因为动态库a.so导出函数中调用的函数被应用程序中同名函数覆盖。
-Wl,Bsymbolic链接选项,Wl表示将紧跟其后的参数,传递给连接器ld。Bsymbolic表示强制采用本地的全局变量定义,这样就不会出现动态链接库的全局变量定义被应用程序/动态链接库中的同名定义给覆盖。

参考链接:
《What exactly does -Bsymblic do?》
《Symbolism and ELF files (or, what does -Bsymbolic do?)》
《Option -Bsymbolic can cause dangerous side effects》

待续。。。

猜你喜欢

转载自blog.csdn.net/zuolj/article/details/111149774