Why a program can run with a dynamic library not found? - linker

After installing SAP HANA successfully, I can see the sapstartsrv process run:
# ps -ef | grep sapstartsrv
xn1adm 2143 1 0 Mar29 ? 00:00:05 /usr/sap/XN1/HDB00/exe/sapstartsrv pf=/home/hana/shared/XN1/profile/XN1_HDB00_dhe2 -D -u xn1adm
But after using ldd command to check sapstartsrv dynamic linking libraries:
# ldd /usr/sap/XN1/HDB00/exe/sapstartsrv
linux-vdso.so.1 (0x00007ffd35a30000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fd1fe6b3000)
librt.so.1 => /lib64/librt.so.1 (0x00007fd1fe4ab000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fd1fe270000)
libpam.so.0 => /lib64/libpam.so.0 (0x00007fd1fe061000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007fd1fde5e000)
libuuid.so.1 => /usr/lib64/libuuid.so.1 (0x00007fd1fdc59000)
libsapnwrfccm.so => not found
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fd1fd8d7000)
libm.so.6 => /lib64/libm.so.6 (0x00007fd1fd5d6000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fd1fd3bf000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd1fd1a2000)
libc.so.6 => /lib64/libc.so.6 (0x00007fd1fcdfb000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd1fe8b7000)
libaudit.so.1 => /usr/lib64/libaudit.so.1 (0x00007fd1fcbd8000)
I can see the libsapnwrfccm.so is not found. But why sapstartsrv program can run with a dynamic library not found?

Because something starts that program by pointing the linker to the directory containing that library. Usually this is done my setting the environment variable LD_LIBRARY_PATH. For example:
LD_LIBRARY_PATH=/look/here/for/libs program
The runtime linker will now also look in /look/here/for/libs to find libraries program depends on.

Related

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.

ODBC Driver not found "File not found error"

I am trying to connect to the database but getting error file not found, the same error is with isql. I know the file is there with correct permission.
$ isql -v ClickHouse
[01000][unixODBC][Driver Manager]Can't open lib '/usr/lib64/libclickhouseodbc.so' : file not found
[ISQL]ERROR: Could not SQLConnect
$ ls -lrt /usr/lib64/libclickhouseodbc.so
-rwxr-xr-x 1 root root 33920808 Mar 7 14:32 /usr/lib64/libclickhouseodbc.so
$ ldd /usr/lib64/libclickhouseodbc.so
linux-vdso.so.1 => (0x00007fffbf36d000)
libodbc.so.2 => /usr/lib64/libodbc.so.2 (0x00007f2366d2f000)
libm.so.6 => /usr/lib64/libm.so.6 (0x00007f2366a2c000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007f236665f000)
/lib64/ld-linux-x86-64.so.2 (0x0000558044ea1000)
libltdl.so.7 => /usr/lib64/libltdl.so.7 (0x00007f2366455000)
libdl.so.2 => /usr/lib64/libdl.so.2 (0x00007f2366250000)
libpthread.so.0 => /usr/lib64/libpthread.so.0 (0x00007f2366034000)
$ which isql | xargs file
/bin/isql: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=dacf3a0f9b65968e63f2ca5b0f79b522f5d7e567, stripped
$ which isql | xargs ldd
linux-vdso.so.1 => (0x00007ffd45fef000)
libodbc.so.2 => /usr/lib64/libodbc.so.2 (0x00007fe706ad3000)
libltdl.so.7 => /usr/lib64/libltdl.so.7 (0x00007fe7068c8000)
libreadline.so.6 => /usr/lib64/libreadline.so.6 (0x00007fe706682000)
libdl.so.2 => /usr/lib64/libdl.so.2 (0x00007fe70647e000)
libpthread.so.0 => /usr/lib64/libpthread.so.0 (0x00007fe706261000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007fe705e94000)
libtinfo.so.5 => /usr/lib64/libtinfo.so.5 (0x00007fe705c6a000)
/lib64/ld-linux-x86-64.so.2 (0x00005638f62f2000)
$ file /usr/lib64/libclickhouseodbc.so
/usr/lib64/libclickhouseodbc.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=aac633748dcbd6d9bf228372c6dbc524e751c4d0, not stripped

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.

Include version number when compiling shared objects

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.

How correct link program with libperl.so

How correct linking with libperl.so
I use Fedora Core 16 and try to compile program with embedding perl follows way:
gcc -W -Wall -g -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -I. -I/usr/include -I/usr/lib/include -I/usr/lib/perl5/CORE -c program.c
gcc -L/lib -L/usr/lib/perl5/CORE -lperl -o program.run program.o
After trying to run program I getting following message:
error while loading shared libraries: libperl.so: cannot open shared object file: No such file or directory
if execute following command 'ldd program.run' then it output to console
ldd ./program.run
linux-gate.so.1 => (0xb7751000)
libperl.so => not found
libc.so.6 => /lib/libc.so.6 (0x4eea5000)
/lib/ld-linux.so.2 (0x4ee80000)
Yes i can set LD_LIBRARY_PATH environment variable and program will be work, but if i execute same command for '/usr/bin/perl' library will be found without setting specific environment variable e.g
ldd `which perl`
linux-gate.so.1 => (0xb77f4000)
libperl.so => /usr/lib/perl5/CORE/libperl.so (0xb767b000)
libresolv.so.2 => /lib/libresolv.so.2 (0x4f22f000)
libnsl.so.1 => /lib/libnsl.so.1 (0x42eaf000)
libdl.so.2 => /lib/libdl.so.2 (0x4f055000)
libm.so.6 => /lib/libm.so.6 (0x4f085000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x41ee6000)
libutil.so.1 => /lib/libutil.so.1 (0x42ecc000)
libpthread.so.0 => /lib/libpthread.so.0 (0x4f05c000)
libc.so.6 => /lib/libc.so.6 (0x4eea5000)
/lib/ld-linux.so.2 (0x4ee80000)
libfreebl3.so => /lib/libfreebl3.so (0x42492000)
How correct link program with libperl.so
Adding -Wl,-rpath -Wl,/usr/lib/perl5/CORE (when linking) should help.
You need to set LD_LIBRARY_PATH at runtime for the dynamic linker to find libperl:
LD_LIBRARY_PATH=/usr/lib/perl5/CORE ./program

Resources