Include version number when compiling shared objects - c

This is a more general question. I know windows DLL's can have a resource file set up with the dll version information, but I'm wondering how to do the same for linux shared objects.
The problem I'm encountering is actually when running just about anything at the terminal, I get a message about libz.so.1 version information not being available. This is due to an application being present with its own version of libz that I've compiled. The library is actually libz.so.1.2.3 and the same version exists in /lib. The files are actually the SAME version of the library, but one of them (which I compiled) says it's missing version information.
So, that leads me to wonder how to actually include the version information in the binary rather than just in the file name. It would be ideal if there's a solution like
./configure .... some_version_option=1.2.3
If I use the working version of the library:
ldd /usr/bin/git
linux-vdso.so.1 => (0x00007fffdfbff000)
libz.so.1 => /lib64/libz.so.1 (0x00007f3797fa7000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003c56000000)
libc.so.6 => /lib64/libc.so.6 (0x0000003c55c00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003c55400000)
If I use the version I compiled:
ldd /usr/bin/git
/usr/bin/git: libz.so.1: no version information available (required by /usr/bin/git)
linux-vdso.so.1 => (0x00007fff872b1000)
libz.so.1 (0x00007f83c9270000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003c56000000)
libc.so.6 => /lib64/libc.so.6 (0x0000003c55c00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003c55400000)

You need to pass the library's symbol version map file with -Wl,--version-script <file.map>. The map file should be included in the library source.

Related

Getting "cannot open shared object file" even though ldd shows it can find it

I looked for similar post on this topic but none the solutions work for me. I am trying to build a small program using openssl.
/mnt/sda1/openssl$ gcc tstsvr.c -I/mnt/sda1/openssl/include -L/mnt/sda1/openssl -lcrypto -lssl
When I try to run it:
$ sudo ./a.out
./a.out: error while loading shared libraries: libcrypto.so.81.1.1: cannot open shared object file: No such file or directory
But:
$ ldd a.out
linux-vdso.so.1 (0x00007fff23fe6000)
libcrypto.so.81.1.1 => /mnt/sda1/openssl/libcrypto.so.81.1.1 (0x00007f82f1db9000)
libssl.so.81.1.1 => /mnt/sda1/openssl/libssl.so.81.1.1 (0x00007f82f1d1e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f82f1b1a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f82f1b14000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f82f1af1000)
/lib64/ld-linux-x86-64.so.2 (0x00007f82f20ad000)
Format looks fine (inside /mnt/sda1/openssl):
$ file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=760dc5f7be4f51f598bab38a0b1eab1a42ef8a68, for GNU/Linux 3.2.0, not stripped
$ file libcrypto.so.81.1.1
libcrypto.so.81.1.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=404d1e7ed143383801efbb10ed7914f2cd0858d4, not stripped
$ ldd libcrypto.so.81.1.1
linux-vdso.so.1 (0x00007ffc44b5a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1083a8c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1083a69000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1083877000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1083d93000)
Just to make sure, I added path to LD_LIBRARY_PATH as well. Even ran sudo ldconfig. Neither made any difference.
What else can I try?
Per sudoers(5):
By default, the env_reset flag is enabled. This causes commands to be executed with a new, minimal environment.
...
Note that the dynamic linker on most operating systems will remove variables that can control dynamic linking from the environment of set-user-ID executables, including sudo. Depending on the operating system this may include RLD*, DYLD, LD_, LDR_*, LIBPATH, SHLIB_PATH, and others. These type of variables are removed from the environment before sudo even begins execution and, as such, it is not possible for sudo to preserve them.
Your easiest option is probably to do:
sudo LD_LIBRARY_PATH=/mnt/sda1/openssl ./a.out

How to link so that pthread_getattr_np will be resolved?

