18

如何在调用 gdb 时打印感兴趣的函数,并根据它们在堆栈中的深度进行缩进?

我希望能够说类似(编造)的话:

(gdb) trace Foo* Bar* printf

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

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

通配符(或等价物)是必不可少的,因为有很多 Foo 和 Bar 函数。虽然我会满足于记录每个功能。或者,也许告诉 gdb 记录特定库中的所有函数。

一些 GDB 向导必须有一个脚本来完成这个常见的工作!

4

5 回答 5

8

在您的情况下,我会求助于definegdb 中的命令,它允许您定义一个函数,该函数最多可以接受 10 个参数。

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

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

if $arg1
...

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

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

于 2009-09-30T20:22:04.463 回答
4

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

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

有关断点的详细信息,请参阅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打印回溯的最后一帧(即它是当前函数)ccontinue, 继续执行的快捷方式,并且end只是命令列表的分隔符。

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

于 2013-01-30T05:04:27.933 回答
2

为工作使用正确的工具;)

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

于 2009-07-14T02:59:38.617 回答
1

您是否在这里看到了 litb 对类似帖子的出色回答?

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

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

于 2008-11-23T01:29:20.607 回答
0

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

缩进更难,但是bt输出是有序的,因此您在跟踪的顶部和main最底部都有当前函数。

所以你用命令创建文件:

br <function name where to break>
run
bt
kill
quit

然后运行gdb <program> -x<command file>

过滤以 - 开头的字符串,#<digit>您将获得堆栈跟踪。

于 2008-11-23T07:53:11.503 回答