如何调用感兴趣的gdb打印函数,根据堆栈的深度缩进?
我希望能够说出(制作):
(gdb) trace Foo* Bar* printf
让gdb打印所有以Foo或Bar开头的函数,因为它们被调用。有点像gnu cflow,除了使用调试符号和只打印实际被调用的函数,而不是所有可能的调用流。
无法帮助的工具包括cachegrind,callgrind和oprofile,它们对最常调用函数的结果进行排序。我需要保留调用的顺序。
通配符(或等效物)是必不可少的,因为有很多Foo和Bar功能。虽然我愿意完全记录所有功能。或者,也许告诉gdb记录特定库中的所有函数。
某些GDB向导必须有这个常见作业的脚本!
答案 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)
答案 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>
开头的字符串 - 您将获得堆栈跟踪。