Reputation: 153
Here's a debugging scenario:
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
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