免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
rdynamic和
userphoto

2015.10.31

關注

遇到如下情況,主程序通過dlopen來打開.so文件,但是.so用到了主程序的log函數(shù)。

編譯so時,通過引用主程序頭文件來編譯通過,頭文件有l(wèi)og函數(shù)聲明:

  extern "C" { 
   void print()
  }

在主程序的.c文件里有函數(shù)的具體實現(xiàn)。


但是dlopen后運行so中函數(shù)時,出現(xiàn)找不到相應的symbol。

這時候就需要在編譯主程序ld時加上參數(shù)-rdynamic,該參數(shù)的作用是:將指示連接器把所有符號(而不僅僅只是程序已使用到的外部符號,但不包括靜態(tài)符號,比如被static修飾的函數(shù))都添加到動態(tài)符號表(即.dynsym表)里,以便那些通過dlopen()或backtrace()(這一系列函數(shù)使用.dynsym表內(nèi)符號)這樣的函數(shù)使用。


-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.


-g是編譯選項,而-rdynamic是鏈接選項

參考:http://www.lenky.info/archives/2013/01/2190


小例子:


a.cc

[cpp] view plaincopy
  1. #include "stdio.h"  
  2. #include <dlfcn.h>  
  3.   
  4. extern "C" {  
  5. void print()  
  6. {  
  7.     printf("I am in so file!\n");  
  8. }  
  9.   
  10. void fun()  
  11. {  
  12.     void * err = dlopen("./libtmp.so", RTLD_LAZY);  
  13.     printf("dlopen = %p\n", err);  
  14.     if (err == NULL) {  
  15.         printf("err=%s\n", dlerror());  
  16.     }     
  17. }  
  18. }  

a.h

[cpp] view plaincopy
  1. extern "C" void print();  
  2. extern "C" void fun();  // 函數(shù)聲明和定義都要有extern “C”,或者都沒有,否則調(diào)用時出現(xiàn)undefined symbol fun  
  3.   
  4. #define NODE_MODULE \  
  5. extern "C" { \  
  6.    static void print_main() __attribute__((constructor)) // dlopen時會自動調(diào)用該contructor函數(shù)</span>  
  7.    static void print_main() { \  
  8.        print(); \  
  9.    } \  
  10. }   


so.cc

[cpp] view plaincopy
  1. #include "a.h"  
  2. #include "stdio.h"  
  3.   
  4. NODE_MODULE  


foo.h

[python] view plaincopy
  1. <span style="font-size:18px;">void foo();</span>  

foo.cc

[cpp] view plaincopy
  1. #include "stdio.h"  
  2.   
  3. void foo()  
  4. {  
  5.     printf("foo === \n");  
  6. }  


main.cc

[cpp] view plaincopy
  1. #include "a.h"  
  2.   
  3. int main(void)  
  4. {  
  5.     fun();  
  6.     return 0;  
  7. }  

Makefile

[cpp] view plaincopy
  1. all:dynamic  
  2.   
  3. libtmp.so:so.cc  
  4.     g++ -fPIC -shared -o $@ $^   
  5.   
  6. a.o:  
  7.     g++ -c a.cc -fPIC  
  8.   
  9. liba.a:a.o  
  10.     ar -r $@  $^   
  11.   
  12. libso.so: foo.cc liba.a  
  13.     g++ -fPIC -shared -o $@ $< -L./ -la -Wl,--whole-archive -la  -Wl,--no-whole-archive -ldl  
  14.   
  15. dynamic:libso.so libtmp.so  
  16.     g++ -o $@ main.cc -Wl,--rpath=. -L./ -lso rdynamic  
  17.   
  18. clean:  
  19.     rm dynamic liba.a a.o libtmp.so  


運行dynamic后輸出為:

[python] view plaincopy
  1. I am in so file!  
  2. dlopen = 0xdeb030  
如果沒有-rdynamic,則輸出為:

[python] view plaincopy
  1. dlopen = (nil)  
  2. err=./libtmp.so: undefined symbol: print  
如果沒有-Wl,--whole-archive -la  -Wl,--no-whole-archive,也會有錯誤:undefined symbol: print


--whole-archive 可以把 在其后面出現(xiàn)的靜態(tài)庫包含的函數(shù)和變量輸出到動態(tài)庫,--no-whole-archive 則關掉這個特性

使用readelf -s libso.so | grep fun來查看libso.so的符號表里是否有fun這個函數(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

  設置默認的ELF鏡像中符號的可見性為隱藏。使用這個特性可以非常充分的提高連接和加載共享庫的性能,生成更加優(yōu)化的代碼,提供近乎完美的API輸出和防止符號碰撞。我們強烈建議你在編譯任何共享庫的時候使用該選項。

-fvisibility-inlines-hidden

        默認隱藏所有內(nèi)聯(lián)函數(shù),從而減小導出符號表的大小,既能縮減文件的大小,還能提高運行性能,我們強烈建議你在編譯任何共享庫的時候使用該選項


所以編譯的時候也不能有-fvisibility=hidden和-fvisibility-inlines-hidden。如果有,也會在dlopen時造成錯誤:undefined symbol

總結:

本實例雖小,但用到了不少編譯選項

a: __attribute__((constructor))
主程序main函數(shù)之前被執(zhí)行或dlopen時被執(zhí)行

b: -rdynamic

ld時將動態(tài)庫的的所有符號都輸出到符號表,以便dlopen和backtrace也能調(diào)用

c: --whole-archive -la -Wl,--no-whole-archive

靜態(tài)庫的符號導入到動態(tài)庫的符號表中,默認是hidden的

d: -fvisibility=hidden和-fvisibility-inlines-hidden

ELF鏡像中符號的可見性為隱藏(在實驗過程中不太好用,待研究)


在編譯nodejs第三方模塊時都會碰到這樣的問題,第三方模塊依賴與nodejs進行編譯,而第三方模塊又是通過dlopen來打開的,這就要求nodejs編譯時將一下第三方模塊需要的函數(shù)都暴露出來。


參考:

http://www.fx114.net/qa-225-106759.aspx

http://os.chinaunix.net/a2010/0112/1060/000001060902_3.shtml



版權聲明:本文為博主原創(chuàng)文章

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
動態(tài)庫全局符號介入與引用效率分析 | 睿初科技軟件開發(fā)技術博客
Linux動態(tài)庫(二)
應用程序設計:在動態(tài)庫中如何調(diào)用外部函數(shù)?
qt creator編譯opus庫
在C/C++程序中打印當前函數(shù)調(diào)用棧
Linux 共享庫文件
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服