Programs often rely on external libraries to function correctly. These libraries can either be compiled directly into the program or loaded from a shared library pool. Using shared libraries helps minimize program size and simplifies development and distribution. In Linux, shared libraries are usually stored in /lib* or /usr/lib* directories.

Different Linux distributions or even versions of the same distribution might utilize different libraries, causing a program compiled for one distribution or version to malfunction on another. When the required library is missing from the system, you may encounter an error.

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

To resolve shared library loading issues, you can use ldd or other command-line tools to determine the shared libraries a program depends on.

Steps to identify shared library dependency in Linux:

  1. Open your preferred terminal application.
  2. Determine the absolute path of the program you want to inspect.
    $ which bash
    /usr/bin/bash
  3. Use ldd to display the shared object dependencies.
    $ 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. Run ldd with verbose mode for more detailed dependency information.
    $ 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. Use readelf to find the dynamic libraries required by the program.
    $ 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. Examine library requirements of running processes by checking /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. Inspect shared library requirements of a running process using the lsof tool.
    $ 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 the shared library requirements 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.