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
Discuss the article:

Comment anonymously. Login not required.

Share!