I'm using gcc to build a portable shared object. I'm applying the technique outlined in this answer to ensure that my binary will work on systems with older versions of glibc.
For the symbol pthread_getattr_np, I use
extern "C" {
__asm__(".symver pthread_getattr_np,pthread_getattr_np#GLIBC_2.2.5");
int __wrap_pthread_getattr_np(pthread_t thread, pthread_attr_t* attr) {
return pthread_getattr_np(thread, attr);
}
}
along with the option -Wl,--wrap=pthread_getattr_np to link to a specific portable version. However, pthread_getattr_np recently migrated from libpthread to libc for newer version of glibc. Even though the versioned symbol pthread_getattr_np#GLIBC_2.2.5 is the same, it's defined in a different library.
When I try to load my binary on an older system, I get the error
error: unable to load shared object
symbol pthread_getattr_np version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
If I run
objdump -T /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_getattr_np
0000000000009420 g DF .text 000000000000035e GLIBC_2.2.5 pthread_getattr_np
I see that the symbol is defined in libpthread.so; and if I run ldd on my binary, I see that libpthread is a dependency
linux-vdso.so.1 (0x00007ffec17fc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa3725cd000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa3723c9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa37202b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa371c3a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa3735dd000)
but the symbol won't resolve correctly.
Is there a way to set up the linking for my shared library so that pthread_getattr_np will resolve to either libpthread or libc depending on where it's defined?

