1

我正在尝试编译和链接与共享库(在本例中为 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.10Base

这意味着当我运行二进制文件时,我得到:

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=yx和符号。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没有该符号)。

有没有办法解决这个问题?

4

2 回答 2

6

另一种可行的方法是简单地从二进制文件中删除符号版本信息(即从每个 ssl 符号中删除 libssl.so.10 版本,并依赖 DT_NEEDED 名称中的版本信息)。这似乎是一个简单的请求,但我也不知道该怎么做。有一些 objcopy 咒语吗?

删除链接后的版本信息是不可行的——这些字符串被输入到哈希表中,重建这些哈希表太复杂了objcopy

您要做的是创建一个设置为的存根 libssl.so.10,它定义了您需要的所有符号,但没有任何版本信息。例如,如果您只需要符号,则可以这样做:DT_SONAMElibssl.so.10SSL_new

 echo "void SSL_new() { }" > t.c &&
 gcc -fPIC -shared -o libssl.so -Wl,--soname='libssl.so.10' t.c

现在将您的程序链接到这个存根库,它不需要任何版本化符号。

然后,运行时链接器将在 CentOS 和CloudLinux 上满足这个未定义的 unversioned SSL_newwith 。SSL_new@libssl.so.10SSL_new@Base

于 2014-01-11T07:10:55.253 回答
1

我能够以这种方式摆脱这些警告(使用 Debian/Arch 而不是 CentOS/Cloud Linux,但它也应该对你有用):

  1. 删除任何 libssl-devel 包以避免混淆

  2. 从源代码编译 libssl

    ./config --prefix=/usr/local --openssldir=/usr/local/openssl shared

  3. 以此为基础构建您的软件。

对我来说,这些版本引用然后消失了,它在没有警告的情况下运行:

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
于 2014-01-09T16:22:06.213 回答