我想找出二进制文件在运行时加载的动态库列表(及其完整路径)。我使用的是CentOS 6.0。这个怎么做?
答案1
您可以使用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.
....
例子:
$ 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)
答案2
readelf -d $executable | grep 'NEEDED'
如果您无法运行可执行文件,例如,如果它是交叉编译的,或者如果您不信任它,则可以使用:
在通常情况下,ldd 调用标准动态链接器(请参阅 ld.so(8)),并将 LD_TRACE_LOADED_OBJECTS 环境变量设置为 1,这会导致链接器显示库依赖项。但请注意,在某些情况下,某些版本的 ldd 可能会尝试通过直接执行程序来获取依赖关系信息。因此,您永远不应该在不受信任的可执行文件上使用 ldd,因为这可能会导致执行任意代码。
例子:
readelf -d /bin/ls | grep 'NEEDED'
示例输出:
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
0x0000000000000001 (NEEDED) Shared library: [libacl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
请注意,库可以依赖于其他库,因此现在您需要找到依赖项。
一种通常有效的简单方法是:
$ 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
但更精确的方法是了解ldd
搜索路径/缓存。我认为ldconfig
这是要走的路。
选择一个,然后重复:
readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'
示例输出:
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]
等等。
也可以看看:
/proc/<pid>/maps
用于运行进程
巴塞尔提到的,这对于查找当前正在运行的可执行文件使用的所有库很有用。例如:
sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u
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
此方法还显示使用 打开dlopen
、测试的库这个最小的设置sleep(1000)
在 Ubuntu 18.04 上破解了。
答案3
ldd 和 lsof 显示加载的库直接地或在一个给定的时刻。他们不考虑通过加载的库dlopen
(或被丢弃dlclose
)。您可以使用 更好地了解这一点strace
,例如,
strace -e trace=open myprogram
(因为dlopen
最终会调用open
- 尽管您当然可能有一个系统使用不同的名称进行 64 位打开...)。
例子:
strace -e trace=open date
给我看这个:
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
从中可以 grep“.so”名称来查看共享对象。
答案4
批量查询:
创建一个小脚本 (
useslib
) 并放入 PATH 中(或在下面的命令中指定完整路径)#! /bin/bash ldd $1 | grep -q $2 exit $?
在命令中使用它
find
,例如:find /usr/bin/ -executable -type f -exec useslib {} libgtk-x11-2.0 \; -print
(libgtk-x11-2.0似乎是gtk2库)