我正在尝试编译和链接与共享库(在本例中为 libcryto 和 libssl,但实际库不相关)链接的程序(我们称之为 myprog)。我在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
@
另一种可行的方法是简单地从二进制文件中删除符号版本信息(即libssl.so.10
从每个 ssl 符号中删除版本,并依赖DT_NEEDED
名称中的版本信息)。这似乎是一个简单的请求,但我也不知道该怎么做。有objcopy
什么咒语吗?
更糟糕的是,在 Centos 上构建一个可以在 CloudLinux 上运行的(单独的)版本就可以了。我尝试这样做:
#define OSLB(SYMNAME) __asm__(".symver " #SYMNAME "," #SYMNAME "@Base");
OSLB (SSL_new);
但是,在链接抱怨SSL_new@Base
是未定义符号时失败(在 Centos 上它是,因为 Centos.so
没有该符号)。
有没有办法解决这个问题?