C/C++程序隱藏符號

使用visibility

#ifdef __cplusplus  //如果是C++語言
#define PASSPORT_EXTERN         extern "C" __attribute__((visibility ("default")))
#else
#define PASSPORT_EXTERN         extern __attribute__((visibility ("default")))
#endif

GNU C 的一大特色就是attribute 機制。
試想這樣的情景,程序調用某函數A,A函數存在於兩個動態鏈接庫liba.so,libb.so中,並且程序執行需要鏈接這兩個庫,此時程序調用的A函數到底是來自於a還是b呢?
這取決於鏈接時的順序,比如先鏈接liba.so,這時候通過liba.so的導出符號表就可以找到函數A的定義,並加入到符號表中,鏈接libb.so的時候,符號表中已經存在函數A,就不會再更新符號表,所以調用的始終是liba.so中的A函數。
爲了避免這種混亂,所以使用

__attribute__((visibility("default")))  //默認,設置爲:default之後就可以讓外面的類看見了。
__attribute__((visibility("hideen")))  //隱藏

設置這個屬性。

visibility用於設置動態鏈接庫中函數的可見性,將變量或函數設置爲hidden,則該符號僅在本so中可見,在其他庫中則不可見。

g++在編譯時,可用參數-fvisibility指定所有符號的可見性(不加此參數時默認外部可見,參考man g++中-fvisibility部分);若需要對特定函數的可見性進行設置,需在代碼中使用attribute設置visibility屬性。

編寫大型程序時,可用-fvisibility=hidden設置符號默認隱藏,針對特定變量和函數,在代碼中使用attribute ((visibility("default")))另該符號外部可見,這種方法可用有效避免so之間的符號衝突。

經測試,C++會導出函數參數,C的方式不會,兩者不能通用。

使用version-script

set_target_properties(your_so_or_exe PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/symbol.version")

symbol.version:

{
    global:JNI_OnLoad;JNI_OnUnload;Java_*;usedFun;
    local:*;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章