52

I want to find out the list of dynamic libraries a binary loads when run (With their full paths). I am using CentOS 6.0. How to do this?

migrated from serverfault.com Mar 17 '14 at 1:57

This question came from our site for system and network administrators.

56

You can do this with ldd command:

NAME
       ldd - print shared library dependencies

SYNOPSIS
       ldd [OPTION]...  FILE...

DESCRIPTION
       ldd  prints  the  shared  libraries  required by each program or shared
       library specified on the command line.
....

Example:

$ ldd /bin/ls
    linux-vdso.so.1 =>  (0x00007fff87ffe000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007ff0510c1000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff050eb9000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007ff050cb0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff0508f0000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff0506ec000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff0512f7000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff0504ce000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007ff0502c9000)
  • 1
    Any idea of what would be a macOS equivalent of this? No lld on darwin, it appears, nor can I find it via homebrew. – mz2 Oct 23 '16 at 14:05
  • 6
    On macOS: otool -L <path-to-binary> – Richard Viney Mar 17 '17 at 22:23
37

readelf -d $executable | grep 'NEEDED'

Can be used if you can't run the executable, e.g. if it was cross compiled, or if you don't trust it:

In the usual case, ldd invokes the standard dynamic linker (see ld.so(8)) with the LD_TRACE_LOADED_OBJECTS environment variable set to 1, which causes the linker to display the library dependencies. Be aware, however, that in some circumstances, some versions of ldd may attempt to obtain the dependency information by directly executing the program. Thus, you should never employ ldd on an untrusted executable, since this may result in the execution of arbitrary code.

Example:

readelf -d /bin/ls | grep 'NEEDED'

Sample ouptut:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Note that libraries can depend on other libraries, so now you need to find the dependencies.

A naive approach that often works is:

$ locate libselinux.so.1
/lib/i386-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libselinux.so.1
/mnt/debootstrap/lib/x86_64-linux-gnu/libselinux.so.1

but the more precise method is to understand the ldd search path / cache. I think ldconfig is the way to go.

Choose one, and repeat:

readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'

Sample output:

