This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: read watchpoints ignored?


> 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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]