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

时间:2008-11-23 00:25:37

标签: c debugging dynamic gdb call-graph

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

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

(gdb) trace Foo* Bar* printf

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

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

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

某些GDB向导必须有这个常见作业的脚本!

5 个答案:

答案 0 :(得分:8)

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

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

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

if $arg1
...

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

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

答案 1 :(得分:3)

rbreak cmd接受正则表达式来设置断点。您可以使用:

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

See this了解断点的详细信息。

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

(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打印回溯的最后一帧(即它是当前函数)c是一个捷径对于continue,继续执行,end只是命令列表的分隔符。

NB :如果跟踪库函数,您可能希望等待lib加载。例如。设置一个中断到main或任何函数,运行app直到那一点,然后才设置你想要的断点。

答案 2 :(得分:2)

使用正确的工具进行工作;)

How to print the next N executed lines automatically in GDB?

答案 3 :(得分:1)

你有没有看到litb对于类似帖子的优秀感谢here

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

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

答案 4 :(得分:0)

您可以在批处理模式下调用gdb(使用-x选项),在需要的位置中断并请求回溯(bt),然后使用{{1}过滤结果}或grep

缩进比较困难,但是egrep输出是有序的,因此您在跟踪顶部有当前函数,在最底部有bt

所以你用命令创建文件:

main

然后运行br <function name where to break> run bt kill quit

过滤以gdb <program> -x<command file>开头的字符串 - 您将获得堆栈跟踪。