自动将进入/退出function日志添加到项目
我有第三方源代码,我必须调查。 我想知道调用函数的顺序,但我不想浪费时间输入:
printf("Entered into %s", __FUNCTION__)
和
printf("Exited from %s", __FUNCTION__)
对于每个function,我也不想触摸任何源文件。
你有什么建议吗? 是否有一个编译器标志可以自动为我执行此操作?
澄清评论:
- 我将交叉编译源代码以在ARM上运行它。
- 我将用gcc编译它。
- 我不想分析静态代码。 我想跟踪运行时。 所以doxygen不会让我的生活更轻松。
- 我有源,我可以编译它。
- 我不想使用面向方面编程。
编辑:我发现gdb提示符中的’frame’命令在那个时间点打印当前帧(或者,你可以说是函数名)。 也许,每次调用函数时,都可以(使用gdb脚本)调用’frame’命令。 你怎么看?
除了通常的调试器和面向方面的编程技术之外,您还可以使用gcc的-finstrument-functions
命令行选项注入自己的检测function。 您必须实现自己的__cyg_profile_func_enter()
和__cyg_profile_func_exit()
函数(在C ++中将它们声明为extern "C"
)。
它们提供了一种跟踪从哪里调用函数的方法。 但是,接口有点难以使用,因为例如,被调用的函数的地址及其调用站点被传递而不是函数名。 您可以记录地址,然后使用objdump --syms
或nm
类的东西从符号表中提取相应的名称,当然假设符号没有从相关的二进制文件中删除。
使用gdb
可能更容易。 因人而异。 🙂
你说“我也不想触摸任何源文件”……如果你让一个脚本为你做这个公平游戏?
在所有.cpp文件上运行此命令
sed 's/^{/{ENTRY/'
所以它将它们转换成:
void foo() {ENTRY // code here }
把它放在每个单元都可以#included的标题中:
#define ENTRY EntryRaiiObject obj ## __LINE__ (__FUNCTION__); struct EntryRaiiObject { EntryRaiiObject(const char *f) : f_(f) { printf("Entered into %s", f_); } ~EntryRaiiObject() { printf("Exited from %s", f_); } const char *f_; };
您可能必须使用sed
脚本获得更好的sed
。 您还可以将ENTRY宏放在您想要探测的任何其他位置,例如函数的一些深度嵌套的内部范围。
使用/ Gh(启用_penter Hook函数)和/ GH(启用_pexit Hook函数)编译器开关(如果可以编译源代码的话)
注意:您将无法使用这些宏。 请参阅此处 (“您将需要获取函数地址(在EIP寄存器中)并将其与映射文件中可由链接器生成的地址进行比较(假设没有发生变基)。但它会非常慢。” )
同意William,使用gdb查看运行时流程。
有一些静态代码分析器可以告诉哪些函数调用哪些,并且可以给你一些调用流程图。 一个工具是“理解C ++”(支持C / C ++),但我认为这不是免费的。 但是你可以找到类似的工具。
如果你正在使用gcc,魔术编译器标志是-g。 使用调试符号编译,在gdb下运行程序,并生成堆栈跟踪。 你也可以使用ptrace,但是使用gdb可能要容易得多。