I am trying to compile and link a program (let's call it myprog) which is linked against a shared library (in this instance libcryto & libssl, but the actual library is not relevant). I am building it on Centos 5.5 but want the same binary to run on other RHEL-like distributions (e.g. CloudLinux). Both have versions of the same library with the same SO_NAME
(i.e. DT_NEEDED
versions correspond).
My issue is this. When I compile on Centos I see:
centos$ objdump -T myprog | fgrep SSL_new
0000000000000000 DF *UND* 0000000000000000 libssl.so.10 SSL_new
which works fine because:
centos$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000000000447d0 g DF .text 0000000000000390 libssl.so.10 SSL_new
However, on CloudLinux:
cloudlinux$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000033a623a120 g DF .text 0000000000000390 Base SSL_new
Note the version of the SSL symbol has changed from libssl.so.10
to Base
.
This means when I run the binary I get:
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)
I understand this is 'just a warning', but I want to get rid of it.
What I want is for my binary to run on both cloudlinux and centos without warnings. The ABI of the openssl libraries are, as far as I can tell, identical at least in the bits I use. Now I can't change the shared libraries as myprog
is meant to run on any cloudlinux or centos libraries. I would accept a solution which at install time fixed up the symbols (somehow), e.g. with objcopy
.
One approach would be something like introduce a weak symbol for [email protected]
which is an alias for SSL_new@Base
. Obviously that would be for every single symbol in the ssl library (so wrappers are not appropriate). But I can't get -Wl,--defsym=x=y
to take values of x
and y
with @
symbols in.
Another approach that might work is simply to remove the symbol versioning information from the binary (i.e. remove the libssl.so.10
version from each of the ssl symbols, and rely on the versioning within the DT_NEEDED
name). This would seem to be a simple request, but I can't see how to do it either. Is there some objcopy
incantation?
Worse case, building on Centos a (separate) version that would work on CloudLinux would be fine. I tried by doing this:
#define OSLB(SYMNAME) __asm__(".symver " #SYMNAME "," #SYMNAME "@Base");
OSLB (SSL_new);
However, that fails on link complaining that SSL_new@Base
is an undefined symbol (which it is, on Centos, as the Centos .so
does not have that symbol).
Is there some way around this?
Removing version info post-link is infeasible -- these strings are entered into hash tables, and rebuilding these hash tables is too complicated a thing to do with
objcopy
.What you want to do is create a stub
libssl.so.10
withDT_SONAME
set tolibssl.so.10
, which defines all the symbols you need from it, but without any version info. For example, this would do if you only needed theSSL_new
symbol:Now link your program against this stub library, and it will not require any versioned symbols.
The runtime linker will then satisfy this undefined unversioned
SSL_new
with[email protected]
on CentOS, and withSSL_new@Base
on CloudLinux.