cannot load shared library which exist on the library search path - linux

I'm trying to execute nft , which was built from source , but it reports
$ nft
nft: error while loading shared libraries: libnftnl.so.4: cannot open shared object file: No such file or directory
I built libmnl,libnftnl,nftables from sources by runnning autogen.sh and then configuring with :
--prefix=/usr/local
these are the contents of /usr/local/lib :
$ ls -l /usr/local/lib/ | grep libnftnl
-rwxr-xr-x 1 root root 961 Mar 2 20:16 libnftnl.la
lrwxrwxrwx 1 root root 17 Mar 2 20:16 libnftnl.so -> libnftnl.so.4.0.0
lrwxrwxrwx 1 root root 17 Mar 2 20:16 libnftnl.so.4 -> libnftnl.so.4.0.0
-rwxr-xr-x 1 root root 913147 Mar 2 20:16 libnftnl.so.4.0.0
more information :
$ ldd $(which nft)
linux-vdso.so.1 => (0x00007ffd7afbf000)
libmnl.so.0 => /usr/lib/x86_64-linux-gnu/libmnl.so.0 (0x00007fc60181f000)
libnftnl.so.4 => not found
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007fc6015d8000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fc601364000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc600f9f000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fc600d75000)
/lib64/ld-linux-x86-64.so.2 (0x000055a0bd82d000)
and the contents of my ld.so.conf are :
$ cat /etc/ld.so.conf
/usr/lib/x86_64-linux-gnu/libfakeroot
# libc default configuration
/usr/local/lib
/usr/local/lib/
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/mesa-egl
/usr/lib/x86_64-linux-gnu/mesa
/usr/lib/i386-linux-gnu/mesa
# Legacy biarch compatibility support
/lib32
/usr/lib32
# Legacy biarch compatibility support
/libx32
/usr/libx32
But if I set LD_LIBRARY_PATH to '/usr/local/lib' :
$ export LD_LIBRARY_PATH=/usr/local/lib
$ ldd $(which nft)
linux-vdso.so.1 => (0x00007ffedf9b3000)
libmnl.so.0 => /usr/local/lib/libmnl.so.0 (0x00007fb58a033000)
libnftnl.so.4 => /usr/local/lib/libnftnl.so.4 (0x00007fb589e0b000)
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007fb589ba3000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fb58992f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb58956a000)
libmxml.so.1 => /usr/lib/libmxml.so.1 (0x00007fb58935b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb58913d000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fb588f14000)
/lib64/ld-linux-x86-64.so.2 (0x000055a827fb3000)
Can anybody help why it cannot find the library even if it exists in the search path ?

I forgot to run ldconfig , as pointed out by #Petesh . Problem got resolved after runnning ldconfig.

Related

How do I diagnose why a shared library is not found?

