Distinguish direct and indirect dependencies of a binary on Linux?
ldd
on Linux will give the list of all shared libraries on which a given binary depends. This is usually much more extensive than the libraries that were listed on the linker command line used to create the binary: it will include most if not all dependencies of those libraries.
Is it possible to determine just the list of libraries that were linked explicitly (i.e. the direct dependencies) and if so, how?
You can use readelf -d
to dump the "dynamic" section of the binary. This will include NEEDED libraries.
For example, comparing ldd
with readelf
on /bin/ls
:
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007fff190da000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f082f94e000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007f082f749000)
libacl.so.1 => /lib64/libacl.so.1 (0x00007f082f540000)
libc.so.6 => /lib64/libc.so.6 (0x00007f082f172000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f082ef10000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f082ed0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f082fb75000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007f082eb07000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f082e8eb000)
$ readelf -d /bin/ls | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
0x0000000000000001 (NEEDED) Shared library: [libcap.so.2]
0x0000000000000001 (NEEDED) Shared library: [libacl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
You can also do this on .so
files
$ readelf -d /lib64/libpcre.so.1 | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
If you plan to list direct dependencies recursively, use lddtree
from pax-utils:
$ lddtree /bin/file
/bin/file (interpreter => /lib64/ld-linux-x86-64.so.2)
libmagic.so.1 => /usr/lib/libmagic.so.1
libzstd.so.1 => /usr/lib/libzstd.so.1
liblzma.so.5 => /usr/lib/liblzma.so.5
libbz2.so.1.0 => /usr/lib/libbz2.so.1.0
libz.so.1 => /usr/lib/libz.so.1
libseccomp.so.2 => /usr/lib/libseccomp.so.2
libc.so.6 => /usr/lib/libc.so.6
(This internally uses python-pyelftools.)