自动将进入/退出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 --symsnm类的东西从符号表中提取相应的名称,当然假设符号没有从相关的二进制文件中删除。

使用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可能要容易得多。