观察点固定地址

问题描述 投票:0回答:2

对于我当前的嵌入式应用程序,我尝试将 GDB 观察点放在固定的内存地址。

作为示例,我的应用程序更新以下地址:0x10793ad0。为了确定代码的哪一部分破坏了值,我尝试了

watch 0x10793ad0

即使 GDB 在此之后不会打印任何错误,但它也无法在执行过程中中断,即使我验证了该值在执行开始和结束之间进行了修改。

问题:

  1. 我真的可以把手表放在固定地址吗?我在网上没有遇到过这样的例子。
  2. 这是正确的方法还是我错过了什么?
debugging gdb watchpoint
2个回答
117
投票

在地址上设置观察点的正确方法是watch *0x10793ad0。请参阅gdb 文档


0
投票

-l/-location
示例

在这个答案中,我想进一步强调 Nathan Kidd 在评论中提到的

-l/-location
选项。 如果您不使用此选项,则执行以下操作:

watch mylocalvar

一旦 
mylocalvar

超出范围,GDB 就会中断,并自动删除该内存观察点。

因此,当您知道某个值只有一个实例通过引用传递时(通常是类似于 
-l

this

),
struct
会非常有用。
考虑:

main.c

typedef struct { int i; } MyThing; void MyThing_init(MyThing *s, int i) { i += 1; s->i = i; i += 2; i += 3; } int MyThing_get_i(MyThing *s) { return s->i; } int main(void) { MyThing s; MyThing_init(&s, 1); MyThing_init(&s, 2); MyThing_init(&s, 3); MyThing_init(&s, 4); return MyThing_get_i(&s); }

编译和调试:

gcc -ggdb3 -O0 -o main.out main.c gdb -nh -ex 'tb MyThing_init' -ex r main.out

此页位于:

6 i += 1;

现在如果我们这样做:

watch s->i

它显示在:

(gdb) i b Num Type Disp Enb Address What 2 hw watchpoint keep y s->i

然后第一个 
c

在根据需要修改变量后停止:

(gdb) c
Continuing.

Hardware watchpoint 2: s->i

Old value = 0
New value = 2
MyThing_init (s=0x7fffffffccb4, i=2) at main.c:8
8           i += 2;

但是当 
c

返回时第二个

MyThing_init
停止并向我们解释它删除了观察点:
(gdb) c
Continuing.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
main () at main.c:19
19          MyThing_init(&s, 2);

我们可以通过以下方式确认:

(gdb) i b No breakpoints or watchpoints.

因此再次使用 
c

运行程序将一直运行直到退出。

但是如果我们改用 

-l

:

watch -l s->i

i b

下显示为:

(gdb) i b
Num     Type           Disp Enb Address            What
2       hw watchpoint  keep y                      -location s->i

那么观察点不会被删除,并且我们每次调用都会中断:

(gdb) c Continuing. Hardware watchpoint 2: -location s->i Old value = 2 New value = 3 MyThing_init (s=0x7fffffffccb4, i=3) at main.c:8 8 i += 2; (gdb) c Continuing. Hardware watchpoint 2: -location s->i Old value = 3 New value = 4 MyThing_init (s=0x7fffffffccb4, i=4) at main.c:8 8 i += 2; (gdb) c Continuing. Hardware watchpoint 2: -location s->i Old value = 4 New value = 5 MyThing_init (s=0x7fffffffccb4, i=5) at main.c:8 8 i += 2; (gdb) c Continuing. Hardware watchpoint 2: -location s->i Old value = 5 New value = 32767 0x00007ffff7c44fd6 in __run_exit_handlers (status=5, listp=0x7ffff7dfe860 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:43 43 ./stdlib/exit.c: No such file or directory.

此技术与 
Mozilla rr 反向调试

结合使用时特别强大,因为通常会发生的情况是您处于失败点,例如: b MyThing_get_i

并且您注意到某事物的错误值,例如 
s->i

,然后您想知道设置该错误值的最后一件事是什么。一旦进入

rr
,您可以立即回答:
watch -l s->i
rc

在 Ubuntu 23.10、GCC 13.2.0 上测试。 GDB 14.

© www.soinside.com 2019 - 2024. All rights reserved.