0x0000000000000001 (NEEDED)             Shared library: [libpcre.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

And so on.

See also:

/proc/<pid>/maps for running processes

Mentioned by Basile, this is useful to find all the libraries currently being used by running executables. E.g.:

sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u

shows all currently loaded dynamic dependencies of init (PID 1):

/lib/x86_64-linux-gnu/ld-2.23.so
/lib/x86_64-linux-gnu/libapparmor.so.1.4.0
/lib/x86_64-linux-gnu/libaudit.so.1.0.0
/lib/x86_64-linux-gnu/libblkid.so.1.1.0
/lib/x86_64-linux-gnu/libc-2.23.so
/lib/x86_64-linux-gnu/libcap.so.2.24
/lib/x86_64-linux-gnu/libdl-2.23.so
/lib/x86_64-linux-gnu/libkmod.so.2.3.0
/lib/x86_64-linux-gnu/libmount.so.1.1.0
/lib/x86_64-linux-gnu/libpam.so.0.83.1
/lib/x86_64-linux-gnu/libpcre.so.3.13.2
/lib/x86_64-linux-gnu/libpthread-2.23.so
/lib/x86_64-linux-gnu/librt-2.23.so
/lib/x86_64-linux-gnu/libseccomp.so.2.2.3
/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libuuid.so.1.3.0

This method also shows libraries opened with dlopen, tested with this minimal setup hacked up with a sleep(1000) on Ubuntu 18.04.

See also: How to see the currently loaded shared objects in Linux? | Super User

11

ldd and lsof show the libraries loaded either directly or at a given moment. They do not account for libraries loaded via dlopen (or discarded by dlclose). You can get a better picture of this using strace, e.g.,

strace -e trace=open myprogram

(since dlopen ultimately calls open - though you may of course have a system using different names for 64-bit opens...).

Example:

strace -e trace=open date

shows me this:

open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
open("/etc/localtime", O_RDONLY)        = 3
Wed Apr 12 04:56:32 EDT 2017

from which one could grep the ".so" names to just see shared objects.

6

lsof also can show you which libraries are being used for one particular process.

i.e.

$ pidof nginx
6920 6919

$ lsof -p 6919|grep mem
nginx   6919 root  mem    REG               0,64    65960     43 /lib64/libnss_files-2.12.so
nginx   6919 root  mem    REG               0,64    19536     36 /lib64/libdl-2.12.so
nginx   6919 root  mem    REG               0,64    10312   1875 /lib64/libfreebl3.so
nginx   6919 root  mem    REG               0,64  1923352     38 /lib64/libc-2.12.so
nginx   6919 root  mem    REG               0,64    88600   1034 /lib64/libz.so.1.2.3
nginx   6919 root  mem    REG               0,64  1967392   1927 /usr/lib64/libcrypto.so.1.0.1e
nginx   6919 root  mem    REG               0,64   183080   1898 /lib64/libpcre.so.0.0.1
nginx   6919 root  mem    REG               0,64    40400   1217 /lib64/libcrypt-2.12.so
nginx   6919 root  mem    REG               0,64   142688     77 /lib64/libpthread-2.12.so
nginx   6919 root  mem    REG               0,64   154664     31 /lib64/ld-2.12.so
2

For a process of pid 1234, you could also read the /proc/1234/maps (textual) pseudo-file (read proc(5)...) or use pmap(1)

This gives the virtual address space of that process, hence the files (including shared libraries, even dlopen(3)-ed one) which are memory mapped

(of course, use ps aux or pgrep(1) to find the processes running some given program)

1

For mass query:

  1. create a small script (useslib) and put in in the PATH (orspecify a full path in the command below)

    #! /bin/bash
    ldd $1 | grep -q $2
    exit $?
    
  2. Use it in a find command, for instance:

    find /usr/bin/ -executable -type f -exec useslib {} libgtk-x11-2.0 \; -print
    

(libgtk-x11-2.0 seems to be the gtk2 lib)

0

It is possible use 'pmap'.

For example, start a process: $ watch date

Get pid: $ ps -ef | grep watch

Show memory map: $ pmap <pid>

Show with full path: $ pmap <pid> -p

$ pmap 72770 72770: watch date 00005613a32c9000 20K r-x-- watch 00005613a34cd000 4K r---- watch 00005613a34ce000 4K rw--- watch 00005613a4f6a000 264K rw--- [ anon ] 00007f2f3a7d5000 204616K r---- locale-archive 00007f2f46fa7000 1748K r-x-- libc-2.27.so 00007f2f4715c000 2048K ----- libc-2.27.so 00007f2f4735c000 16K r---- libc-2.27.so 00007f2f47360000 8K rw--- libc-2.27.so 00007f2f47362000 16K rw--- [ anon ] 00007f2f47366000 12K r-x-- libdl-2.27.so 00007f2f47369000 2044K ----- libdl-2.27.so 00007f2f47568000 4K r---- libdl-2.27.so 00007f2f47569000 4K rw--- libdl-2.27.so 00007f2f4756a000 160K r-x-- libtinfo.so.6.1 00007f2f47592000 2048K ----- libtinfo.so.6.1 00007f2f47792000 16K r---- libtinfo.so.6.1 00007f2f47796000 4K rw--- libtinfo.so.6.1 00007f2f47797000 232K r-x-- libncursesw.so.6.1 00007f2f477d1000 2048K ----- libncursesw.so.6.1 00007f2f479d1000 4K r---- libncursesw.so.6.1 00007f2f479d2000 4K rw--- libncursesw.so.6.1 00007f2f479d3000 148K r-x-- ld-2.27.so 00007f2f47bdb000 20K rw--- [ anon ] 00007f2f47bf1000 28K r--s- gconv-modules.cache 00007f2f47bf8000 4K r---- ld-2.27.so 00007f2f47bf9000 4K rw--- ld-2.27.so 00007f2f47bfa000 4K rw--- [ anon ] 00007ffd39404000 136K rw--- [ stack ] 00007ffd3959b000 12K r---- [ anon ] 00007ffd3959e000 8K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 215692K $ pmap 72770 -p 72770: watch date 00005613a32c9000 20K r-x-- /usr/bin/watch 00005613a34cd000 4K r---- /usr/bin/watch 00005613a34ce000 4K rw--- /usr/bin/watch 00005613a4f6a000 264K rw--- [ anon ] 00007f2f3a7d5000 204616K r---- /usr/lib/locale/locale-archive 00007f2f46fa7000 1748K r-x-- /usr/lib64/libc-2.27.so 00007f2f4715c000 2048K ----- /usr/lib64/libc-2.27.so 00007f2f4735c000 16K r---- /usr/lib64/libc-2.27.so 00007f2f47360000 8K rw--- /usr/lib64/libc-2.27.so 00007f2f47362000 16K rw--- [ anon ] 00007f2f47366000 12K r-x-- /usr/lib64/libdl-2.27.so 00007f2f47369000 2044K ----- /usr/lib64/libdl-2.27.so 00007f2f47568000 4K r---- /usr/lib64/libdl-2.27.so 00007f2f47569000 4K rw--- /usr/lib64/libdl-2.27.so 00007f2f4756a000 160K r-x-- /usr/lib64/libtinfo.so.6.1 00007f2f47592000 2048K ----- /usr/lib64/libtinfo.so.6.1 00007f2f47792000 16K r---- /usr/lib64/libtinfo.so.6.1 00007f2f47796000 4K rw--- /usr/lib64/libtinfo.so.6.1 00007f2f47797000 232K r-x-- /usr/lib64/libncursesw.so.6.1 00007f2f477d1000 2048K ----- /usr/lib64/libncursesw.so.6.1 00007f2f479d1000 4K r---- /usr/lib64/libncursesw.so.6.1 00007f2f479d2000 4K rw--- /usr/lib64/libncursesw.so.6.1 00007f2f479d3000 148K r-x-- /usr/lib64/ld-2.27.so 00007f2f47bdb000 20K rw--- [ anon ] 00007f2f47bf1000 28K r--s- /usr/lib64/gconv/gconv-modules.cache 00007f2f47bf8000 4K r---- /usr/lib64/ld-2.27.so 00007f2f47bf9000 4K rw--- /usr/lib64/ld-2.27.so 00007f2f47bfa000 4K rw--- [ anon ] 00007ffd39404000 136K rw--- [ stack ] 00007ffd3959b000 12K r---- [ anon ] 00007ffd3959e000 8K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 215692K

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy