Re: x86 watchpoints bug (Re: ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver))

Philippe Waroquiers
2011-05-31T22:15:33Z

> +gdb_test_no_output "set breakpoint always-inserted on"

I confirm that the bug of the DR register kept busy is also present
on a native GDB debugging.

Note the bug is slightly more difficult to trigger without
the "set breakpoint always-inserted on"
as it seems to depend on the order in which watchpoints are inserted.

If you just do:
break s.c:24
run
watch s1
watch s2
watch s4
watch s3
c
you do not trigger the busy bug as gdb inserts them
in the order : s3
s4
s1
s2
and then there is no busy register remaining.

I was able to trigger the bug with the following sequence: s1 s2 s4 s16 (that gdb inserts
in the order s4 s1 s2 s16. See below the full trace of the bug with this order.

Note that it would be less user confusing if gdb would always insert the watchpoints in the
order the user entered them. No idea if this is easy to do.
Of course, the confusion only happens with limited hw watchpoint (with Valgrind gdbserver,
there will be no confusion :).
E.g. this is what you can obtain on amd64 with the Valgrind gdbserver (and the patched gdb
allowing unlimited length):
(gdb) info watch
Num Type Disp Enb Address What
1 hw watchpoint keep y s1
2 hw watchpoint keep y s2
3 hw watchpoint keep y s3
4 hw watchpoint keep y s4
5 hw watchpoint keep y s5
6 hw watchpoint keep y s6
7 hw watchpoint keep y s7
8 hw watchpoint keep y s8
9 hw watchpoint keep y s16
10 hw watchpoint keep y s32
11 hw watchpoint keep y s64
12 hw watchpoint keep y s128
13 hw watchpoint keep y s1000
breakpoint already hit 1 time
(gdb)
(the above is an advertisement for the Valgrind gdbserver + patched gdb to allow unlimited length :)

Philippe

########################## bug without always-inserted, using s1 s2 s4 s16
...
stopped_data_addr:
CONTROL (DR7): 0000000000000000 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000000000, ref.count=0 DR1: addr=0x0000000000000000, ref.count=0
DR2: addr=0x0000000000000000, ref.count=0 DR3: addr=0x0000000000000000, ref.count=0

Breakpoint 1, main () at s.c:24
24 p[i] = 1;
(gdb) watch s1
Hardware watchpoint 2: s1
(gdb) watch s2
Hardware watchpoint 3: s2
(gdb) watch s4
Hardware watchpoint 4: s4
(gdb) watch s16
Hardware watchpoint 5: s16
(gdb) c
Continuing.
stopped_data_addr:
CONTROL (DR7): 0000000000000000 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000000000, ref.count=0 DR1: addr=0x0000000000000000, ref.count=0
DR2: addr=0x0000000000000000, ref.count=0 DR3: addr=0x0000000000000000, ref.count=0
insert_watchpoint (addr=606ac0, len=4, type=data-write):
CONTROL (DR7): 00000000000d0101 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000606ac0, ref.count=1 DR1: addr=0x0000000000000000, ref.count=0
DR2: addr=0x0000000000000000, ref.count=0 DR3: addr=0x0000000000000000, ref.count=0
insert_watchpoint (addr=609248, len=1, type=data-write):
CONTROL (DR7): 00000000001d0105 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000606ac0, ref.count=1 DR1: addr=0x0000000000609248, ref.count=1
DR2: addr=0x0000000000000000, ref.count=0 DR3: addr=0x0000000000000000, ref.count=0
insert_watchpoint (addr=60d128, len=2, type=data-write):
CONTROL (DR7): 00000000051d0115 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000606ac0, ref.count=1 DR1: addr=0x0000000000609248, ref.count=1
DR2: addr=0x000000000060d128, ref.count=1 DR3: addr=0x0000000000000000, ref.count=0
insert_watchpoint (addr=60d1c0, len=16, type=data-write):
CONTROL (DR7): 00000000951d0155 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000606ac0, ref.count=1 DR1: addr=0x0000000000609248, ref.count=1
DR2: addr=0x000000000060d128, ref.count=1 DR3: addr=0x000000000060d1c0, ref.count=1
Warning:
Could not insert hardware watchpoint 5.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

remove_watchpoint (addr=606ac0, len=4, type=data-write):
CONTROL (DR7): 00000000951d0154 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000000000, ref.count=0 DR1: addr=0x0000000000609248, ref.count=1
DR2: addr=0x000000000060d128, ref.count=1 DR3: addr=0x000000000060d1c0, ref.count=1
remove_watchpoint (addr=609248, len=1, type=data-write):
CONTROL (DR7): 00000000951d0150 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000000000, ref.count=0 DR1: addr=0x0000000000000000, ref.count=0
DR2: addr=0x000000000060d128, ref.count=1 DR3: addr=0x000000000060d1c0, ref.count=1
remove_watchpoint (addr=60d128, len=2, type=data-write):
CONTROL (DR7): 00000000951d0140 STATUS (DR6): 00000000ffff4ff0
DR0: addr=0x0000000000000000, ref.count=0 DR1: addr=0x0000000000000000, ref.count=0
DR2: addr=0x0000000000000000, ref.count=0 DR3: addr=0x000000000060d1c0, ref.count=1
0x0000000000400494 in main () at s.c:24
24 p[i] = 1;
(gdb)