version `libssl.so.10' not found

On Ubuntu 18.04 with apt install I installed libssl1.0.0 and libssl1.0-dev.
The following shared objects are available:
/usr/lib/x86_64-linux-gnu/libssl.so
/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
/usr/lib/x86_64-linux-gnu/libcrypto.so
Set the variable LD_LIBRARY_PATH with the previous path:
$ echo $LD_LIBRARY_PATH
/usr/lib/x86_64-linux-gnu
Created the following symbolic links:
ln -s /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 /usr/lib/x86_64-linux-gnu/libssl.so.10
ln -s /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /usr/lib/x86_64-linux-gnu/libcrypto.so.10
Now this is what I have:
$ file /usr/lib/x86_64-linux-gnu/libssl.so.10
/usr/lib/x86_64-linux-gnu/libssl.so.10: symbolic link to /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
$ ldd /usr/lib/x86_64-linux-gnu/libssl.so.10
linux-vdso.so.1 (0x00007ffeeaddb000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f28054fc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f280510b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2804f07000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2805ba7000)
$ file /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0d054641049b9747c05d030262295dfdfdd3055d, stripped
$ ldd /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
linux-vdso.so.1 (0x00007ffff3971000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f446f2b1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f446eec0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f446ecbc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f446f95c000)
So, at this point the dependencies for the library I will use are met.
When I try to validate that, I get issues such as version `libssl.so.10' not found.
$ file libpjsua2.so
libpjsua2.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=9481ccc9a0bbfe937ebb1dbc40002af55c2b424c, not stripped
$ ldd libpjsua2.so
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libssl.so.10: version `libssl.so.10' not found (required by ./libpjsua2.so)
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libcrypto.so.10: version `OPENSSL_1.0.1_EC' not found (required by ./libpjsua2.so)
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libcrypto.so.10: version `libcrypto.so.10' not found (required by ./libpjsua2.so)
linux-vdso.so.1 (0x00007ffc83691000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0d98395000)
libssl.so.10 => /usr/lib/x86_64-linux-gnu/libssl.so.10 (0x00007f0d9812d000)
libcrypto.so.10 => /usr/lib/x86_64-linux-gnu/libcrypto.so.10 (0x00007f0d97cea000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f0d97ae2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0d978c3000)
libasound.so.2 => /usr/lib/x86_64-linux-gnu/libasound.so.2 (0x00007f0d975bc000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0d9721e000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0d97006000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0d96c15000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0d98d91000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0d96a11000)
I would like to highlight that appears somehow it's able to resolve some .so:
libssl.so.10 => /usr/lib/x86_64-linux-gnu/libssl.so.10 (0x00007f0d9812d000)
libcrypto.so.10 => /usr/lib/x86_64-linux-gnu/libcrypto.so.10 (0x00007f0d97cea000)
There is a way for me to fix this? So libpjsua2.so is usable.
The shared library libpjsua2.so is designed for the version of OpenSSL shipped by Red Hat, CentOS, or Fedora, while you're trying to use a version built for Ubuntu. This won't work because the SONAME is different, as well as the symbol versioning.
There isn't any way to make this work, so you'll either need to use a shared library compiled for an Ubuntu (or Debian) system or run your program on the system the shared library was compiled for. Note that both Debian and Ubuntu ship a package called libpjsua2, so installing that may meet your needs.
You could theoretically copy the relevant OpenSSL version from the intended operating system, but doing so will likely involve a bunch of other broken shared libraries, and you will probably not be happy with the result.

How to set --rpath in configure script for openssl [duplicate]

This question already has answers here:
Build OpenSSL with RPATH?
(2 answers)
How to compile OpenSSL with relative rpath
(5 answers)
Closed 4 years ago.
I have different openssl versions on my system and I don't want to install the most current openssl version into the system location - e.q. /usr/bin/openssl.
Now, when I compile openssl then I get this running ldd:
root => ldd /FaF/openssl/bin/openssl
linux-vdso.so.1 (0x00007ffe60d92000)
--> libssl.so.1.1 => not found
--> libcrypto.so.1.1 => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007facf337b000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007facf315e000)
libc.so.6 => /lib64/libc.so.6 (0x00007facf2dbd000)
/lib64/ld-linux-x86-64.so.2 (0x00007facf357f000)
I refer to libssl.so.1.1 and libcrypto.so.1.1 which are not found and this is OK that far.
Running ldd with preceded LD_LIBRARY_PATH works:
root => LD_LIBRARY_PATH=/FaF/openssl/lib/ ldd /FaF/openssl/bin/openssl
linux-vdso.so.1 (0x00007fff221a1000)
libssl.so.1.1 => /FaF/openssl/lib/libssl.so.1.1 (0x00007f45f842a000)
libcrypto.so.1.1 => /FaF/openssl/lib/libcrypto.so.1.1 (0x00007f45f7f9a000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f45f7d96000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f45f7b79000)
libc.so.6 => /lib64/libc.so.6 (0x00007f45f77d8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f45f869b000)
/FaF/openssl/lib is the directory where the correct libraries are.
I have now these possible solutions:
Adding /FaF/openssl/lib to /etc/ld.so.conf and running ldconfig - This is not really an option because it may break the system version of openssl.
As I did in the above example I can precede each time I need opensslwith LD_LIBRARY_PATH=/FaF/openssl/lib/ - not really a good option and it isn't always possible.
I can link the path with --rpath=/FaF/openssl/lib into openssl.
My question:
For the moment I didn't figure out how to set --rpath=/FaF/openssl/lib in the configure command which generates openssl. Can somebody provide me this information?
I tried setting LD_LIBRARY_PATH and LDFLAGS but nothing works.
I prefer a solution which is hard-coded into openssl so there are not other settings required.
OK. Here is the - very simple - way how to solve it according to 3) from my question.
I ran ./config -h and got this output:
root => ./config -h
Usage: config [options]
-d Build with debugging when possible.
-t Test mode, do not run the Configure perl script.
-v Verbose mode, show the exact Configure call that is being made.
-h This help.
Any other text will be passed to the Configure perl script.
See INSTALL for instructions.
Operating system: x86_64-whatever-linux2
Configuring for linux-x86_64
The text Any other text will be passed to the Configure perl script. says it all.
I just added the --rpath at the end to the config command which looks now like this:
./config --prefix=/FaF/openssl threads shared -Wl,--rpath=/FaF/openssl/lib

Link against different glibc

I installed glibc-2.18 into my home directory and want to link an application against it:
$ g++ -pthread -o tsx_test tsx_test.cpp -Wl,--rpath=/home/hl/lib/ \
-Wl,--dynamic-linker=/home/hl/lib/ld-linux-x86-64.so.2
Compiling and linking works fine using g++4.7.3, however, fails when executing it:
$ ./tsx_test
./tsx_test: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
/usr/lib/x86_64-linux-gnu/libstdc++.so.6 definitely exists, when I compile without "--rpath" the same libstdc++.so.6 is linked and everything works fine.
$ ldd tsx_test
linux-vdso.so.1 => (0x00007fff42bd4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f42aa3aa000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f42aa194000)
libpthread.so.0 => /home/hl/lib/libpthread.so.0 (0x00007f42a9f75000)
libc.so.6 => /home/hl/lib/libc.so.6 (0x00007f42a9bc8000)
libm.so.6 => /home/hl/lib/libm.so.6 (0x00007f42a98c5000)
/home/hl/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f42aa6c9000)
/usr/lib/x86_64-linux-gnu/libstdc++.so.6 definitely exists
... but your libc doesn't look there.
You can set your RPATH like so: -Wl,-rpath=/home/hl/lib:/usr/lib, or you can edit /home/hl/etc/ld.so.conf and tell your libc to look in /usr/lib (after /home/hl/lib).j
Is it a permission problem, can't I mix root owned and user owned libs?
No. You can definitely mix and match root-owned and user-owned libraries.

Resources