public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
From: Eli Zaretskii <eliz@gnu.org>
To: Vladimir Prus <ghost@cs.msu.su>
Cc: gdb@sources.redhat.com
Subject: Re: read watchpoints ignored?
Date: Fri, 11 Nov 2005 18:19:00 -0000	[thread overview]
Message-ID: <uk6ff2gjm.fsf@gnu.org> (raw)
In-Reply-To: <200511111622.01337.ghost@cs.msu.su> (message from Vladimir Prus on Fri, 11 Nov 2005 16:22:00 +0300)

> From: Vladimir Prus <ghost@cs.msu.su>
> Date: Fri, 11 Nov 2005 16:22:00 +0300
> 
>     (gdb) b main
>     Breakpoint 1 at 0x80483a4: file rw.cpp, line 8.
>     (gdb) r
>     Starting program: /tmp/a.out
> 
>     Breakpoint 1, main () at rw.cpp:8
>     8           a = 10;
>     (gdb) rwatch a
>     Hardware read watchpoint 2: a
>     (gdb) c
>     Continuing.
>     Hardware read watchpoint 2: a
> 
>     Value = 10
>     0x080483bd in main () at rw.cpp:11
>     11          c = a;
> 
> Expected result: gdb stops on "b = a" line.
> Actual result: gdb stops on "c = a".

On what platform was that, and with which version of GDB?  Also, what
debug info format was used by the compiler in your case, and what
compiler switches were used to compile and link the program?

I will assume that this is on some x86 platform; if not, the rest of
this message might not be useful.

First, I cannot reproduce this problem with the MS-Windows port of
GCC; the session transcript I saw is at the end of this message.

