简体   繁体   English

如何找到使用ldd和rpath无法显示的隐藏库?

[英]How to find a hidden library that can't be shown by using ldd and rpath?

I'm building High Performance Linpack, and I am trying to share the binary to my colleagues. 我正在构建高性能Linpack,并且试图与我的同事共享该二进制文件。 Before I build it, the following libraries are also build by myself, and are installed in /opt . 在构建它之前,以下库也是由我自己构建的,并安装在/opt These libraries are: /opt/blis , /opt/knem , and /opt/openmpi . 这些库是: /opt/blis/opt/knem/opt/openmpi

I tried to transfer these binary and only necessary libraries to my colleagues. 我试图将这些二进制且仅必要的库转移给我的同事。 However I found that the library I build located in /opt/openmpi/lib must be referenced in runtime. 但是我发现我在/opt/openmpi/lib建立的库必须在运行时引用。

I already check all binaries and libraries about rpath/runpath, and the usage of share libraries by using ldd, chrpath, and objdump. 我已经通过使用ldd,chrpath和objdump检查了有关rpath / runpath以及共享库使用情况的所有二进制文件和库。 No other library in /opt/openmpi/lib should be referenced. /opt/openmpi/lib不应引用其他库。

Is there any suggested method to know which library will be referenced, or how to trace runtime file access for me, to find out what are the minimal set of files that I need to transfer to my colleague? 有什么建议的方法可以知道将要引用哪个库,或者如何为我跟踪运行时文件访问,以找出需要转移给我的同事的最小文件集是什么?

Using ldd and found that following libraries and binaries will be used: 使用ldd,发现将使用以下库和二进制文件:

Binaries: 二进制文件:

  • xhpl
  • mpirun

Libraries: 图书馆:

  • libblis.so.2
  • libjemalloc.so.2
  • libmpi.so.40
  • libopen-pal.so.40
  • libopen-rte.so.40

I used chrpath to let all the binaries and libraries point to the running directory, but it doesn't work: 我使用chrpath让所有二进制文件和库都指向正在运行的目录,但是它不起作用:

  • chrpath -c [binaries and libraries]
  • chrpath -r ./ [binaries and libraries]

I expected I can only transfer the minimal number of files to my colleagues and run it without modifying the system config. 我希望只能将最少数量的文件传输给我的同事并运行它,而无需修改系统配置。

You have luck that Linux is very strong in such things. 您很幸运Linux在这些方面非常强大。 The likely reason, why ldd doesn't show them, is that ldd shows only the libraries linked by the dynamic linker. ldd不显示它们的可能原因是ldd仅显示了由动态链接器链接的库。 It does not show the libs which were linked by C api calls ( dlopen(...) et al). 它不显示通过C api调用链接的库( dlopen(...)等)。

How to trace a program in runtime for the opened sharedlibs 如何在运行时为打开的共享库跟踪程序

You can check with the strace tool, what a program tries to do while it runs. 您可以使用strace工具检查程序在运行时尝试执行的操作。 Mostly, in loads its libraries in the first seconds: 通常,在开始的几秒钟内加载其库:

The command 命令

strace -s 4096 -f -o sux ./yourbinary

will start your ./yourbinary in tracing mode, and writes the output in a file named sux . 将以跟踪模式启动您的./yourbinary ,并将输出写入名为sux的文件中。 For example, the first some lines of a strace of a /bin/echo looks so: 例如, /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 !

It traces the kernel calls, what the binary executed, what results a lot of unneeded (and, for unexperienced eyes, often hardly comprehensible) information, too. 它也跟踪内核调用,二进制文件执行了什么,导致了很多不需要的信息(对于经验不足的人来说,通常很难理解)。 But, any time if it uses an open -like call to some library (in my example, the /lib/<arch>/libc.so.6 file), it will be clearly visible. 但是,无论/lib/<arch>/libc.so.6 ,只要它使用对某个库的/lib/<arch>/libc.so.6 open的调用(在我的示例中为/lib/<arch>/libc.so.6文件),它都将清晰可见。

You can also use the grep tool to filter the output, for example grep openat.*\\.so sux will filter for the library openings in the output file ( sux in our example). 您也可以使用grep工具过滤输出,例如grep openat.*\\.so sux将过滤输出文件中的库开口(在本示例中为sux )。

The important thing is what we use here, that opening a shared lib is being done with a simple openat() call on the kernel level (what is a kernel-call variant of the open() in the C libraries). 重要的是我们在这里使用的是,打开共享库是通过在内核级别进行简单的openat()调用来完成的(这是C库中open()的内核调用变体)。

How to check a running process, which sharedlibs has it mapped 如何检查正在运行的进程(已映射到哪个共享库)

It is being done by the lsof tool. 这是通过lsof工具完成的。 The linked in shared libraries are mmap() -ped files in the address space of the running process. 共享库中链接的文件是正在运行的进程的地址空间中的mmap() ped文件。 MMap means that the file is not read into the heap of the process, instead it is mapped into its address space. MMap意味着该文件不会被读取到进程的堆中,而是会被映射到其地址空间中。 The difference is not important in our case, but lsof shows them differently. 在我们的案例中,差异并不重要,但是lsof却以不同的方式显示了它们。 Essentially, the content of an mmap() -ped file will be available in the memory of the process on a pointer: reading it will read the file, and writing to it will write the file (on the disk). 本质上,一个mmap() ped文件的内容将在指针的进程内存中可用:读取该文件将读取该文件,写入该文件将写入该文件(在磁盘上)。 It can be even executed (called by call on the assembly level), and this is what we with the linked shared libs mostly do! 它甚至可以执行 (在汇编级别通过callcall ),而这正是我们使用链接的共享库所做的!

To get the list of the opened (mmapped) files of a running process, you can use the command 要获取正在运行的进程的打开(映射)文件的列表,可以使用以下命令

lsof -n -P -p <pid>

-n -P is only to disable some here unneeded network resolutions, -p is the important thing, because it shows the opened files of <pid> . -n -P仅禁用此处不需要的某些网络分辨率, -p是重要的事情,因为它显示了<pid>的打开文件。 For example, the lsof output of a running bash shell is this: 例如,正在运行的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

In the fd column, where you can see mem , it is an mmap() -ed file. fd列中,您可以看到mem ,它是一个mmap()文件。 If a file with a .so extension is mapped, then it is a runtime-linked shared lib. 如果映射了扩展名为.so的文件,则该文件为运行时链接的共享库。

Again you can use the grep tool to filter the output. 同样,您可以使用grep工具来过滤输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM