mathway
mathway

Reputation: 153

Watchpoint doesn't work when reverse executing

Here's a debugging scenario:

  1. Create start breakpoint A and finish breakpoint B.
  2. Start recording. Continue.
  3. Reach breakpoint B.
  4. Set watchpoint to watch writes to some piece of memory.
  5. Reverse continue until watchpoint breaks execution.

Let's suppose that setting the watchpoint is only possible in step 4, not earlier, since the location of memory that should be watched is only known at that point.

Here's a simple example. main.c:

int main(void)
{
    int num;
    num = 5;

    return 0;
}

Debugging session:

$ cc main.c
$ gdb -q -nx -ex 'set disassembly-flavor intel' ./a.out
Reading symbols from ./a.out...
(No debugging symbols found in ./a.out)
(gdb) b *main + 0
Breakpoint 1 at 0x1129
(gdb) disas main
Dump of assembler code for function main:
   0x0000000000001129 <+0>:     push   rbp
   0x000000000000112a <+1>:     mov    rbp,rsp
   0x000000000000112d <+4>:     mov    DWORD PTR [rbp-0x4],0x5
   0x0000000000001134 <+11>:    mov    eax,0x0
   0x0000000000001139 <+16>:    pop    rbp
   0x000000000000113a <+17>:    ret
End of assembler dump.
(gdb) b *main + 16
Breakpoint 2 at 0x1139
(gdb) r
Starting program: /var/tmp/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x0000555555555129 in main ()
(gdb) record
(gdb) c
Continuing.

Breakpoint 2, 0x0000555555555139 in main ()
(gdb) p/x $rbp-0x4
$1 = 0x7fffffffe63c
(gdb) watch *(int*)0x7fffffffe63c
Hardware watchpoint 3: *(int*)0x7fffffffe63c
(gdb) reverse-continue
Continuing.

No more reverse-execution history.
0x0000555555555129 in main ()
(gdb)

The last command shows that reverse execution didn't stop where it is supposed to stop, that is *main+4. Instead, it stopped where the recording has started, ignoring any memory writes.

My simple experiment was motivated by that video at the CppCon 2015, highlighting usefulness of the record & replay concept. Really, I don't know what I've done wrong, because for me it seems that I've repeated every step from the video.

Also, reading gdb docs didn't help either.

So, why the watchpoint has been ignored and how can it be prevented?

Upvotes: 1

Views: 111

Answers (1)

mathway
mathway

Reputation: 153

Try telling gdb to use a software breakpoint instead of the hardware one through the command set can-use-hw-watchpoints 0.

It seems that the hardware watchpoint doesn't work here because when executing back and forth through reverse-execution history, no traditional process execution takes place, it's only gdb changing it's internal memory to make appearance that a program executed backwards.

In other words, we should use hardware watchpoints when the real process executes on a CPU, and software watchpoints when gdb makes an emulation through its recording history.

Thanks to Peter Cordes for the explanation in the comments.

Upvotes: 2

Related Questions