Using the ldd command on Linux


Shared object files streamline programs by providing information applications need to do their jobs, but that don’t have to be part of the application itself. To find out which of these files a Linux command calls on, use the ldd command.

What is a shared object file?

Shared object files (designated as .so) are libraries that are automatically linked into a program when the program starts, yet exist as a standalone files. They contain information that can be used by one or more programs to offload resources so that any program calling a .so file doesn’t itself have to actually provide all the needed tools. These files can be linked to any program and be loaded anywhere in memory.

A single .so file might contain information and functions on how to quickly search through the whole computer or perform very complex calculations. Several programs can then call upon that .so file. In fact, .so files can be updated/replaced without those programs having to make any changes to their own code.

Shared libraries can be linked to any program at run-time. Think of them as chunks of code that can be used by many different programs, thus allowing those programs to be smaller and much more efficient than ensuring all the programs that use them contain them and get updated as needed if the code changes.

Using ldd

This simple example uses ldd to find out what files the date command uses:

$ ldd /usr/bin/date
        linux-vdso.so.1 (0x00007ffd230e5000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f8e9fc54000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8e9fe52000)

The result above shows that the date command uses three shared object files.

Note that you have to include a full pathname to the file when using ldd. Otherwise, ldd looks into the current directory for the program name and isn’t likely to find it.

$ ldd date
ldd: ./date: No such file or directory

If you’re not sure where a particular program is located, you can use the which command in either of the forms shown below.

$ which pwd
/usr/bin/pwd
$ ldd /usr/bin/pwd
        linux-vdso.so.1 (0x00007ffe9df9b000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f686d670000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f686d85d000)

or

$ ldd `which pwd`
        linux-vdso.so.1 (0x00007ffc3b9e4000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2d491a9000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2d49396000)

You can get a lot more information by using the -v (or –verbose) option:

$ ldd -v `which pwd`
        linux-vdso.so.1 (0x00007ffeea1f6000)
        libc.so.6 => /lib64/libc.so.6 (0x00007ff3b0c64000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff3b0e51000)

        Version information:
        /usr/bin/pwd:
                libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.33) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
                libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        /lib64/libc.so.6:
                ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2
                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

The ldd command is sometimes used when it appears that a needed shared library is missing, and instead a “not found” message is generated. For example:

                   libcsfml-graphics.so.2.2 => not found

If many or all of the needed libraries are missing, you might actually be missing a configuration file or symbolic link meant to make the connection. Missing shared object files are very uncommon, and you are unlikely to ever run into this problem.

Some programs use only a few shared libraries while others use a pile of them. Take a look at the reboot command and you will see a very long list of files like this:

$ ldd /usr/sbin/reboot
        linux-vdso.so.1 (0x00007ffd0b374000)
        libsystemd-shared-249.so => /usr/lib/systemd/libsystemd-shared-249.so (0x00007f30fbec3000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f30fbe9a000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f30fbc90000)
        libacl.so.1 => /lib64/libacl.so.1 (0x00007f30fbc85000)
        libblkid.so.1 => /lib64/libblkid.so.1 (0x00007f30fbc4d000)
        libcap.so.2 => /lib64/libcap.so.2 (0x00007f30fbc43000)
        libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007f30fbc07000)
        libgcrypt.so.20 => /lib64/libgcrypt.so.20 (0x00007f30fbacb000)
        libip4tc.so.2 => /lib64/libip4tc.so.2 (0x00007f30fbac1000)
        libkmod.so.2 => /lib64/libkmod.so.2 (0x00007f30fbaa6000)
        liblz4.so.1 => /lib64/liblz4.so.1 (0x00007f30fba82000)
        libmount.so.1 => /lib64/libmount.so.1 (0x00007f30fba3d000)
        libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f30fb74d000)
        libp11-kit.so.0 => /lib64/libp11-kit.so.0 (0x00007f30fb61b000)
        libpam.so.0 => /lib64/libpam.so.0 (0x00007f30fb609000)
        libseccomp.so.2 => /lib64/libseccomp.so.2 (0x00007f30fb5e8000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f30fb5bc000)
        libzstd.so.1 => /lib64/libzstd.so.1 (0x00007f30fb4c6000)
        liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f30fb498000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f30fc216000)
        libattr.so.1 => /lib64/libattr.so.1 (0x00007f30fb490000)
        libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f30fb46a000)
        libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f30fb41d000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f30fb403000)
        libffi.so.6 => /lib64/libffi.so.6 (0x00007f30fb3f6000)
        libaudit.so.1 => /lib64/libaudit.so.1 (0x00007f30fb3c8000)
        libeconf.so.0 => /lib64/libeconf.so.0 (0x00007f30fb3bd000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f30fb2e1000)
        libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f30fb24a000)
        libibverbs.so.1 => /lib64/libibverbs.so.1 (0x00007f30fb228000)
        libcap-ng.so.0 => /lib64/libcap-ng.so.0 (0x00007f30fb21d000)
        libnl-route-3.so.200 => /lib64/libnl-route-3.so.200 (0x00007f30fb197000)
        libnl-3.so.200 => /lib64/libnl-3.so.200 (0x00007f30fb173000)

Of course, what this output doesn’t tell you is how many programs use these shared libraries and how much trouble you would have if one of the more important ones was removed from your system. Even common commands could stop working.

Don’t be fooled. Likely every command that you enter on a Linux system is using shared libraries. Even as modest a command as echo uses several:

$ ldd /usr/bin/echo
        linux-vdso.so.1 (0x00007ffdbf99d000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0696277000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f069649c000)

The criticality of these files is quite obvious. Fortunately, it’s easy to appreciate them, but otherwise let them do their thing. There’s no way to peer into them or inquire about how they work. You can display some details like those shown below, but this doesn’t provide much insight the functions the files provide.

$ ls -l /lib64/libc.so.6
-rwxr-xr-x. 1 root root 2387984 Oct  1 14:19 /lib64/libc.so.6
$ file /lib64/libc.so.6
/lib64/libc.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux),
dynamically linked, interpreter lib64/ld-linux-x86-64.so.2, BuildID[sha1]=
f891252f9069edee265f92cfb9a163880999588b, for GNU/Linux 3.2.0, not stripped

Wrap-Up

Shared object files are an extremely important part of any Linux system as they allow programs to share resources that can be updated and loaded into memory separately. It’s easy to determine what shared object files any particular command uses, but virtually impossible to determine the roles that they are playing.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.

Copyright © 2022 IDG Communications, Inc.



Source link