Linux動態連結庫同名符號裝載問題(二)
上一篇《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的符號就是發生衝突的。