How to show shared library dependency in Linux
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:
-
Launch your preferred terminal application.
-
Get absolute path of the program you want to check.
$ which bash /usr/bin/bash
-
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)
-
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>.
-
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]
-
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
-
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
-
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