如何为每个具有该类型的结构变量观察结构的成员?

时间:2011-04-05 19:45:40

标签: gdb

我正在腐蚀一个struct成员,其中struct用于构建一个 大树。我试图设置一个观察点,但“变量”有 各种名称(我见过的所有例子都使用显式全局变量, 所以不要显示我正在寻找的例子。

(gdb) watch *(OP*)->op.sibling
A syntax error in expression, near `->op.sibling'.
(gdb) watch *(struct op*)->op.sibling
A syntax error in expression, near `->op.sibling'.
(gdb) watch (struct op*)->op.sibling
A syntax error in expression, near `->op.sibling'.

最接近我接受的语法不起作用

(gdb) watch (struct op*)o->op.sibling
No symbol "o" in current context.

是否有一个表达形式,我错过了它将是独立的 变量名称,并注意其特定的事实 那种结构?

这是否能够检测到结构的memset覆盖? (即使不是,它会帮助我排除某些原因)

是否有超出基本用法的gdb引用? (对于某些“基本”的定义)

2 个答案:

答案 0 :(得分:13)

正如ninjalj所说,你必须有一个地址值得关注;这就是观察点的重点。请考虑以下示例:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct node {
  long value;
  struct node *next;
} node;

node *build_node(int x, node *next)
{
  node *n = malloc(sizeof(*n));
  n->value = x;
  n->next = next;
  return n;
}

int main()
{
  node *n = build_node(1, NULL);
  n = build_node(2, n);
  n = build_node(3, n);

  memset(&n->next->value, 0xFF, sizeof(long) + 3);  // corrupt the list

  return 0;
}

这里我生成一个整数列表,然后将其破坏。让我们看看GDB中的情况:

gdb -q ./a.out
Reading symbols for shared libraries .. done
(gdb) b main
Breakpoint 1 at 0x100000e0c: file foo.c, line 20.
(gdb) r
Starting program: /tmp/a.out 
Reading symbols for shared libraries +. done

Breakpoint 1, main () at foo.c:20
20    node *n = build_node(1, NULL);

(gdb) b 26
Breakpoint 2 at 0x100000e8d: file foo.c, line 26.
(gdb) c
Continuing.

Breakpoint 2, main () at foo.c:26
26    return 0;
(gdb) p *n
$1 = {
  value = 3, 
  next = 0x100100090
}
(gdb) p *n.next
$2 = {
  value = -1, 
  next = 0x100ffffff
}

我们清楚地看到n->next已彻底损坏。假设我们不知道发生了什么,并希望通过GDB观察点找到。

首先,我们需要建立已损坏的地址:

(gdb) print &n.next.value
$3 = (long int *) 0x100100090
(gdb) watch *$3
Hardware watchpoint 3: *$3

这里我只是在地址0x100100090上设置一个8字节的观察点。

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /private/tmp/a.out 
warning: Could not set watchpoint 3
warning: Could not set watchpoint 3

Breakpoint 1, main () at foo.c:20
20    node *n = build_node(1, NULL);

我使用的是旧版本的GDB,它不了解如何在程序重启期间正确禁用和重新启用硬件观察点。如果您使用的是更新版本,则可能看不到上述警告。当我在断点1停止时,我可以简单地重新启用观察点:

(gdb) enable 3
(gdb) c
Continuing.
Hardware watchpoint 3: *$3

Old value = 0
New value = 2
build_node (x=2, next=0x100100080) at foo.c:14
14    n->next = next;

好的,我们已达到预期的点数和预期值。下一次修改会破坏它,我们想知道发生了什么。

(gdb) c
Continuing.
Hardware watchpoint 3: *$3

Old value = 2
New value = 255
0x00007fff82fae450 in memset ()
(gdb) bt
#0  0x00007fff82fae450 in memset ()
#1  0x0000000100000ebe in __inline_memset_chk (__dest=0x100100090, __val=255, __len=11) at _string.h:80
#2  0x0000000100000e8d in main () at foo.c:24

Voilà,您现在知道意外修改的来源。

答案 1 :(得分:1)

你怎么期望这个工作? gdb观察点转换为适当的硬件调试观察点,即它们是内存地址。因此,它们的目的是覆盖内存区域,而不是数据类型。