在gdb中观察内存范围?

36

我在使用GDB调试程序,希望当内存区域0x08049000到0x0804a000被访问时程序停止。但是手动设置内存断点时,GDB似乎只支持同时设置两个断点。

(gdb) awatch *0x08049000
Hardware access (read/write) watchpoint 1: *0x08049000
(gdb) awatch *0x08049001
Hardware access (read/write) watchpoint 2: *0x08049001
(gdb) awatch *0x08049002
Hardware access (read/write) watchpoint 3: *0x08049002
(gdb) run
Starting program: /home/iblue/git/some-code/some-executable
Warning:
Could not insert hardware watchpoint 3.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

已经有一个问题提到过这个话题了,答案是可以使用valgrind来实现。不幸的是,该答案没有包含任何示例或对valgrind手册的引用,因此并没有提供很多帮助:如何使用gdb观察整个内存区域中的任何更改?

所以,我该怎么观察整个内存区域呢?


有趣的事实:PowerPC具有范围断点(但没有监视点):https://dev59.com/QWrXa4cB1Zd3GeqPEO0t#31658056 - Ciro Santilli OurBigBook.com
x86支持小的监视范围,最多可达8个字节:https://zh.wikipedia.org/wiki/X86调试寄存器 - Ciro Santilli OurBigBook.com
3个回答

32
如果您使用GDB 7.4和Valgrind 3.7.0,则可以拥有无限制的“模拟”硬件观察点。
在Valgrind下启动您的程序,并给出参数--vgdb=full --vgdb-error=0,然后使用GDB连接到它(target remote | vgdb)。 然后您可以通过执行rwatch (char[100]) *0x5180040来观察内存范围,比如使用watchawatchrwatch命令。
更多详情请参见Valgrind用户手册上关于gdb集成的部分

4
在我花费了一整天的时间来琢磨mprotect和滥用SIGSEV处理程序以中断内存访问之后,我尝试了这个方法,它运行得非常完美。你挽救了我的一整天。谢谢! - iblue
是的,+1。我已经寻找这样的功能好几个月了。 - Crashworks
那么,如何确定由valgrind启动的进程的堆地址呢?我通常通过*/proc/[pid]/maps来确定,但是当我通过这个valgrind命令启动python时,maps文件没有像我习惯的那样被*[heap]**标识的条目。 - Andrew Falanga
1
我意识到这个答案是很久以前写的,但我对这个答案感到困惑,因为gdb可以自己完成这个任务,不需要valgrind的帮助。至少现在可以这样做。它会采用单步执行并反复检查的方式。显然这非常耗费时间(就像valgrind一样),所以你需要缩小范围,找出即将发生损坏的位置,然后创建监视点,这样你就不必让它在整个调试过程中运行缓慢了。 - doug65536

16

检测内存地址变化的功能被称为硬件断点,它实际上是CPU的一个特性——一个位于内存控制器内部的寄存器,用于检测是否访问了特定地址,并触发调试器中断。不幸的是,x86架构 只有四个这样的寄存器, 这就是为什么你在设置内存监视断点时受到限制的原因。

这就是为什么你需要使用像valgrind这样的工具; 如果你想要监视整个区域,你必须使用模拟内存访问模式的软件来完成。我不知道valgrind是否支持监视整个内存范围。也许你需要自己修改它。可以修改VALGRIND_MAKE_MEM_NOACCESS()函数来抛出一个断点,但允许程序继续执行。


2

我已经验证了最近的 gdb 支持监视一系列地址,因此 Valgrind 不是必须的,就像其他答案所建议的那样,测试环境:

  • GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
  • 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz

使用以下命令:

watch *(char [100]*)&gbuf

然后我们开始观察地址范围[gbuf,gbuf + 100)


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