如何找出运行时加载的动态库可执行文件?

125 libraries executable dynamic-linking

我想找出运行时二进制加载的动态库列表(及其完整路径)。我正在使用 CentOS 6.0。这该怎么做?

cuo*_*glm 125

您可以使用以下ldd命令执行此操作:

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.
....
Run Code Online (Sandbox Code Playgroud)

例子:

$ 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)
Run Code Online (Sandbox Code Playgroud)

  • 在 macOS 上:`otool -L <path-to-binary>` (14认同)
  • 请注意,这可能会执行二进制文件。因此,如果二进制文件不受信任,最好不要使用 `ldd`。参见 [手册页](http://man7.org/linux/man-pages/man1/ldd.1.html)。 (4认同)
  • 遵循@PaulRooney 的评论:特别是,手册页建议使用`objdump -p /path/to/program | 如果您不信任可执行文件,请使用 grep NEEDED` 作为 ldd 的替代方案。 (3认同)
  • 知道什么是 macOS 等价物吗?似乎达尔文上没有“lld”,我也无法通过自制软件找到它。 (2认同)
  • 当您想要查看依赖关系的层次结构树(包括依赖关系的依赖关系)时,“pax-utils”中的“lddtree”会更好;普通的“ldd”仅显示直接依赖关系。 (2认同)

Cir*_*郝海东 85

readelf -d $executable | grep 'NEEDED'

如果您无法运行可执行文件(例如,如果它是交叉编译的,或者您不信任它),则可以使用:

在通常情况下,ldd 调用标准动态链接器(参见 ld.so(8))并将 LD_TRACE_LOADED_OBJECTS 环境变量设置为 1,这会导致链接器显示库依赖项。但是请注意,在某些情况下,某些版本的 ldd 可能会尝试通过直接执行程序来获取依赖项信息。因此,永远不要在不受信任的可执行文件上使用 ldd,因为这可能会导致执行任意代码。

例子:

readelf -d /bin/ls | grep 'NEEDED'
Run Code Online (Sandbox Code Playgroud)

样品输出:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
Run Code Online (Sandbox Code Playgroud)

请注意,库可以依赖于其他库,因此现在您需要找到依赖项。

通常有效的幼稚方法是:

$ 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
Run Code Online (Sandbox Code Playgroud)

但更精确的方法是了解ldd搜索路径/缓存。我认为ldconfig是要走的路。

选择一个,然后重复:

readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'
Run Code Online (Sandbox Code Playgroud)

示例输出:

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]
Run Code Online (Sandbox Code Playgroud)

等等。

也可以看看:

/proc/<pid>/maps 用于运行进程

Basile 提到,这对于查找当前正在运行的可执行文件使用的所有库很有用。例如:

sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u
Run Code Online (Sandbox Code Playgroud)

显示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
Run Code Online (Sandbox Code Playgroud)

此方法还示出了具有打开的库dlopen,以测试该最小设置入侵了一个sleep(1000)在Ubuntu 18.04。

另请参阅:如何在 Linux 中查看当前加载的共享对象?| 超级用户

  • 关于 readelf 方法的一个好处是它也适用于跨二进制文件(例如:amd64 上的 armhf) (3认同)
  • +1 深入研究 elf 二进制文件本身,而不是依赖链接器或其他工具。 (2认同)

Tho*_*key 24

ldd 和 lsof 显示直接或在给定时刻加载的库。它们不考虑通过dlopen(或由 丢弃dlclose)加载的库。您可以使用strace例如更好地了解这一点,

strace -e trace=open myprogram
Run Code Online (Sandbox Code Playgroud)

(因为dlopen最终调用open- 尽管您当然可能有一个系统为 64 位打开使用不同的名称......)。

例子:

strace -e trace=open date
Run Code Online (Sandbox Code Playgroud)

给我看这个:

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
Run Code Online (Sandbox Code Playgroud)

从中可以grep“.so”名称以查看共享对象。

  • 改进:`strace -e trace=open,openat myprogram` (7认同)

小智 11

lsof还可以向您显示哪些库正在用于某个特定进程。

IE

$ 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
Run Code Online (Sandbox Code Playgroud)