2011-01-13 31 views
7

假設我有:GCC鏈接到一個共享對象的連接器的名稱

  • /usr/lib/libsomething.so.1上機A;
  • /usr/lib/libsomething.so.2機器B.

兩臺機器有/usr/lib/libsomething.so符號鏈接到各自庫。

如果我鏈接使用gcc-lsomething(甚至/usr/lib/libsomething.so),它會跟隨符號鏈接,並ldd機器A生產的是這樣的:

libsomething.so.1 => /usr/lib/libsomething.so.1 

這意味着它將無法找到庫在機器B.

現在我知道這些是主要版本號的變化,我知道他們可能不兼容,但我願意冒這個風險。我想告訴鏈接是尋找libsomething.so,不遵循符號鏈接,以便ldd將顯示

libsomething.so => /usr/lib/libsomething.so.1 
上一個

libsomething.so => /usr/lib/libsomething.so.2 
上B.

然後裝載機將遵循符號鏈接到任何版本。

此外,我不想延遲加載與dlopen或任何東西。我希望它在編譯時鏈接到共享對象。

這甚至可能嗎?

回答

8

製作使用任何可用版本的共享庫的可執行文件當然是可能的。

的問題是,你聯繫你的可執行文件到特定版本的SONAMElibsomething.so.1libsomething.so.2)。您應該使用unversioned soname libsomething.so代替它。

爲了實現這一目標,在構建機上,你應該編譯和SONAME(ELF SONAME)等於libsomething.so(不含版)安裝庫,同時構建可執行程序鏈接器可以選擇這種SONAME。按照Shared Libraries HOWTO,您可以通過所需的

無版本SONAME在構建庫:

gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o 

然後,只要你安裝庫和運行ldconfig,您有:

  • 符號鏈接/lib/libsomething.so指向機器A上的/lib/libsomething.so.1;
  • 符號鏈接/lib/libsomething.so指向/lib/libsomething.so.2上機B.

裝載機(運行ldd)將選擇未版本控制符號鏈接無論在哪裏它指向:

  • libsomething.so => /lib/libsomething.so (0xNNNNNNNN)上機A;
  • libsomething.so => /lib/libsomething.so (0xNNNNNNNN)上機B.

Linux動態加載(ld.so)解析基於寫入在可執行(ELF NEEDED)它們的soname值庫。在構建可執行文件時,該值從庫文件(ELF SONAME)中複製而來。只要目標系統上存在與可執行文件中記錄的soname相匹配的符號鏈接,該符號鏈接指向的庫就會被加載。


讓我們通過您設置和顯示運行命令verifing假設。

爲了清晰起見,我使用Fedora 18 X86_64進行測試並將輸出調整爲i686

  • 編譯兩個libsomething.so.1libsomething.so.2。確保SONAME設置爲無版本libsomething.so

    readelf -a libsomething.so.1 | grep SONAME 
    0xNNNNNNNN (SONAME)    Library soname: [libsomething.so] 
    
    readelf -a libsomething.so.2 | grep SONAME 
    0xNNNNNNNN (SONAME)    Library soname: [libsomething.so] 
    
  • 安裝庫到各自的機器/lib/目錄下。在兩臺機器上運行ldconfig -v並驗證輸出。

    ldconfig -v 2>&1 | grep something 
    libsomething.so -> libsomething.so.1 (changed) 
    
    ldconfig -v 2>&1 | grep something 
    libsomething.so -> libsomething.so.2 (changed) 
    
  • 編譯可執行文件,並確保它指的是同一的soname沒有版本NEEDED

    readelf -a executable | grep NEEDED 
    0xNNNNNNNN (NEEDED)    Shared library: [libsomething.so] 
    
  • 您現在執行依賴於未版本控制libsomething.so。將可執行文件複製到兩臺機器上,並針對兩個副本運行ldd

    ldd executable 
    libsomething.so => /lib/libsomething.so (0xNNNNNNNN) 
    

    兩臺機器上的最後一個輸出結果與使用soname而不是版本的soname構建的可執行文件相同。這使得裝載器在目標機器上採用未版本化的符號鏈接。取決於機器,符號鏈接可以指向庫libsomething.so.1libsomething.so.2的不同實現。

+0

我沒有建立圖書館的問題,我認爲真正的答案是不做我的建議,如果你真的想作弊,只需使用符號鏈接。這提供了一些很好的信息,所以我接受。 – 2015-01-20 17:45:55

2

這意味着它將無法找到機器B.庫

而且它不應該反正。

根據soversions的定義,libsomething.so.2表示API/ABI與libsomething.so.1不兼容。因此,只需在要加載的程序庫的表格中添加libsomething.so即可,這實際上是錯誤的。 libsomething.so符號鏈接僅僅作爲ld提示默認選擇哪個soversion。

無論文件ld實際上以何種方式打開,都需要在程序中編碼DTNAME/SONAME字段。如果你不想這樣做,不要裝備libsomething與soname。但它可能很容易變成痛苦......開始嘗試運行程序時遇到不可用的符號。