簡體   English   中英

"加載兩個具有相同靜態鏈接函數的共享庫時使用哪個函數"

[英]Which function is used when loading two shared libraries with same statically linked functions

我一直在閱讀並試圖了解符號如何在 Linux 的共享庫中得到解析。 所以這里是我所面臨的描述。

我正在使用可以加載用戶創建的共享庫以添加功能的應用程序 ( APP )。 我有兩個這樣的庫, LIB_A.soLIB_B.so ,它們執行單獨的事情並且不依賴於另一個來工作。 它們是獨立編譯的,並且基於編譯器參數( -fPIC ),看起來它會使符號可插入(來自我對該主題的研究)。 所以大多數符號將默認導出。

現在,有一個LIB_ALIB_B都使用的公共代碼,它被編譯並與每個庫靜態鏈接。 公共代碼不使用任何命名空間或靜態函數,所以我假設它們也會被導出。 LIB_A 和 LIB_B 都按 APP 中的預期加載和工作。

但是如果在公共代碼中發現了一個錯誤,但只有LIB_A可以重新編譯,因為它需要固定的代碼。 我的問題是,當重新編​​譯LIB_A以獲取公共代碼中的此更改並在APP中加載時,是否會有LIB_A (已修復錯誤)和 LIB_B 沒有錯誤修復)並且每個人都將使用各自的副本,還是都鏈接並共享兩者中的公共代碼版本之一? 有沒有辦法讓我使用調試器來發現符號的來源?

只是為了提前回答問題,我不知道庫將按哪個順序加載,我無法重新編譯 LIB_B 來獲取更改,只有 LIB_A。 我沒有 APP 的源代碼,不知道它是如何動態加載庫的。

我知道編譯器標志有很多,但假設它只是-fPIC ,沒有設置-fvisibility-hidden-Wl,-Bsymbolic-fno-semantic-interposition標志。 如果發生沖突,這些會解決這個問題嗎?

我查看了使用nm -D命令,我看到一些符號是 W,這是否意味着它會使用現有的符號,如果它在使用使用庫靜態構建的符號之前已經存在?

我一直在閱讀文章和搜索,但我不確定我是否 100% 確定了這一點。

編輯有關更多信息,我在運行時按需加載這些庫。 通過將dlopenRTLD_LOCALRTLD_GLOBAL一起使用,這會改變什么嗎? 從描述來看, RTLD_LOCAL 似乎阻止了全局加載符號,因此不會沖突或鏈接到庫外的其他符號?

LIB_A(有錯誤修復)和 LIB_B(沒有錯誤修復)是否有單獨的公共代碼副本?

在沒有-fvisibility=hidden (或您提到的其他類似標志)的情況下,運行時鏈接器將確保將所有重復符號解析為相同的實現(在 LIB_A 或 LIB_B 中)。 所以庫將有效地共享代碼。

有沒有辦法讓我使用調試器來發現符號的來源?

通常,符號將從提供它們的第一個加載庫(LIB_A 或 LIB_B)中獲取。 庫將按照它們在可執行文件的.dynamic部分中列出的順序加載(運行readelf -d app以確保或簡單地運行您的應用程序,並將LD_DEBUG變量設置為symbols )。 如果要強制首先加載 LIB_A,可以相應地設置LD_PRELOAD

我知道編譯器標志有很多,但假設它只是-fPIC ,沒有-fvisibility-hidden -Wl,-Bsymbolic , -Wl,-Bsymbolic-fno-semantic-interposition標志被設置。 如果發生沖突,這些會解決這個問題嗎?

我假設您希望每個庫都使用它自己版本的通用符號? 實現此目標的最標准方法是-fvisibility=hidden 這將防止通用符號被導出,然后它們將被靜態解析為本地副本。 當然,那么您需要找到並注釋其他需要導出的函數。

-Bsymbolic也可能有所幫助,但這將強制解析所有本地可解析的引用,即您將無法將其限制為您感興趣的符號子集。而且它的使用范圍也不太廣泛。

至於-fno-semantic-interposition ,我手頭沒有最近的 GCC,但我的印象是它是編譯器的優化標志,通常不能保證符號的本地分辨率。

我查看了使用 nm -D 命令,我看到一些符號是 W,這是否意味着它會使用現有符號,如果它在使用庫中靜態構建的符號之前已經存在?

不,運行時鏈接器沒有考慮符號的弱點(至少沒有我不推薦使用的LD_DYNAMIC_WEAK 環境變量)。

回答你的部分問題:

有沒有辦法讓我發現符號的來源

如果您定義環境變量LD_DEBUG=bindings並運行您的程序,您將得到它。 其他選項可用,使用LD_DEBUG=help獲取列表。

補充說明<\/h2>

他們有以下符號:

在 host.exe 中使用這些來加載時<\/strong>

 libA 中可用的函數:[ func_host()<\/code> , func_libA()<\/code> ]
libB 中可用的函數:[ func_host()<\/code> , func_libB()<\/code> ]

另一件事可能會有所幫助<\/h2>

如果<\/strong>您不想在 libA 符號表中調用func_host()<\/code> ,請使用RTLD_DEEPBIND | RTLD_LOCAL<\/code> 而是RTLD_DEEPBIND | RTLD_LOCAL<\/code> 。

"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM