0

I have a variable getting corrupted. I want to see where this is happening, so a watchpoint is the obvious choice, except this variable frequently gets set (in this case, processing network packets and it gets set once for each packet). I would like to exempt the watchpoint from the location where the variable is supposed to get written. Basically, what I would like is "watch variable if line_number != x"; the gdb docs seem to be a bit thin on the conditional expressions, so I'm not sure this is possible...

abatie
  • 169
  • 3
  • 10

1 Answers1

1

There are a couple of ways to do this, in the following source file.

struct stuff {
  int watched;
};

void dont_hit(struct stuff *foo) {
  begin:
   for (int i = 0; i < 100; i++)
      foo->watched = i;
  end:
   return;
}

void hit(struct stuff *foo) {
  foo->watched = 1024;
}

int main()
{
  struct stuff foo;

  setup:
    dont_hit(&foo);
    hit(&foo);
    dont_hit(&foo);
}

We can then use the watchpoint condition: if $pc != ... as shown below:

(gdb) break main
(gdb) r
(gdb) watch foo.watched
(gdb) c
Hardware watchpoint 2: foo.watched

Old value = -8320
New value = 0
dont_hit (foo=0x7fffffffde90) at main.c:7
7      for (int i = 0; i < 100; i++)
(gdb) p $pc
$1 = (void (*)()) 0x4004c0 <dont_hit+26>
(gdb) watch -location foo->watched if $pc != 0x4004c0
ardware watchpoint 3: -location foo->watched
(gdb) delete 2
(gdb) c
Continuing.

Hardware watchpoint 3: -location foo->watched

Old value = 99
New value = 1024
hit (foo=0x7fffffffde90) at main.c:15

Another way is to use breakpoints to enable/disable the watchpoint in places we don't want it to trigger, I'm using the label's here setup/begin/end for clarity, but you can replace main:label with filename:line_number

break main:setup
run
watch -location foo.watched
break dont_hit:begin
commands
  silent
  disable 2
  cont
end

break dont_hit:end
commands
  silent
  enable 2
  cont
end

A third way, is going to use Python, and FinishBreakpoints to do the enabling/disabling.

matt
  • 5,364
  • 1
  • 25
  • 25
  • I tried "watch orig_pktlen if $_ != 0x8049831" (address being the address it was at when the watchpoint tripped) and it ran for a while then gave: Recursive internal problem. Aborted (core dumped) – abatie Apr 21 '17 at 19:52
  • Same result using $pc instead of $_ – abatie Apr 21 '17 at 20:58
  • That's indicative of some bad problem in gdb. Hard to say what without a reproducer. Anyway this was a good answer and this technique does work. – Tom Tromey Apr 21 '17 at 21:20