A program would typically depend on other libraries to function. These libraries could either be compiled into the program itself or loaded from a pool of shared libraries.

The use of shared libraries reduces the program size and eases the development and distribution of the program. In Linux, shared libraries are stored in /lib* or /usr/lib*.

Different Linux distributions or even versions of the same distribution might package different libraries, making a program compiled for a particular distribution or version not correctly run on another. You will get the following error when the required library is not available in the system.

$ sudo dpkg sudo: error while loading shared libraries: libpthread.so.0:  cannot open shared object file: No such file or directory

You can check the shared libraries that a program depends on using ldd or other command-line tools to troubleshoot shared libraries loading issues.

Steps to find shared library dependency in Linux:

  1. Launch your preferred terminal application.
  2. Get absolute path of the program you want to check.

    $ which bash /usr/bin/bash

  3. Print shared object dependencies using ldd.

    $ ldd /usr/bin/bash 	linux-vdso.so.1 (0x00007ffdd2749000) 	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fcecb9b6100) 	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fcecb9b0000) 	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcecb7c5000) 	/lib64/ld-linux-x86-64.so.2 (0x00007fcecbb21000)

  4. Print verbose dependency info using ldd.

    $ ldd --verbose /usr/bin/bash 	linux-vdso.so.1 (0x00007ffce299c000) 	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f6fb24dd000) 	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f6fb24d6100) 	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6fb22ec000) 	/lib64/ld-linux-x86-64.so.2 (0x00007f6fb2648000)  	Version information: 	/usr/bin/bash: 		libdl.so.2 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libdl.so.2 		libtinfo.so.6 (NCURSES6_TINFO_5.0.19991023) => /lib/x86_64-linux-gnu/libtinfo.so.6 		libc.so.6 (GLIBC_2.11) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.8) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.15) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 	/lib/x86_64-linux-gnu/libtinfo.so.6: 		libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.16) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 	/lib/x86_64-linux-gnu/libdl.so.2: 		ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2 		libc.so.6 (GLIBC_PRIVATE) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 		libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 	/lib/x86_64-linux-gnu/libc.so.6: 		ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2 		ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2

    More options for ldd:

    $ ldd --help Usage: ldd [OPTION]... FILE...       --help              print this help and exit       --version           print version information and exit   -d, --data-relocs       process data relocations   -r, --function-relocs   process data and function relocations   -u, --unused            print unused direct dependencies   -v, --verbose           print all information  For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

  5. Find dynamic library required by program using readelf.

    $ readelf --dynamic /usr/bin/bash | grep NEEDED  0x0000000000000001 (NEEDED)             Shared library: [libtinfo.so.6]  0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]  0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

  6. Read library requirement of running processes from /proc/<process-id>/maps.

    $ awk '/\.so/{print $6}'  /proc/$(pgrep bash | head -n1)/maps | sort -u /usr/lib/x86_64-linux-gnu/ld-2.29.so /usr/lib/x86_64-linux-gnu/libc-2.29.so /usr/lib/x86_64-linux-gnu/libdl-2.29.so /usr/lib/x86_64-linux-gnu/libnss_files-2.29.so /usr/lib/x86_64-linux-gnu/libtinfo.so.6.1

  7. View shared library requirement of a running process using lsof.

    $ lsof -p $(pgrep bash | head -n1) | grep mem\ bash    4470 user  mem    REG    8,1    51672 404577 /usr/lib/x86_64-linux-gnu/libnss_files-2.29.so bash    4470 user  mem    REG    8,1 14529344 401393 /usr/lib/locale/locale-archive bash    4470 user  mem    REG    8,1  2000480 403822 /usr/lib/x86_64-linux-gnu/libc-2.29.so bash    4470 user  mem    REG    8,1    18656 403961 /usr/lib/x86_64-linux-gnu/libdl-2.29.so bash    4470 user  mem    REG    8,1   183528 404929 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.1 bash    4470 user  mem    REG    8,1    26402 789841 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache bash    4470 user  mem    REG    8,1   179032 403610 /usr/lib/x86_64-linux-gnu/ld-2.29.so

    pgrep bash | head -n1 gets the ID of the first process named bash

  8. Use pmap to gather shared library requirement of a program.

    $ pmap $(pgrep bash | head -n1) | grep \.so | awk '{ print $4 }' | sort -u ld-2.29.so libc-2.29.so libdl-2.29.so libnss_files-2.29.so libtinfo.so.6.1