I am trying to run an app which is linked against libboost_system.so
$ ./app
app: error while loading shared libraries: libboost_system.so.1.63.0: cannot open shared object file: \
No such file or directory
If I run ldd on the app, it shows it can't find the library:
$ ldd ./app
linux-vdso.so.1 (0x00007ffdedb94000)
libboost_system.so.1.63.0 => not found
libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f19a1a7b000)
librt.so.1 => /lib64/librt.so.1 (0x00007f19a1a70000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f19a1a69000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f19a1879000)
libm.so.6 => /lib64/libm.so.6 (0x00007f19a1733000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f19a1716000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f19a16f4000)
libc.so.6 => /lib64/libc.so.6 (0x00007f19a152a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f19a1ae5000)
The library is present on my system:
$ locate libboost_system.so.1.63.0
/usr/local/lib/libboost_system.so.1.63.0
$ ls -la /usr/local/lib/libboost_system*
-rw-r--r--. 1 root root 47014 Jul 2 16:57 /usr/local/lib/libboost_system.a
lrwxrwxrwx. 1 root root 25 Jul 2 16:57 /usr/local/lib/libboost_system.so -> libboost_system.so.1.63.0
-rwxr-xr-x. 1 root root 19816 Jul 2 16:57 /usr/local/lib/libboost_system.so.1.63.0
ld is configured with /usr/local/lib:
$ ld --verbose | grep SEARCH_DIR | sed 's/; /\n/g'
SEARCH_DIR("=/usr/x86_64-redhat-linux/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/x86_64-redhat-linux/lib")
SEARCH_DIR("=/usr/local/lib") <----- here
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
I've also run ldconfig to refresh the cache, but that doesn't help.
I tried searching for RPATH or RUNPATH with readelf, neither are specified:
$ readelf -d ./app | grep -i path
< no results >
If I explicitly set LD_LIBARY_PATH then the library is found:
$ LD_LIBRARY_PATH=/usr/local/lib ldd ./app
linux-vdso.so.1 (0x00007fffa9a5d000)
libboost_system.so.1.63.0 => /usr/local/lib/libboost_system.so.1.63.0 (0x00007f5fff664000)
libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f5fff5fc000)
librt.so.1 => /lib64/librt.so.1 (0x00007f5fff5f1000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f5fff5ea000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f5fff3fa000)
libm.so.6 => /lib64/libm.so.6 (0x00007f5fff2b4000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f5fff297000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5fff275000)
libc.so.6 => /lib64/libc.so.6 (0x00007f5fff0ab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5fff66b000)
Why can't ld find libboost_system.so.1.63.0 without specifying LD_LIBRARY_PATH?
You are looking at the "wrong" linker. ld is the static linker and isn't what's used by at runtime to locate the shared libraries.
The dynamic linker, ld.so, is what locates shared libraries.
The dynamic linker does look at the LD_LIBRARY_PATH and that's why it works if you set it.
If you want to update the search locations for dynamic linker (and not want to set LD_LIBRARY_PATH), you can create a file in /etc/ld.so.conf.d/ and update /etc/ld.so.cache with ldconfig.
The diagnostic is activated by LD_DEBUG (cf. man ld.so):
LD_DEBUG=libs ./a.out
It shows the search paths that the loader tried: ($LD_LIBRARY_PATH, R[UN]PATH from the app or library's ELF, ld.so.cache).
Its output is a little long to copy here, but would look like this:
265: find library=libboost_system.so.1.63.0 [0]; searching
265: search path= [...] (LD_LIBRARY_PATH)
[trying many files...]
265: search path= [...] (RUNPATH from file ./app)
[still trying many files...]
265: search cache=/etc/ld.so.cache
[still trying many files...]
In your case, you'd probably have seen that /usr/local/lib was not in the cache. Depending on the distribution, it may look by default in /usr/local/lib/x86_64-linux-gnu or /usr/local/lib64 or none at all.

Newly built gcc not being used even after setting $PATH

My server has GCC4 and I need newer version, so I built GCC7.3.0 and added the path to the $PATH variable. After this, gcc -v and g++ -v points to the correct version:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/users/home/m/GCC-7.3.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/m/gccbuild/../srcdir/configure --prefix=/home/m/GCC-7.3.0 --enable-languages=c,c++,fortran,go --disable-multilib
Thread model: posix
gcc version 7.3.0 (GCC)
However, I tried compiling a simple hello.cc program and ldd a.out gives:
linux-vdso.so.1 => (0x00007ffe609bb000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fa0bff67000)
libm.so.6 => /lib64/libm.so.6 (0x00007fa0bfc65000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fa0bfa4f000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa0bf681000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa0c026e000)
From here, was expecting something like:
libstdc++.so.6 => /users/home/m/GCC-7.3.0/lib64/libstdc++.so.6 (0x0000123456789000)
libgcc_s.so.1 => /users/home/m/GCC-7.3.0/lib64/libgcc_s.so.1 (0x0000123456ABC000)
Also, cat /proc/version gives:
Linux version 3.10.0-1127.el7.x86_64 (mockbuild#kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Mar 31 23:36:51 UTC 2020
EDIT:
Output to grep configure config.status within gcc build directory:
# Generated by configure.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
configured by /home/s18002/gccbuild/../srcdir/configure, generated by GNU Autoconf 2.64,
ac_configure_extra_args=
ac_configure_extra_args="$ac_configure_extra_args --silent"
set X '/bin/sh' '/home/s18002/gccbuild/../srcdir/configure' '--prefix=/home/m/GCC-7.3.0' '--disable-multilib' '--enable-languages=c,c++,fortran,go,lto' $ac_configure_extra_args --no-create --no-recursion
"L) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/li"\
S["extra_host_zlib_configure_flags"]=""
S["extra_host_libiberty_configure_flags"]="--enable-shared"
S["extra_linker_plugin_configure_flags"]=""
S["extra_isl_gmp_configure_flags"]="--with-gmp- builddir=$$r/$(HOST_SUBDIR)/gmp"
S["extra_mpc_mpfr_configure_flags"]="--with-mpfr-include=$$s/mpfr/src --with-mpfr-lib=$$r/$(HOST_SUBDIR)/mpfr/src/.libs"
S["extra_mpc_gmp_configure_flags"]="--with-gmp-include=$$r/$(HOST_SUBDIR)/gmp --with-gmp-lib=$$r/$(HOST_SUBDIR)/gmp/.libs"
S["extra_mpfr_configure_flags"]="--with-gmp-include=$$r/$(HOST_SUBDIR)/gmp --with-gmp-lib=$$r/$(HOST_SUBDIR)/gmp/.libs"
S["extra_liboffloadmic_configure_flags"]=""
S["TOPLEVEL_CONFIGURE_ARGUMENTS"]="/home/s18002/gccbuild/../srcdir/configure --prefix=/home/s18002/GCC-7.3.0 --enable-languages=c,c++,fortran,go --disable-multilib"
# Let's still pretend it is `configure' which instantiates (i.e., don't
configure_input='Generated from '`
`' by configure.'
configure_input="$ac_file. $configure_input"
case $configure_input in #(
ac_sed_conf_input=`$as_echo "$configure_input" |
*) ac_sed_conf_input=$configure_input;;
s|#configure_input#|$ac_sed_conf_input|;t t
The package I was trying to install got installed, which means it is using gcc7. How can I make sure GCC7 is used locally for all my purposes?
Make sure you are compiling with g++ and not gcc:
$ gcc test.c
$ ldd a.out
linux-vdso.so.1 => (0x00007ffcbdd71000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b23c32000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b24000000)
$ g++ test.c
$ ldd a.out
linux-vdso.so.1 => (0x00007ffedc577000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f745ed73000)
libm.so.6 => /lib64/libm.so.6 (0x00007f745ea71000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f745e85b000)
libc.so.6 => /lib64/libc.so.6 (0x00007f745e48d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f745f07a000)

Linking: Why does linker not honour symlink to library?

I have the following C program:
#include <stdio.h>
#include <zlib.h>
int main()
{
z_stream strm;
int integer = 0;
scanf("heloworld %d", &integer);
printf("ok\n");
if (integer == 10)
{
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, 0);
}
return 0;
}
This is a basic helloworld program which uses zlib.
If I search for the libz library, I can find it under /usr/lib/x86_64-linux-gnu/libz.so:
$ ls -lah libz.so
lrwxrwxrwx 1 root root 40 May 20 14:55 libz.so -> /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
and it is pointing to the real version of libz rather than the soname.
I compile it with the following command and check the dependencies:
$ gcc a.c -lz
$ ldd a.out
linux-vdso.so.1 (0x00007ffec44b6000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f6674055000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6673e63000)
/lib64/ld-linux-x86-64.so.2 (0x00007f667408c000)
How is it pointing to libz.so.1 instead of libz.so.1.2.11 (realname) since the symlink of libz.so.1 is pointing there? I am assuming that the linker is using the symlink however this is not the case.
Further to this, if I perform the following command:
$ objdump -p libz.so.1.2.11 | grep SONAME
SONAME libz.so.1
My question is, is it using the symlink name or the SONAME from the file the symlink provides?
If the linker put libz.so.1.2.11 in your executable, then it would break when you updated the library. Instead it puts the major version known to ldconfig in the executable, which is in turn a link to the current installed version.
See ldconfig http://man7.org/linux/man-pages/man8/ldconfig.8.html
I have discovered that under /lib/x86_64-linux-gnu there are two symlinks for libz.so which are:
libz.so
libz.so.1
When I compile, the linker uses the libz.so as a symlink to point to another .so file.
The .so file which libz.so is pointing to contains an SONAME entry which can be viewed as so:
$ objdump -p ./libz.so | grep SONAME
SONAME libz.so.1
Further I can see that the symlink points to libz.so.1.2.11
$ ls -alh libz.so
lrwxrwxrwx 1 root root 36 May 21 00:51 libz.so -> /lib/x86_64-linux-gnu/libz.so.1.2.11
If I edit the .dynstr section of that library like so:
$ sudo objcopy --dump-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
# Find the bytes for libz.so.1 and change them to libz.so.2
$ hexedit /tmp/dyn.dump
$ sudo objcopy --update-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
and then recompile my binary I notice:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Once I create a symlink of libz.so.2 under /lib/x86_64-linux-gnu/libz.so.2 to point to libz.so.1.2.11 I get the following output:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => /lib/x86_64-linux-gnu/libz.so.2 (0x00007f58bb7b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Therefore to answer my question it is not the symlink which adds an entry in the runtime dependencies of the executable but the SONAME entry in the shared object.

Why won't my compiled c++ binary execute?

So I have just compiled my code and when I try to execute the binary I am getting
-bash: ./a.out: No such file or directory
When I do ldd a.out I see everything is there that I need
ldd a.out
linux-vdso.so.1 (0x00007ffd337fb000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f1200930000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f1200728000)
libncurses.so.5 => /lib/x86_64-linux-gnu/libncurses.so.5 (0x00007f1200505000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f12002db000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f12000d7000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007f11ffed1000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007f11ffcb7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f11ff919000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f11ff6fa000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f11ff309000)
/usr/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f1200b4d000)
Also doing an ls -la shows the file as such
lrwxrwxrwx 1 user user 33 Jul 18 21:26 a.out
Does anyone have any reason why this isn't working?
I am using Ubuntu 18.04.2 LTS.
When I do ldd a.out I see everything is there that I need
No, there isn't.
ldd has been changed to run a known ELF interpreter / dynamic linker instead of the one from the binary's header. You can check that by yourself -- ldd is a shell script on your system.
ldd a.out
...
/usr/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2
And here it's the proof. Do you have a /usr/lib/ld-linux-x86-64.so.2 on your system?
A simpler testcase:
$ echo 'int main(){}' | cc -xc -
$ ./a.out
$ perl -pe 's/ld-linux/ld-LOOOL/' -i ./a.out
$ ./a.out
bash: ./a.out: No such file or directory
$ ldd ./a.out
linux-vdso.so.1 (0x00007ffd707e9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe936d52000)
/lib64/ld-LOOOL-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fe9372f3000)
As a quick-fix, you can pass the path to an existing interpreter when compiling your program
cc -Wl,-dynamic-linker,/lib64/ld-linux-x86-64.so.2 ...

How to add shared library search path to a executable file?

I build the ffmpeg with librtmp. My librtmp is at /opt/librtmp/lib. When I execute the ffmpeg, it said:
./ffmpeg: error while loading shared libraries: librtmp.so.0: cannot open shared object file: No such file or directory
I use ldd command it displays not found:
[qty#testing bin]# ldd ffmpeg
linux-vdso.so.1 => (0x00007fff15576000)
librtmp.so.0 => not found
libz.so.1 => /lib64/libz.so.1 (0x00002b9a71e10000)
libm.so.6 => /lib64/libm.so.6 (0x00002b9a72025000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002b9a722a8000)
libc.so.6 => /lib64/libc.so.6 (0x00002b9a724c3000)
/lib64/ld-linux-x86-64.so.2 (0x00002b9a71bf2000)
I know my so at:
[qty#testing bin]# ls -alh /opt/librtmp/lib/
total 300K
drwxr-xr-x 3 root root 4.0K Sep 25 17:10 .
drwxr-xr-x 7 root root 4.0K Sep 25 17:10 ..
-rw-r--r-- 1 root root 158K Sep 25 17:10 librtmp.a
lrwxrwxrwx 1 root root 12 Sep 25 17:10 librtmp.so -> librtmp.so.0
-rwxr-xr-x 1 root root 118K Sep 25 17:10 librtmp.so.0
drwxr-xr-x 2 root root 4.0K Sep 25 17:10 pkgconfig
I found several ways to fix the problem
modify /etc/ld.so.conf, but it required a supper user
set LD_LIBRARY_PATH variable, but it is not conventient to users
pass rpath to gcc, like this
configure args for my ffmpeg
PKG_CONFIG_PATH="/opt/librtmp/lib/pkgconfig" ./configure --disable-doc \
--disable-ffserver --disable-avdevice \
--disable-postproc --disable-avfilter --disable-bsfs \
--disable-filters \
--disable-asm \
--disable-bzlib \
--enable-librtmp \
--prefix=/opt/ffmpeg \
--extra-ldflags="-Wl,-rpath,/opt/librtmp/lib"
Assume there are no source code to re-compile? How do add the shared library search path to a executable file ?
I realize that OP has probably moved on but this is the kind of thing that NixOS does regularly and they have released a tool for this very problem. Also this was a problem I had before even hearing of NixOS.
Here's an example usage of their tool patchelf
...
Likewise, you can change the RPATH, the linker search path embedded into executables and dynamic libraries:
patchelf --set-rpath /opt/my-libs/lib:/foo/lib program
This causes the dynamic linker to search in /opt/my-libs/lib and /foo/lib for the shared libraries needed by program....
From https://nixos.org/patchelf.html
You could use addrpath to add an RPATH to your elf file.
The RPATH will work like LD_LIBRARY_PATH, that is, telling the dynamic loader to search for the shared libraries in that path. RPATH will be permanently in your ELF file.
nixos
this might be nixos specific but provides an interesting insight on ldd/patchelf:
https://lastlog.de/blog/posts/playing_FTL_on_NIXOS.html
ubuntu
on ubuntu/fedora you would use: LD_LIBRARY_PATH with a starter script ./ftl, again, see my above posting about FTL and how it is deployed.
My fix to this problem is to install librtmp into /usr/local/lib and run 'sudo ldconfig' after installing it.
Ffmpeg can then be configured simply by adding --enable-librtmp.
For me this works fine: No system modifications necessary!

Resources