【发布时间】:2014-01-09 10:55:17
【问题描述】:
我正在尝试编译和链接一个与共享库(在本例中为 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 的值,其中包含@ 符号。
另一种可行的方法是简单地从二进制文件中删除符号版本信息(即从每个 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 没有那个符号)。
有没有办法解决这个问题?
【问题讨论】:
标签: linux linker libc binutils objcopy