我正在尝试编译和链接一个程序(让我们称之为myprog),该程序链接到共享库(在本例中为 libcryto& libssl ,但实际的库不相关)。我正在 Centos 5.5 上构建它,但希望在其他 RHEL 类似的发行版(例如CloudLinux)上运行相同的二进制文件。两者都具有相同库的版本,具有相同的SO_NAME
(即DT_NEEDED
版本对应)。
我的问题是这个。当我在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
。
一种方法就是为SSL_new@libssl.so.10
引入弱符号,这是SSL_new@Base
的别名。显然,这将适用于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);
然而,在链接上失败,抱怨SSL_new@Base
是一个未定义的符号(在Centos上,因为Centos .so
没有该符号)。
有什么方法吗?
答案 0 :(得分:3)
另一种可行的方法是简单地从二进制文件中删除符号版本控制信息(即从每个ssl符号中删除libssl.so.10版本,并依赖于DT_NEEDED名称中的版本控制)。这似乎是一个简单的请求,但我也看不出如何做到这一点。是否有一些objcopy咒语?
删除版本信息后链接是不可行的 - 这些字符串被输入到哈希表中,重建这些哈希表与objcopy
过于复杂。
您要做的是创建一个存根 libssl.so.10
,DT_SONAME
设置为libssl.so.10
,它定义了您需要的所有符号,但< em>没有任何版本信息。例如,如果您只需要SSL_new
符号,则会执行此操作:
echo "void SSL_new() { }" > t.c &&
gcc -fPIC -shared -o libssl.so -Wl,--soname='libssl.so.10' t.c
现在将您的程序链接到此存根库,不需要任何版本化符号。
然后,运行时链接器将在CentOS上使用SSL_new
和在CloudLinux上使用SSL_new@libssl.so.10
来满足此未定义的无版本SSL_new@Base
。
答案 1 :(得分:1)
我能够以这种方式摆脱这些警告(使用Debian / Arch而不是CentOS / Cloud Linux,但它也适用于你):
删除所有libssl-devel包以避免混淆
从源代码编译libssl
./config --prefix=/usr/local --openssldir=/usr/local/openssl shared
针对该软件构建您的软件。
对我来说,这些版本引用随后消失了,并且在没有警告的情况下运行:
Version References:
required from libcrypto.so.1.0.0:
0x066a2b20 0x00 10 OPENSSL_1.0.0
required from libssl.so.1.0.0:
0x066a2b20 0x00 05 OPENSSL_1.0.0