Re: [ppc-linux-nat]: set access flag for h/w watchpoint even if it is only read or write

Eli Zaretskii
2006-07-07T10:04:49Z

> Date: Fri, 7 Jul 2006 00:35:21 -0400
> From: Wu Zhou <woodzltc@cn.ibm.com>
> Cc: gdb-patches@sourceware.org
>
> Just as Daniel said, my problem is not the same as yours. given the
> following code:
>
> int var1 = 0, var2;
> var1 = 10;
> var2 = var1;
>
> if we set read watchpoint on var1, it should stop at "var2 = var1", but
> gdb are using "watchpoint_check" to see if the watched variable are
> changed or not, if it is changed, then it assumes the watched variable is
> writed; if not, it assumes the watched variable is read.
>
> Because when execution get to "var1=10", it won't trigger a watchpoint,
> the old value stored in var1 is still 0, so watchpoint_check will get a
> wrong conclusion that var1 is changed to 10 by this instruction. So it
> won't treat it as a read watchpoint hit.

This doesn't happen on x86, with this test program:

#include <stdio.h>

int main (void)
{
int var1 = 0, var2;
var1 = 10;
var2 = var1;

printf ("%d %d\n", var1, var2);
return 0;
}

I think the reason it works for me is that on x86, there's no real
support for read watchpoints, so we actually set a read-write
watchpoint, and then the logic of watchpoint_check does TRT.

What is the situation with this on a PPC? What kinds of data
breakpoints does it support, and what associated functionality can we
use in the ptrace call or its PPC equivalent?

> My solution is to let gdb update the value stored in the watched variable,
> so that it always get the fresh value for comparison.

That will work, but the question is: is this the optimal solution for
the PPC? Maybe there's a better solution, one that doesn't slow down
the normal case.

> Another solution might be to change the verify logic of read watchpoint
> hit in watchpoint_check. Maybe we can just trust the underlying os will
> only trigger in read hit?

The question is, how to do that without breaking other platforms, like
x86, which we cannot trust. If you can come up with a design that
accommodates both types of situations, I will be happy to review it.

Daniel, could you please point me to Ulrich's change, either in
ChangeLogs or in the sources? I cannot find it forf some reason.

> Comparing all these solution, my solution is the most simple one. I mean,
> it makes little change to the current code. To address the slowdown, we
> can still use the original flags for write hit.
>
> What is your idea on this?

I think the cleanest solution is for breakpoint.c to get the idea of
the kind of support it can get from the target. If the target
implements real read watchpoints, it should propagate that knowledge
to breakpoint.c, where it examines the watchpoints and decides which
one to announce.

Please note that there are complications in this area: a user could
have legitimately set several different watchpoints on the same
address, each one with its own type (read, write, access) and its own
set of conditions and/or commands. Whatever new design we come up
with, it has to support these complicated situations, because the user
will expect GDB to announce only those watchpoints which meet the
conditions and type constraints. For example, what happens with your
solution if I put both read and write watchpoints on the same
variable? The current code does TRT on x86 in that case. As you see
below, it correctly announces each one of the two watchpoints where
expected (except for a slight off-by-one shift in line numbers):

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) start
Breakpoint 1 at 0x4012b5: file wpt.c, line 4.
Starting program: D:\usr\eli\data/./wpt.exe
main () at wpt.c:4
4 {
(gdb) watch var1
Hardware watchpoint 2: var1
(gdb) rwatch var1
Hardware read watchpoint 3: var1
(gdb) c
Continuing.
Hardware watchpoint 2: var1

Old value = 2
New value = 0
main () at wpt.c:6
6 var1 = 10;
(gdb)
Continuing.
Hardware watchpoint 2: var1

Old value = 0
New value = 10
main () at wpt.c:7
7 var2 = var1;
(gdb)
Continuing.
Hardware read watchpoint 3: var1

Value = 10
0x004012cb in main () at wpt.c:7
7 var2 = var1;
(gdb)
Continuing.
Hardware read watchpoint 3: var1

Value = 10
0x004012d8 in main () at wpt.c:9
9 printf ("%d %d\n", var1, var2);
(gdb)
Continuing.
10 10

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.