遇到如下情況,主程序通過dlopen來打開.so文件,但是.so用到了主程序的log函數(shù)。 編譯so時(shí),通過引用主程序頭文件來編譯通過,頭文件有l(wèi)og函數(shù)聲明: extern "C" { 在主程序的.c文件里有函數(shù)的具體實(shí)現(xiàn)。
但是dlopen后運(yùn)行so中函數(shù)時(shí),出現(xiàn)找不到相應(yīng)的symbol。 這時(shí)候就需要在編譯主程序ld時(shí)加上參數(shù)-rdynamic,該參數(shù)的作用是:將指示連接器把所有符號(而不僅僅只是程序已使用到的外部符號,但不包括靜態(tài)符號,比如被static修飾的函數(shù))都添加到動態(tài)符號表(即.dynsym表)里,以便那些通過dlopen()或backtrace()(這一系列函數(shù)使用.dynsym表內(nèi)符號)這樣的函數(shù)使用。
-rdynamic
-g是編譯選項(xiàng),而-rdynamic是鏈接選項(xiàng) 參考:http://www./archives/2013/01/2190
小例子:
a.cc [cpp] view plaincopy
a.h [cpp] view plaincopy
[cpp] view plaincopy
foo.h [python] view plaincopy
foo.cc [cpp] view plaincopy
main.cc [cpp] view plaincopy
Makefile [cpp] view plaincopy
運(yùn)行dynamic后輸出為: [python] view plaincopy
[python] view plaincopy
--whole-archive 可以把 在其后面出現(xiàn)的靜態(tài)庫包含的函數(shù)和變量輸出到動態(tài)庫,--no-whole-archive 則關(guān)掉這個(gè)特性 使用readelf -s libso.so | grep fun來查看libso.so的符號表里是否有fun這個(gè)函數(shù)暴露出來。有--whole-archive的可以查到fun,而沒有--whole-archive的,則找不到fun 先理清一下code 可執(zhí)行文件dynamic依賴與libso.so,而libso.so有包含liba.a,在liba.a的函數(shù)fun調(diào)用dlopen來打開libtmp.so 主函數(shù)調(diào)用liba.a的函數(shù)來打開libtmp.so
-fvisibility=hidden 設(shè)置默認(rèn)的ELF鏡像中符號的可見性為隱藏。使用這個(gè)特性可以非常充分的提高連接和加載共享庫的性能,生成更加優(yōu)化的代碼,提供近乎完美的API輸出和防止符號碰撞。我們強(qiáng)烈建議你在編譯任何共享庫的時(shí)候使用該選項(xiàng)。 -fvisibility-inlines-hidden 默認(rèn)隱藏所有內(nèi)聯(lián)函數(shù),從而減小導(dǎo)出符號表的大小,既能縮減文件的大小,還能提高運(yùn)行性能,我們強(qiáng)烈建議你在編譯任何共享庫的時(shí)候使用該選項(xiàng)
所以編譯的時(shí)候也不能有-fvisibility=hidden和-fvisibility-inlines-hidden。如果有,也會在dlopen時(shí)造成錯(cuò)誤:undefined symbol 本實(shí)例雖小,但用到了不少編譯選項(xiàng) a: __attribute__((constructor)) b: -rdynamic ld時(shí)將動態(tài)庫的的所有符號都輸出到符號表,以便dlopen和backtrace也能調(diào)用 c: --whole-archive -la -Wl,--no-whole-archive 靜態(tài)庫的符號導(dǎo)入到動態(tài)庫的符號表中,默認(rèn)是hidden的 d: -fvisibility=hidden和-fvisibility-inlines-hidden ELF鏡像中符號的可見性為隱藏(在實(shí)驗(yàn)過程中不太好用,待研究)
參考: http://www./qa-225-106759.aspx http://os./a2010/0112/1060/000001060902_3.shtml 版權(quán)聲明:本文為博主原創(chuàng)文章 |
|