帮助使用GDB跟踪(或类似工具)的方法。

6
我有一个应用程序,源代码是用C语言编写的。我可以按照自己的意愿进行编译,并添加所需的工具等。但是,我不想在源代码中添加一堆printf语句。我希望能够产生某种日志,显示特定值(例如全局结构的某个成员)何时被写入(其值发生了更改)。我希望能够显示源文件和行号,以及旧值和新值。
此外,我还希望能够通过名称而不是地址来指定该值。但是,地址也可以。如果我可以指定一个函数内部的本地值,则额外加分。
我仍然在费尽心思地尝试理解gdb的跟踪命令。非常感谢您的帮助。谢谢。
3个回答

6

首先,您需要确保使用调试符号编译程序,并且可能不进行优化以使gdb最有用。对于gcc,这将是-g -O0

其次,您要查找的功能不是跟踪,而是监视点。

(gdb) help watch
Set a watchpoint for an expression.
A watchpoint stops execution of your program whenever the value of
an expression changes.

因此,给定一些示例代码:

那么,给出一些示例代码:

int main() {
    int a;
    a = 1;
    a = 2;
    return 0;
}

您可以在上面运行gdb,然后:
(gdb) b main
Breakpoint 1 at 0x80483a5: file test.c, line 4.
(gdb) run
Starting program: /tmp/test 

Breakpoint 1, main () at test.c:4
4               a = 1;
(gdb) watch a
Hardware watchpoint 2: a
(gdb) c
Continuing.
Hardware watchpoint 2: a

Old value = -1207552288
New value = 2
main () at test.c:8
8               return 0;

由于存在于堆栈中,而不是内存中,它的工作方式有点奇怪。如果启用了优化,它的工作甚至会更少:a将被优化掉。


1
尝试将a声明为volatile int,这可能会使示例更好地运行。 - caf
谢谢derobert。据我所了解,观察器会导致程序执行停止,直到用户“继续”。我确定我可以编写一个expect脚本来完成这个任务,但是是否有办法在gdb内部自动完成呢? - tvaughan
@tvaughan:我不知道在gdb中有没有自动完成它的方法。 - derobert
@tvaughan:尽管gdb确实有一个(可选的)内置Python API,但您可能可以使用它。 “info gdb扩展Python”应该能帮到您。 - derobert

3
如前所述,您需要在变量上设置监视点。
然后使用“commands”命令。
(gdb) help commands
Set commands to be executed when a breakpoint is hit.
Give breakpoint number as argument after "commands".
With no argument, the targeted breakpoint is the last one set.
The commands themselves follow starting on the next line.
Type a line containing "end" to indicate the end of them.
Give "silent" as the first line to make the breakpoint silent;
then no output is printed when it is hit, except what the commands print.

因此,从watch命令中找到观察点编号,然后执行以下操作(假设您的观察点是第二个断点)

(gdp) commands 2
> print a
> cont
> end

假设您想要的变量是a。如果您对gdb给出的输出感到满意,可以省略print语句。
您还可以使用原始断点中的命令设置监视点并继续执行。

1
谢谢你们两个,@derobert和@peter!我最终回到了这个问题:


break main
commands
        watch somevar
        commands
                cont
        end
        cont
end
run

这个技巧很有用。当“somevar”是全局的或者是在“main”函数中时,它可以正常工作。如果“somevar”是另一个函数的本地变量,只需将“main”替换为该函数名称即可。

将这些命令放入文件中(例如“gdbscript”),然后像下面这样运行gdb:

gdb -x gdbscript a.out

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接