On Debian GNU/Linux, I can reproduce the problem, but it seems that it
is a side effect of another problem: the breakpoint set by "b main"
stops the program too late.  Observe:

  ~$ gdb ./rwt
  GNU gdb 6.1-debian
  Copyright 2004 Free Software Foundation, Inc.
  GDB is free software, covered by the GNU General Public License, and you are
  welcome to change it and/or distribute copies of it under certain conditions.
  Type "show copying" to see the conditions.
  There is absolutely no warranty for GDB.  Type "show warranty" for details.
  This GDB was configured as "i386-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
  (gdb) info address main
  Symbol "main" is a function at address 0x8048364.
  (gdb) b *0x8048364
  Breakpoint 1 at 0x8048364: file rwt.c, line 6.
  (gdb) r
  Starting program: /home/e/eliz/rwt

  Breakpoint 1, main () at rwt.c:6
  6       {
  (gdb) rwatch a
  Hardware read watchpoint 2: a
  (gdb) c
  Continuing.
  Here I am
  Hardware read watchpoint 2: a

  Value = 10
  0x0804838f in main () at rwt.c:10
  10         b = a;
  (gdb) c
  Continuing.
  Hardware read watchpoint 2: a

  Value = 10
  0x08048399 in main () at rwt.c:11
  11         c = a;

Note that a breakpoint set by address now stops the program at the
right place: the opening brace of the main function.  In your session
(and also here, if I use "b main"), it stopped on line 7, not line 6.

Can someone please tell why "b main" stops the program one line too
late?

So I'm guessing that the problem happens because GDB misses the data
write into a in line 7, and thus doesn't take notice that a was
assigned the value 10.  That's why it gets confused when "b = a;"
reads from a.

> Here's why it happens. When breakpoint is set, gdb reads the current value
> of 'a', which is zero. After continue, a is assigned the value of '10', and
> then first read watchpoint fires (on "b = a"). We arrive to
> "bpstat_stop_status" (breakpoint.c), which has the following code:
> 
> 
>   else if (b->type == bp_read_watchpoint || 
>              b->type == bp_access_watchpoint)
>       {
>         ...
>         if (found)
>           {
>             ...
>             int e = catch_errors (watchpoint_check, bs, message,
>                                   RETURN_MASK_ALL);
>             switch (e)
>               {
>               .......
>               case WP_VALUE_CHANGED:
>                 if (b->type == bp_read_watchpoint)
>                   {
>                     /* Don't stop: read watchpoints shouldn't fire if
>                        the value has changed.  This is for targets
>                        which cannot set read-only watchpoints.  */
>                     bs->print_it = print_it_noop;
>                     bs->stop = 0;
>                     continue;
>                   }
> 
> 
> Since value of 'a' was changed by the "a = 10" line, "watchpoint_check"
> returns "WP_VALUE_CHANGED", and reporting of watchpoint is completely
> suppressed.
> 
> Questions:
> 1. Is this a bug?

No, I don't think so.  The theory behind the read watchpoint support
on x86 is that GDB should also see the data writes into the watched
variable, and thus always track its current value.  This is because
x86 debug hardware doesn't support read watchpoints, it only supports
data-write watchpoints and access (read or write) watchpoints.  So GDB
_emulates_ read watchpoints on x86 by setting an access watchpoint,
and monitoring value changes with the code you presented above.
Access watchpoint should trigger when the address is written by the
"a = 10;" line, at which point GDB should get control, record the new
value, then continue the debuggee without announcing the watchpoint
(since the value changed).  Later, when "b = a;" reads from a, the
access watchpoint fires again, but this time the value didn't change,
so the watchpoint should be announced.

Can you see which part of the above doesn't work, and why?

> 2. Can this bug be fixed by removing this inner
> 
>       if (b->type == bp_read_wathcpoint)
> 
>    statement?

I hope the description above explains why not.

>    This will cause watchpoints to trigger more often
>    on those target that don't have "read-only watchpoints", but 
>    there will be no risk of missing watchpoint.

Not only does it cause extra read watchpoints, it wreaks a complete
havoc in all but the most simple situations.  For example, consider
the case that two or more watchpoints are set on the same address,
each one with a different condition.  Without the above code, read
watchpoints are unusable on x86, and, worse, any use of read
watchpoints completely disrupts all other hardware watchpoints,
because the facilities used by GDB to find out which watchpoints fired
are very limited, so it gets completely confused when more than one
watchpoint seems to fire.

>    And I think missed
>    watchpoint is more harm then spurious watchpoint.

Both of these harmful, so we should fix this problem.  But not at a
price of going back to the mess we had back before this condition was
added; that's a price which is too heavy, IMO.

Here's the GDB session on MS-Windows.  As you see, "b main" stops at
line 6, the opening brace of the main function, and then the
watchpoint works as you expected.

  D:\usr\eli>gdb ./rwt.exe
  GNU gdb 6.3
  Copyright 2004 Free Software Foundation, Inc.
  GDB is free software, covered by the GNU General Public License, and you are
  welcome to change it and/or distribute copies of it under certain conditions.
  Type "show copying" to see the conditions.
  There is absolutely no warranty for GDB.  Type "show warranty" for details.
  This GDB was configured as "i686-pc-mingw32"...
  (gdb) b main
  Breakpoint 1 at 0x4012b5: file rwt.c, line 6.
  (gdb) r
  Starting program: D:\usr\eli/./rwt.exe

  Breakpoint 1, main () at rwt.c:6
  6       {
  (gdb) rwatch a
  Hardware read watchpoint 2: a
  (gdb) c
  Continuing.
  Here I am
  Hardware read watchpoint 2: a

  Value = 10
  0x004012d5 in main () at rwt.c:10
  10         b = a;
  (gdb) c
  Continuing.
  Hardware read watchpoint 2: a

  Value = 10
  0x004012df in main () at rwt.c:11
  11         c = a;
  (gdb)

  reply	other threads:[~2005-11-11 18:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-11 13:22 Vladimir Prus
2005-11-11 18:19 ` Eli Zaretskii [this message]
2005-11-13 16:45   ` Daniel Jacobowitz
2005-11-13 22:38     ` Eli Zaretskii
2005-11-14  2:43       ` Daniel Jacobowitz
2005-11-14  4:38         ` Eli Zaretskii
2005-11-14 14:42           ` Daniel Jacobowitz
2005-11-15  4:02             ` Eli Zaretskii
2005-11-14 10:10         ` Vladimir Prus
2005-11-14 14:41           ` Daniel Jacobowitz
2005-11-14 14:45             ` Daniel Jacobowitz
2005-11-15  4:02               ` Eli Zaretskii
2005-11-14 13:16         ` Johan Rydberg
2005-11-14 13:42           ` Vladimir Prus
2005-11-14 13:59             ` Johan Rydberg
2005-11-14 14:10               ` Vladimir Prus
2005-11-15  4:01             ` Eli Zaretskii

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=uk6ff2gjm.fsf@gnu.org \
    --to=eliz@gnu.org \
    --cc=gdb@sources.redhat.com \
    --cc=ghost@cs.msu.su \
    /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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).