我試圖編譯和鏈接一個程序(我們稱之爲myprog),它與共享庫鏈接(在這種情況下,libcryto & libssl,但實際的庫不是相關)。我正在將其構建在Centos 5.5上,但希望使用相同的二進制文件運行在類似發行版(例如CloudLinux)的其他RHEL上。兩個版本都具有相同的庫(SO_NAME
)(即DT_NEEDED
版本對應)。重寫共享庫undef symbol編譯對象的版本
我的問題是這樣的。當我編譯在CentOS我看到:
centos$ objdump -T myprog | fgrep SSL_new
0000000000000000 DF *UND* 0000000000000000 libssl.so.10 SSL_new
的正常工作,因爲:
centos$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000000000447d0 g DF .text 0000000000000390 libssl.so.10 SSL_new
然而,在CloudLinux:
cloudlinux$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000033a623a120 g DF .text 0000000000000390 Base SSL_new
注意SSL符號的版本已經從libssl.so.10
改變到Base
。
這意味着,當我運行的二進制我得到:
cloudlinux$ ./myprog
./myprog: /usr/lib64/libcrypto.so.10: no version information available (required by ./myprog)
./myprog: /usr/lib64/libssl.so.10: no version information available (required by ./myprog)
我理解,這是「只是一個警告」,但我想擺脫它。
我想要的是我的二進制文件在cloudlinux和centos上運行,沒有警告。據我所知,openssl庫的ABI至少在我使用的位中是相同的。現在我無法更改共享庫,因爲myprog
可以在任何cloudlinux或centos庫上運行。我會接受一個解決方案,它在安裝時確定符號(以某種方式),例如與objcopy
。
一種方法就像是爲[email protected]
引入弱符號,這是[email protected]
的別名。顯然,這將是每個單一的符號在ssl庫(所以包裝不適合)。但我不能讓-Wl,--defsym=x=y
的x
採取的價值觀和y
與@
符號英寸
另一種做法可能的工作無非是從二進制中刪除符號版本信息(即從每個SSL的去除libssl.so.10
版本符號,並依靠DT_NEEDED
名稱中的版本)。這似乎是一個簡單的請求,但我看不出如何去做。有一些objcopy
咒語嗎?
更糟糕的情況是,在Centos上構建一個可以在CloudLinux上工作的(單獨的)版本可以。我試着這樣做:
#define OSLB(SYMNAME) __asm__(".symver " #SYMNAME "," #SYMNAME "@Base");
OSLB (SSL_new);
然而,失敗的鏈接抱怨[email protected]
是一個未定義的符號(這是在CentOS,因爲CentOS的.so
不具有符號)。
有沒有辦法解決這個問題?
這似乎是前進的方向。我必須通過一個.o文件建立共享庫,才能使其工作:'gcc -c -Wall -Werror -fPIC -o dummy.o dummy.c && gcc -shared -o dummy.so -Wl, - soname ='libssl.so.1.0.0'dummy.o && gcc -o objtest objtest.c -l:./ dummy.so'。這種方法的優點是:(a)生成的二進制文件可以在任何地方生成未版本化的符號;(b)不需要擔心函數原型;(c)C文件dummy.c可以自動生成從.so文件的objdump -T小Perl。 – abligh
@abligh「我必須通過一個.o文件構建共享庫,才能使其工作」 - 它*應該*在沒有分割編譯/鏈接步驟的情況下工作。我很好奇爲什麼它沒有。 –
不知道,但objdump產生的結果'不是一個動態二進制'或一些類似的錯誤。 – abligh