Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Philippe Waroquiers" <philippe.waroquiers@skynet.be>
To: "Pedro Alves" <pedro@codesourcery.com>
Cc: <gdb-patches@sourceware.org>,	<yao@codesourcery.com>
Subject: Re: x86 watchpoints bug (Re: ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver))
Date: Thu, 09 Jun 2011 22:16:00 -0000	[thread overview]
Message-ID: <D646518AEF614784B6A4A9CD3B5B773F@soleil> (raw)
In-Reply-To: <201106090059.42380.pedro@codesourcery.com>

Thanks for the feedback, behaviour looks to be better
when adding the missing assignment. But I suspect I found another
bug in the area of "high level" to "low level" to "hw level" watchpoints.

>> I suspect the problem might be in the following piece of code:
>> static void
>> update_inferior (struct i386_debug_reg_state *inf_state,
>>    struct i386_debug_reg_state *new_state)
>> {
>>   int i;
>> 
>>   ALL_DEBUG_REGISTERS (i)
>>     {
>>       if (new_state->dr_mirror[i] != inf_state->dr_mirror[i]
>>    || (new_state->dr_ref_count[i] != 0
>>        && inf_state->dr_ref_count[i] == 0))
>>  {
>> 
>> The dr_mirror is the address being watched.
>> But if address being watched is 0x0, then a 'busy' register
>> watching 0x0 and a non-busy register will have equal dr_mirror.
>> Then the || condition is bizarre as the ref.count will be updated
>> only if the current inf_state ref.count is 0.
> 
> Not the ref.count.  The address to watch, DR[0-3].

Without the  *inf_state = *new_state,
I had some difficulties to understand the above code.

From what I understand now, the idea of this piece of code
is (only) to change the real value of the hw register.
But if inf_state->dr_mirror properly mirrors the value of the hw
register, then the inequality of the dr_mirror[i] should
be good enough to detect the need to change the hw register.

And if setting the address is only to be done when activating
the watchpoint, then the inequality on the ref count should be
good enough (and the assert new_state->dr_ref_count[i] == 1
should hold when changing the hw addr value).

Well it seems I still have difficulty to understand the code :).

But even if I do not understand the code, after adding 
the *inf_state = *new_state, the behaviour looks better.

>> +# registers were available to cover a single (low level) watchpoint.
> watchpoint.  So the comment was correct if you think of high and
> low level watchpoints like I was thinking.  Maybe you were thinking
> of a high level watchpoint as what the target sees?

Yes, I was interpreting "high level" being a Z2 packet, and "low level"
being the "hw" watchpoint.
Now, I understand that we have:
   high level watchpoints = "user defined watchpoints in gdb" = watched expressions
   low level watchpoints = "memory region watchpoints needed to implement the high level" = Z2 packets
   hw level  watchpoints =  "hw watchpoint(s) needed to implement the low level watchpoint(s)"

Thanks for the clarification


Doing some additional checks, I found something else slightly strange, but it seems
to be wrong at the mapping between "high level watchpoints" and "low level watchpoints".

In the below, you see that 3 identical watchpoints results in 1 single Z2
packet, but disabling the 3 watchpoints gives 3 z2 packets (sent
when the last watchpoint is disabled).
The reason for this assymetry looks not very clear to me, but that might
just be an implementation detail.
I however suspect there is still a bug, as after, when sharing a debug register
between two non-identical watchpoints, we are losing a part of the to be watched
zone : we still have a user level watchpoint of 16 bytes at 0x0, but the hw registers
are only watching 8 bytes at 0x8.
(the below is done with a patched gdb/gdbserver containing the "dr busy" fix
+ the missing assignment + the "set length" patch to allow watching 16 bytes
with gdbserver).
Note that the bug seems also present in native debugging (see native gdb session at the end).



(gdb) tar rem :1234
Remote debugging using :1234
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ffff7de2a60 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) set breakpoint always-inserted  on
(gdb) mo set debug-hw-points 1
H/W point debugging output enabled.
(gdb) watch *(long *) 0x0
Hardware watchpoint 1: *(long *) 0x0
(gdb) watch *(long *) 0x0
Hardware watchpoint 2: *(long *) 0x0
(gdb) watch *(long *) 0x0
Hardware watchpoint 3: *(long *) 0x0
(gdb) dis 1
(gdb) dis 2
(gdb) dis 3
(gdb) enabl
(gdb) watch * (char (*)[16]) 0x0
Hardware watchpoint 4: * (char (*)[16]) 0x0
(gdb) dis 1
(gdb) dis 2
(gdb) dis 3
(gdb) 


Listening on port 1234
Remote debugging from host 127.0.0.1
insert_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00090101          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=1  DR1: addr=0x0, ref.count=0
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00090100          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=0  DR1: addr=0x0, ref.count=0
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00090100          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=0  DR1: addr=0x0, ref.count=0
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00090100          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=0  DR1: addr=0x0, ref.count=0
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
insert_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00090101          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=1  DR1: addr=0x0, ref.count=0
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
insert_watchpoint (addr=0, len=16, type=data-write):
 CONTROL (DR7): 00990105          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=2  DR1: addr=0x8, ref.count=1
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00990105          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=1  DR1: addr=0x8, ref.count=1
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00990104          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=0  DR1: addr=0x8, ref.count=1
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 00990104          STATUS (DR6): 00000000
 DR0: addr=0x0, ref.count=0  DR1: addr=0x8, ref.count=1
 DR2: addr=0x0, ref.count=0  DR3: addr=0x0, ref.count=0



(gdb) watch * (char (*)[16]) 0x0
Hardware watchpoint 6: * (char (*)[16]) 0x0
insert_watchpoint (addr=0, len=16, type=data-write):
 CONTROL (DR7): 0000000000990105          STATUS (DR6): 00000000ffff4ff0
 DR0: addr=0x0000000000000000, ref.count=2  DR1: addr=0x0000000000000008, ref.count=1
 DR2: addr=0x0000000000000000, ref.count=0  DR3: addr=0x0000000000000000, ref.count=0
(gdb) info wat
Num     Type           Disp Enb Address            What
1       hw watchpoint  keep y                      *(long *) 0x0
3       hw watchpoint  keep y                      *(long *) 0x0
4       hw watchpoint  keep y                      *(long *) 0x0
6       hw watchpoint  keep y                      * (char (*)[16]) 0x0
(gdb) dis 1
(gdb) dis 3
(gdb) dis 4
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 0000000000990105          STATUS (DR6): 00000000ffff4ff0
 DR0: addr=0x0000000000000000, ref.count=1  DR1: addr=0x0000000000000008, ref.count=1
 DR2: addr=0x0000000000000000, ref.count=0  DR3: addr=0x0000000000000000, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 0000000000990104          STATUS (DR6): 00000000ffff4ff0
 DR0: addr=0x0000000000000000, ref.count=0  DR1: addr=0x0000000000000008, ref.count=1
 DR2: addr=0x0000000000000000, ref.count=0  DR3: addr=0x0000000000000000, ref.count=0
remove_watchpoint (addr=0, len=8, type=data-write):
 CONTROL (DR7): 0000000000990104          STATUS (DR6): 00000000ffff4ff0
 DR0: addr=0x0000000000000000, ref.count=0  DR1: addr=0x0000000000000008, ref.count=1
 DR2: addr=0x0000000000000000, ref.count=0  DR3: addr=0x0000000000000000, ref.count=0
(gdb) info watch
Num     Type           Disp Enb Address            What
1       hw watchpoint  keep n                      *(long *) 0x0
3       hw watchpoint  keep n                      *(long *) 0x0
4       hw watchpoint  keep n                      *(long *) 0x0
6       hw watchpoint  keep y                      * (char (*)[16]) 0x0
(gdb) 


  reply	other threads:[~2011-06-09 22:16 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-21 22:20 ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver) Philippe Waroquiers
2011-05-26 19:02 ` Tom Tromey
2011-05-29 13:01   ` Philippe Waroquiers
2011-05-30 15:26     ` Joel Brobecker
2011-05-31 19:07     ` x86 watchpoints bug (Re: ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver)) Pedro Alves
2011-05-31 20:25       ` Philippe Waroquiers
2011-05-31 20:53         ` Pedro Alves
2011-05-31 21:29       ` Pedro Alves
2011-05-31 22:15         ` Philippe Waroquiers
2011-05-31 23:04           ` Pedro Alves
2011-06-01 14:35             ` Pedro Alves
2011-06-08 22:55               ` Philippe Waroquiers
2011-06-09  0:00                 ` Pedro Alves
2011-06-09 22:16                   ` Philippe Waroquiers [this message]
2011-07-21 17:20                     ` Pedro Alves
2011-07-22 16:40                       ` Philippe Waroquiers
2011-07-22 16:43                         ` Pedro Alves
2011-07-23 16:28                           ` Thiago Jung Bauermann
2011-07-26 20:02                             ` software watchpoints bug (was: Re: x86 watchpoints bug) Pedro Alves
2011-07-27  3:45                               ` Thiago Jung Bauermann
2011-07-22 17:19                         ` x86 watchpoints bug (Re: ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver)) Pedro Alves
2011-05-27  3:25 ` ping: Re: PATCH : allow to set length of hw watchpoints (e.g. for Valgrind gdbserver) Yao Qi
2011-05-27 17:53   ` Tom Tromey
2011-05-27 17:59     ` Pedro Alves
2011-05-30  4:06       ` Yao Qi
2011-05-30  5:34         ` Philippe Waroquiers
2011-05-30  5:48           ` Yao Qi
2011-05-30  6:31             ` Philippe Waroquiers
2011-05-31 17:31         ` Pedro Alves
2011-05-31 18:06           ` Philippe Waroquiers
2011-06-01 15:15             ` Pedro Alves
2011-06-05 20:55               ` Philippe Waroquiers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=D646518AEF614784B6A4A9CD3B5B773F@soleil \
    --to=philippe.waroquiers@skynet.be \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@codesourcery.com \
    --cc=yao@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox