Shared libraries are central to how applications run on Linux, and checking their dependencies helps diagnose startup failures and subtle runtime bugs. When a required .so file is missing or mismatched, an otherwise valid binary can refuse to start with errors about loading shared libraries.
Most dynamically linked ELF binaries list their required libraries in their metadata, and the dynamic loader (commonly /lib64/ld-linux-x86-64.so.2) locates those libraries in search paths such as /lib, /usr/lib, and any locations derived from rpath, runpath, or environment variables. Tools like ldd, readelf, and process-introspection commands expose this information directly from the binary or from a running process.
Commands shown here target typical Linux systems using the standard glibc runtime and work for both executables and shared objects. Output formats and library paths vary between distributions and architectures, and running ldd on untrusted binaries can be unsafe because it may execute code as part of the loading process. Before changing or installing libraries based on this information, backups and change control help avoid breaking other applications that rely on the same .so files.
A typical failure caused by a missing shared library resembles the following example when a command tries to load an absent .so file.
$ sudo dpkg sudo: error while loading shared libraries: libpthread.so.0: cannot open shared object file: No such file or directory
Steps to check library dependencies in Linux:
- Open the terminal application.
- Determine the absolute path of the program being inspected.
$ which bash /usr/bin/bash
- Display the shared object dependencies of the program using ldd.
$ ldd /usr/bin/bash linux-vdso.so.1 (0x0000ffff8c75c000) libtinfo.so.6 => /lib/aarch64-linux-gnu/libtinfo.so.6 (0x0000ffff8c530000) libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff8c370000) /lib/ld-linux-aarch64.so.1 (0x0000ffff8c720000)
The ldd command shows all shared libraries required by a program and the resolved path to each .so file.
Running ldd on untrusted executables can be unsafe because it may cause code execution through crafted runtime loaders or environment settings.
- Run ldd in verbose mode to view version references and dependency details.
$ ldd --verbose /usr/bin/bash linux-vdso.so.1 (0x0000ffff82bcc000) libtinfo.so.6 => /lib/aarch64-linux-gnu/libtinfo.so.6 (0x0000ffff82990000) libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff827d0000) /lib/ld-linux-aarch64.so.1 (0x0000ffff82b80000) Version information: /usr/bin/bash: ld-linux-aarch64.so.1 (GLIBC_2.17) => /lib/ld-linux-aarch64.so.1 libtinfo.so.6 (NCURSES6_TINFO_5.0.19991023) => /lib/aarch64-linux-gnu/libtinfo.so.6 libc.so.6 (GLIBC_2.25) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.38) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.33) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.36) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.34) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.17) => /lib/aarch64-linux-gnu/libc.so.6 /lib/aarch64-linux-gnu/libtinfo.so.6: ld-linux-aarch64.so.1 (GLIBC_2.17) => /lib/ld-linux-aarch64.so.1 libc.so.6 (GLIBC_2.33) => /lib/aarch64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.17) => /lib/aarch64-linux-gnu/libc.so.6 /lib/aarch64-linux-gnu/libc.so.6: ld-linux-aarch64.so.1 (GLIBC_PRIVATE) => /lib/ld-linux-aarch64.so.1 ld-linux-aarch64.so.1 (GLIBC_2.17) => /lib/ld-linux-aarch64.so.1 ##### snipped #####
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>. - Use readelf to inspect dynamic section entries and list required shared libraries without executing the program.
$ readelf --dynamic /usr/bin/bash | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libtinfo.so.6] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
The NEEDED entries show the .so names recorded in the binary, independent of how the dynamic loader resolves them on the system.
- Inspect libraries required by a running process using the /proc filesystem memory maps.
$ awk '/\.so/{print $6}' /proc/$(pgrep bash | head -n1)/maps | sort -u /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 /usr/lib/aarch64-linux-gnu/libc.so.6 /usr/lib/aarch64-linux-gnu/libtinfo.so.6.4 - List memory-mapped shared libraries of a running process using lsof.
$ lsof -p $(pgrep bash | head -n1) | grep mem bash 4843 root mem REG 0,64 1722920 2102162 /usr/lib/aarch64-linux-gnu/libc.so.6 bash 4843 root mem REG 0,64 265416 2102264 /usr/lib/aarch64-linux-gnu/libtinfo.so.6.4 bash 4843 root mem REG 0,64 203968 2102142 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
pgrep bash | head -n1 selects the first matching process ID for bash and passes it to lsof.
- Use pmap to check the memory maps of a running process and summarise the loaded shared libraries.
$ pmap $(pgrep bash | head -n1) | tail -n +2 | grep \.so | awk '{ print $4 }' | sort -u ld-linux-aarch64.so.1 libc.so.6 libtinfo.so.6.4 - Re-run the original program after resolving missing dependencies to verify that no shared library error is reported.
$ sudo dpkg --help Usage: dpkg [<option>...] <command> Commands: -i|--install <.deb file name>... | -R|--recursive <directory>... --unpack <.deb file name>... | -R|--recursive <directory>... -A|--record-avail <.deb file name>... | -R|--recursive <directory>... --configure <package>... | -a|--pending ##### snipped #####
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
