假设我有一个二进制库(* .so)和一个使用该库的二进制程序(即我不拥有任何一个的源代码)。
如何确定在运行时调用了哪些库函数。我想知道他们的名字,但不需要实时信息。
两个二进制文件都不包含调试符号。
答案 0 :(得分:0)
objdump命令从二进制文件中转储外部符号引用。典型的用例是使用-T
选项运行它,以转储二进制文件的外部符号引用。
例如,在objdump -T
上运行/bin/ls
:
/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
感兴趣,表明动态函数调用。在这里,我们可以看到`/ bin / ls引用了一些熟悉的C库函数,例如getenv()
和sigprocmask()
。
使用库的内部实现详细信息,无法识别的库调用可能是头文件中的内部宏的结果。这可能就是“ __ctype_toupper_loc”的全部含义。
将其与C ++代码一起使用时,您还希望指定-C
选项,以消除C ++符号的麻烦。
当然,特定二进制文件带有对某些库函数的外部引用这一事实并不能保证二进制文件在运行时会真正调用它。
答案 1 :(得分:0)
(暂时)忽略使用dlopen
/ dlsysm
的可能性,您通常只会使用nm a.out
之类的东西(或可执行文件的名称)。
对于C ++,您可能希望添加--demangle
以将C ++名称分解为至少稍微易读的名称。您可能还想使用-u
来获取未定义的外部符号(这将删除可能无关的许多符号)。
如果程序使用的是dlopen
/ dlsym
,那么实质上知道链接的唯一方法是在运行时对其进行监视。例如,它可以打开一个文本文件,读取一些字符串,然后使用这些字符串作为要链接的库和函数的名称。更改该文本文件可能会完全更改其链接的功能,因此您无法真正根据可执行文件本身的内容来确定它。