4

给定一个动态链接的 ELF 二进制文件,例如/bin/less.

在二进制文件中,有一个对共享库提供的函数的调用,例如strcpy()

如何找出strcp函数是从哪个共享库/共享对象中获取的?换句话说,我想得到对 func_name/shared_obj_name.so。

迈克尔·斯莱德在回答这篇文章时写道:

ELF 文件没有指定哪些符号来自哪些库;它只是将共享库列表添加到 ELF 二进制文件中,并让链接器在库中查找符号。

然而,必须有一种方法来收集所需的信息(使用链接器)。在我的情况下,执行二进制文件和 ltrace 不是一个选项。到目前为止我尝试了什么:

我试过objdump -T /bin/less | grep strcpy这给了我:

0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strcpy
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __strcpy_chk

这既不是明确的,也没有给我.so文件的名称。

运行ldd /bin/less,返回:

linux-vdso.so.1 =>  (0x00007ffe8b7fa000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f92c23a5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f92c1fe0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f92c25ec000))

让我认为“GLIBC_2.2.5”对应于libc.so.6

如何以编程方式找到(导入的)函数对应的共享对象(.so 文件)?

4

1 回答 1

3

如何找出 strcp 函数是从哪个共享库/共享对象中获取的?

一般来说,您不能:该库可以在运行时更改。例如,如果我编译以下源代码:

int strcpy(char *a, const char *src) { abort(); }

$ gcc -fPIC -shared -o foo.so foo.c

然后像这样运行你的程序:

LD_PRELOAD=./foo.so /bin/less

那么从中strcpy获得的库是foo.so. 使用LD_PRELOAD这种方式称为库插入,在各种情况下都很有用。

除了. _ _LD_PRELOAD

如果您没有使用任何此类机制,并且正在使用 GLIBC,那么您可以要求动态加载程序为您回答该问题。这是一种方法:

 LD_DEBUG=bindings ldd -r /bin/less < /dev/null |& egrep '\Wstrcpy\W'
     26623: binding file /bin/bash [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]
     26633: binding file /lib/x86_64-linux-gnu/libtinfo.so.5 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]
     26633: binding file /bin/less [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]

上面你可以看到ldd调用bashless作为单独的进程,它们都绑定到libc.so.6这个特定的符号。

如何以编程方式找到(导入的)函数对应的共享对象(.so 文件)?

如果您使用的是 GLIBC,请使用dladdr来“询问”动态链接器。返回的“信息”参数会告诉你文件名。

于 2015-04-30T04:24:00.233 回答