2013-06-28 50 views
4
共享庫

平臺:Ubuntu的12.04LTS x86_64的
Python版本:2.7.3使用Python的ctypes與鏈接到非標準的共享庫

我有一個由供應商給我一個共享庫,並它包含了libcrypto.so.0.9.8和libssl.0.9.8,並附有註釋說明它不適用於這些庫的其他版本。

我們運行的Ubuntu版本(12.04LTS)使用libcrypto.so.1.0.0和libssl.so.1.0.0,我試圖對這些進行編譯,並確認它不起作用。

我繼續編寫我的C函數,並測試它是否針對給定的庫進行編譯,它的工作原理,一切都很開心,我得到了我期待的結果,等等等等。這裏是粘性的地方。當我將函數導入python並嘗試運行它時,似乎ld.so仍然試圖將它鏈接到libcrypto.so.1.0.0,而不是指定的庫。

我已將所有庫複製到/ etc /目錄(重命名爲post)以創建一個一致的位置,以便在其他服務器上實現這些位置時放置這些位置。

我與編譯:

gcc -fPIC -shared vendor_lib_test.c -o libmylib.so -lvendor_ssl 

aditional的gcc的選項我試過有:

-Wl,-rpath,/etc/directory,-rpath-link,/etc/directory #together, and each individually 
-Wl,-R,/etc/directory/libssl.so.0.9.8,-R,/etc/directory/libcrypto.so.0.9.8 #both with, and without the above 

我試圖運行10.04LTS,它使用0.9的舊服務器上運行的代碼。這兩個庫中的8個,並且它按預期工作,但它是我們擁有的最後一個10.04服務器,並且不會用於生產。

檢查,對LDD產生(編輯刪除敏感信息):

linux-vdso.so.1 => (0x00007fff39fe9000) 
libvendor_ssl.so => /etc/directory/liblpcapi_ssl.so (0x00007f3c7602b000) 
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3c75c64000) 
libssl.so.0.9.8 => /etc/directory/libssl.so.0.9.8 (0x00007f3c75b1c000) 
libcrypto.so.0.9.8 => /etc/directory/libcrypto.so.0.9.8 (0x00007f3c758ab000) 
/lib64/ld-linux-x86-64.so.2 (0x00007f3c76341000) 
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3c756a7000) 

所以它似乎被鏈接到正確的庫,但在運行python腳本生成分段錯誤,和gdb給了我們:

$ gdb python 
(gdb) run ./ptest.py 
Starting program: /usr/bin/python ./ptest.py 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff724dc68 in RSA_public_encrypt() from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 

所以它仍然試圖鏈接到1.0.0,我在我的頭撞牆在這裏。

編輯:export LD_LIBRARY_PATH =/etc /目錄也無法正常工作。

+1

用ctypes加載你的庫後,看看'os.system('pmap%d'% os.getpid())'來查看哪些版本被加載。還要檢查'realed-d libmylib.so'和'readelf -d libvendor_ssl.so'是否需要''NEEDED'版本和'RPATH'或'RUNPATH'值。 – eryksun

+0

感謝您的評論。 pmap顯示兩個庫加載的0.9.8,其次是1.0.0。 readelf在供應商庫上顯示0.9.8,沒有RPATH。 readelf顯示了我的庫上的RPATH庫路徑:[/ etc/directory] ​​ –

+0

似乎python自己加載了1.0.0。如果你只是簡單地導入os,然後打印os.system('pmap%d'%os.getpid()),它會顯示libcrypto.1.0.0已加載。解決方法的任何想法? –

回答

0

有一個未公開的gcc參數,它允許你設置共享庫的路徑:「-l:/usr/libname.so」。

如果你將完整的lib名稱傳給gcc,可能ld會做你想要的,你就可以運行選擇的庫版本,例如: gcc(...)-l:/ etc /目錄/ libssl.0.9.8 -l:/etc/directory/libcrypto.so.0.9.8