假设我有一个二进制库(*.so)和使用该库的二进制程序(即我没有这两者的源代码)。
如何在运行时找出调用了库中哪些函数。我想知道它们的名称,但不需要实时信息。
这两个二进制文件都不包含调试符号。
如何在运行时找出调用了库中哪些函数。我想知道它们的名称,但不需要实时信息。
这两个二进制文件都不包含调试符号。
Objdump命令从二进制文件中转储外部符号引用。一般使用-T
选项运行它,以便转储一个二进制文件的外部符号引用。
例如,在/bin/ls
上运行objdump -T
:
/bin/ls: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.3 __ctype_toupper_loc
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 getenv
0000000000000000 DF *UND* 0000000000000000 cap_to_text
0000000000000000 DO *UND* 0000000000000000 GLIBC_2.2.5 __progname
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 sigprocmask
...
等等,转储包括所有外部符号引用,不仅仅是函数。手册页面解释了第二列中代码的含义,指定外部符号引用的类型。这里,看起来我们对DF感兴趣,表示动态函数调用。在这里,我们可以看到一些熟悉的C库函数,如getenv()
和sigprocmask()
,被"/bin/ls"引用。
无法识别的库调用可能是头文件中的内部宏使用库的内部实现细节导致的。这可能就是“__ctype_toupper_loc”的全部含义。
当使用此选项与C++代码一起使用时,您还需要指定-C
选项以取消编译C++符号。
当然,特定二进制文件携带某个库函数的外部引用并不能保证二进制文件在运行时实际调用该函数。
暂时忽略使用dlopen
/dlsysm
的可能性,通常你只需要使用类似nm a.out
(或者你可执行文件的名称)的命令。
对于C++,你可能想要添加--demangle
来解开C++名称,使其更易读。你也可以使用-u
来获取仅未定义的外部符号(这将删除一些你可能不关心的符号)。
如果程序正在使用dlopen
/dlsym
,那么了解它链接的内容的唯一方法就是在运行时监视它。它可能(例如)打开一个文本文件,读取一些字符串,然后使用这些字符串作为库和函数的名称进行链接。更改该文本文件可能会完全改变它链接的函数,因此你无法根据可执行文件本身的内容确定这一点。
strace
能帮到你吗? - alk