在调用函数时使GDB打印控制流程

如何调用感兴趣的gdb打印函数,根据堆栈的深度缩进?

我希望能够说出(制作):

(gdb) trace Foo* Bar* printf 

并让gdb打印所有以Foo或Bar开头的函数,因为它们被调用。 有点像gnu cflow,除了使用调试符号和仅实际调用的打印函数,而不是所有可能的调用流。

无法帮助的工具包括cachegrind,callgrind和oprofile,它们最常调用函数的结果。 我需要保留的调用顺序。

通配符(或等效的)是必不可少的,因为有很多Foo和Bar函数。 虽然我愿意完全记录所有function。 或者,也许告诉gdb记录特定库中的所有函数。

某些GDB向导必须有一个用于此常见作业的脚本!

在您的情况下,我将转向gdb中的define命令,它允许您定义一个函数,该函数最多可以包含10个参数。

您可以将函数名称传递给“trace”作为您定义的函数的参数,或者将它们全部记录在函数本身中。 我会做类似以下的事情

 define functiontrace if $arg0 break $arg0 commands where continue end end if $arg1 ... 

gdb中用户定义函数的参数引用为$ arg0- $ arg9。 或者,您可以在函数中记录要跟踪的每个函数,而不是使用$ arg0-9。

注意:这不会缩进堆栈跟踪中的深度,但每次调用函数时都会打印堆栈跟踪。 我发现这种方法比strace等更有用…因为它会记录你想要的任何函数,系统,库,本地或其他。

有一个rbreak cmd接受用于设置断点的正则表达式。 您可以使用:

 (gdb) rbreak Foo.* (gdb) rbreak Bar.* (gdb) break printf 

有关断点的详细信息, 请参阅此处。

然后使用commands打印调用的每个函数。 例如,让α=最后一个断点的编号(如果错过了你可以用它检查) ,然后执行:

 (gdb) commands 1-α Type commands for breakpoint(s) 1-α, one per line. End with a line saying just "end". >silent >bt 1 >c >end (gdb) 

一些细化: silent抑制不必要的信息消息, bt 1打印最后一帧的回溯(即它是当前函数)ccontinue的快捷方式,继续执行,而end只是命令列表的分隔符。

注意 :如果您跟踪库函数,您可能希望等待lib加载。 例如,设置一个rest到main或任何function,运行应用程序直到该点,然后只设置你想要的断点。

使用正确的工具;)

如何在GDB中自动打印下N行?

你有没有看到litb对这里类似post的出色表现?

他使用readelf来获取有趣的符号,使用gdb命令来获取跟踪,并使用awk来粘合所有这些。

基本上你需要改变的是修改他的gdb命令脚本以从回溯中删除1深度以查看堆栈并过滤特定函数,并使用awk / python /(…)脚本重新格式化输出以将其呈现为树。 (我承认我现在太懒了…)

您可以在批处理模式下调用gdb (使用-x选项),在需要的地方中断并请求回溯( bt ),然后使用grepegrep过滤结果。

缩进比较困难,但是bt输出是有序的,所以你在轨迹顶部有一个当前函数,而在最底部有main函数。

所以你用命令创建文件:

 br  run bt kill quit 

然后运行gdb -x

过滤以#开头的字符串 – 您将获得堆栈跟踪。