GDB:将观察点设置为数组,定义值大小

GDB: set watchpoint into array, defining value size

提问人:Robert 提问时间:9/15/2023 最后编辑:Robert 更新时间:9/16/2023 访问量:82

问:

我的程序使用数组作为堆的表示形式,它可能包含不同大小的值。对于这个问题,最值得注意的是,at 的值 和 是两个 16 位值。char heap[](uint16_t*) &heap[0](uint16_t*) &heap[2]

我希望在这些值中的第二个值上设置一个观察点,并在达到某个值时中断。在这种情况下,第二个值是一个正在倒计时的计数器,我希望在它达到例如零时中断(但出于我目前的测试目的,我使用 )。9998

这就是我的 C 程序的样子(把它放进去并用test.cgcc -g -o mainh test.c)

#include <stdint.h>
#include <stdlib.h>
#define HEAP_SIZE 65536
char heap[HEAP_SIZE];
void proc0();
void proc1();
void proc0()
{ }
void proc1()
{ }
void main()
{
    *(uint16_t *) &heap[0] = (uint16_t) 4;
    proc0();
    exit(0);
}

我的框架生成了一个 GDB 文件来安装一些断点并修改这两个值,GDB 毫无问题地接受了它们。我遇到的问题是,首先安装的观察点永远不会执行。(将以下命令放入commandsh.txt)

watch *(uint16_t*) &heap[2]
cond 1 *(uint16_t*) &heap[2] == 9998
commands
set *(uint16_t*) &heap[0] = 50
p *(uint16_t*) &heap[0]
continue
end

break proc0
commands
set *(uint16_t*) &heap[2] = (*(uint16_t*) &heap[2]) - 1
c
end

run
q

断点安装在 和 处,但只有一个与我遇到的问题相关,因此省略了其余断点。断点会正确地触发 at 的值,并将值从初始 递减到 。但是,观察点及其条件永远不会触发,使第一个值保持不变,而我希望它是 。(通过从 bash 运行来执行命令)mainexitproc0proc0proc0(uint16_t *) &heap[2]99989999450gdb -q -x commandsh.txt mainh

当我运行 GDB 时,我的输出显示观察点永远不会中断,并且指示的堆地址处的值不会打印:

Reading symbols from mainh...
Hardware watchpoint 1: *(uint16_t*) &heap[2]
Breakpoint 2 at 0x1151: file test.c, line 8.

This GDB supports auto-downloading debuginfo from the following URLs:
https://debuginfod.ubuntu.com 
Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 2, proc0 () at test.c:8
8   { }
[Inferior 1 (process 146113) exited normally]

我怀疑问题与我的语法有关,并试图将观察点更改为

watch {uint16_t} &heap[2]
cond 1 {uint16_t} &heap[2] == 9998
commands
set {uint16_t} &heap[0] = 50
continue
end

但这并没有改变任何事情。我做错了什么?

C Linux 调试 GDB

评论

1赞 Tom 9/15/2023
请提供最小可重复的例子
2赞 Tom 9/15/2023
好的,请稍等片刻。
1赞 Robert 9/15/2023
@lundin这与我的问题完全无关,也不相关。
1赞 Lundin 9/15/2023
@Robert 鉴于该行在 C 语言中没有定义的行为,我看不出它有什么不相关。*(uint16_t *) &heap[0] = (uint16_t) 4;
1赞 ssbssa 9/15/2023
我很确定,只有当监视的表达式在程序中发生变化时才会触发观察点,而不是在 gdb 中更改它们时才会触发。

答:

1赞 Employed Russian 9/16/2023 #1

问题在于,当正在调试的程序更改值时,硬件观察点会起作用。

当它不是程序时,它们不起作用,但 GDB 本身正在执行更改(就像这里发生的那样)。

还有其他类似的“错过观察点”的例子,例如内核写入内存时:

int fd = open("/dev/zero", ...);
char buf = 'a';               // set a watchpoint on location of buf
read(fd, &buf, 1);            // buf is now changed, but watchpoint doesn't "fire".