上一篇《Linux动态链接库同名符号装载问题(一)》中提到了动态链接的一些问题,本文主要讨论动态加载时符号冲突的问题。
PART1:RTLD_DEEPBIND打开动态链接导致段错误的现象
可执行程序A通过dlopen动态加载library.so,有可能出现library.so中和这样的情况:
程序A中存在函数search_hash()
library.so中同样存在函数search_hash()
dlopen使用默认参数情况下,程序A中的search_hash已经加载到全局符号表,当library.so中某个函数想调用search_hash时,实际会调用到进程A中的search_hash函数。为了保证library.so能够优先调用到自己的函数,可以在dlopen时使用RTLD_DEEPBIND参数,优先调用.so内部的参数。
但是,在使用RTLD_DEEPBIND参数打开在某些使用libstdc++的动态链接库是会发生段错误。
GCC网站上的这个BUG report很详细的描述了该现象。
据另一个BUG report中的分析,是由于程序启动时会初始化libstdc++,但是当dlopen某个动态链接库,因为使用了RTLD_DEEPBIND参数,动态链接库内部调用libstdc++中的函数时会被定为到一个未初始化的实例,引起段错误。
尚未找到该问题的解决方案。
PART2:动态加载的链接库冲突符号如何定位?
在某些情况下.so之间也存在依赖,例如还存在另一个library2.so依赖于library.so中的一些函数,就要求在dlopen打开library.so时添加RTLD_GLOBAL参数,将library.so的符号表全局打开。这样有可能造成程序A和library.so中符号名冲突,由于这个冲突时在运行时发生的,很不容易调试。这里提供一个可以在运行前检查的方法:
nm A|awk '{if ($2=="T") print $3}'> symbol
nm library.so|awk '{if ($2=="T") print $3}'>> symbol
cat symbol|sort|uniq -c>collision_symbol
在collision_symbol文件中出现次数大于1的符号就是发生冲突的。
这篇文章很好的分析了Linux动态链接库的机制:http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/index.html