[英]How to find a hidden library that can't be shown by using ldd and rpath?
我正在构建高性能Linpack,并且试图与我的同事共享该二进制文件。 在构建它之前,以下库也是由我自己构建的,并安装在/opt
。 这些库是: /opt/blis
, /opt/knem
和/opt/openmpi
。
我试图将这些二进制且仅必要的库转移给我的同事。 但是我发现我在/opt/openmpi/lib
建立的库必须在运行时引用。
我已经通过使用ldd,chrpath和objdump检查了有关rpath / runpath以及共享库使用情况的所有二进制文件和库。 /opt/openmpi/lib
不应引用其他库。
有什么建议的方法可以知道将要引用哪个库,或者如何为我跟踪运行时文件访问,以找出需要转移给我的同事的最小文件集是什么?
使用ldd,发现将使用以下库和二进制文件:
二进制文件:
xhpl
mpirun
图书馆:
libblis.so.2
libjemalloc.so.2
libmpi.so.40
libopen-pal.so.40
libopen-rte.so.40
我使用chrpath让所有二进制文件和库都指向正在运行的目录,但是它不起作用:
chrpath -c [binaries and libraries]
chrpath -r ./ [binaries and libraries]
我希望只能将最少数量的文件传输给我的同事并运行它,而无需修改系统配置。
您很幸运Linux在这些方面非常强大。 ldd
不显示它们的可能原因是ldd
仅显示了由动态链接器链接的库。 它不显示通过C api调用链接的库( dlopen(...)
等)。
您可以使用strace
工具检查程序在运行时尝试执行的操作。 通常,在开始的几秒钟内加载其库:
命令
strace -s 4096 -f -o sux ./yourbinary
将以跟踪模式启动您的./yourbinary
,并将输出写入名为sux
的文件中。 例如, /bin/echo
的strace的前几行看起来是这样的:
execve("/bin/echo", ["/bin/echo", "arg"], 0x7ffd2542fc50 /* 39 vars */) = 0
brk(NULL) = 0x5631fce2c000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (file not found)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=275366, ...}) = 0
mmap(NULL, 275366, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7edeb8de6000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <--- here you can see, that it opened /lib/x86_64-linux-gnu/libc.so.6 !
它也跟踪内核调用,二进制文件执行了什么,导致了很多不需要的信息(对于经验不足的人来说,通常很难理解)。 但是,无论/lib/<arch>/libc.so.6
,只要它使用对某个库的/lib/<arch>/libc.so.6
open
的调用(在我的示例中为/lib/<arch>/libc.so.6
文件),它都将清晰可见。
您也可以使用grep
工具过滤输出,例如grep openat.*\\.so sux
将过滤输出文件中的库开口(在本示例中为sux
)。
重要的是我们在这里使用的是,打开共享库是通过在内核级别进行简单的openat()
调用来完成的(这是C库中open()
的内核调用变体)。
这是通过lsof
工具完成的。 共享库中链接的文件是正在运行的进程的地址空间中的mmap()
ped文件。 MMap意味着该文件不会被读取到进程的堆中,而是会被映射到其地址空间中。 在我们的案例中,差异并不重要,但是lsof
却以不同的方式显示了它们。 本质上,一个mmap()
ped文件的内容将在指针的进程内存中可用:读取该文件将读取该文件,写入该文件将写入该文件(在磁盘上)。 它甚至可以执行 (在汇编级别通过call
来call
),而这正是我们使用链接的共享库所做的!
要获取正在运行的进程的打开(映射)文件的列表,可以使用以下命令
lsof -n -P -p <pid>
-n -P
仅禁用此处不需要的某些网络分辨率, -p
是重要的事情,因为它显示了<pid>
的打开文件。 例如,正在运行的bash shell的lsof
输出是这样的:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 9072 root cwd DIR 8,7 4096 721255 /root
bash 9072 root rtd DIR 8,7 4096 2 /
bash 9072 root txt REG 8,7 1168776 6422594 /bin/bash
bash 9072 root mem REG 8,7 55792 2105586 /lib/x86_64-linux-gnu/libnss_files-2.28.so
bash 9072 root mem REG 8,7 164738 3844637 /usr/share/locale/de/LC_MESSAGES/libc.mo
bash 9072 root mem REG 8,7 337184 3051462 /usr/lib/locale/de_AT.utf8/LC_CTYPE
bash 9072 root mem REG 8,7 2586242 2753498 /usr/lib/locale/aa_DJ.utf8/LC_COLLATE
bash 9072 root mem REG 8,7 1824496 2105577 /lib/x86_64-linux-gnu/libc-2.28.so
bash 9072 root mem REG 8,7 14592 2105579 /lib/x86_64-linux-gnu/libdl-2.28.so
bash 9072 root mem REG 8,7 183528 2097224 /lib/x86_64-linux-gnu/libtinfo.so.6.1
bash 9072 root mem REG 8,7 89016 2105583 /lib/x86_64-linux-gnu/libnsl-2.28.so
bash 9072 root mem REG 8,7 47608 2105588 /lib/x86_64-linux-gnu/libnss_nis-2.28.so
bash 9072 root mem REG 8,7 39736 2105584 /lib/x86_64-linux-gnu/libnss_compat-2.28.so
bash 9072 root mem REG 8,7 54 3020617 /usr/lib/locale/agr_PE/LC_NUMERIC
bash 9072 root mem REG 8,7 165632 2105569 /lib/x86_64-linux-gnu/ld-2.28.so
<...many unneeded thingy...>
bash 9072 root 0u CHR 136,2 0t0 5 /dev/pts/2
bash 9072 root 1u CHR 136,2 0t0 5 /dev/pts/2
bash 9072 root 2u CHR 136,2 0t0 5 /dev/pts/2
bash 9072 root 255u CHR 136,2 0t0 5 /dev/pts/2
在fd
列中,您可以看到mem
,它是一个mmap()
文件。 如果映射了扩展名为.so
的文件,则该文件为运行时链接的共享库。
同样,您可以使用grep
工具来过滤输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.