This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
Watching complex expressions patch
I think that the approach of VALUE_LAZY for the watchpoint is completely
wrong !
I propose here a patch that completely change the mecanism of which
memory must be
watched :
if you have a struct t { int a,b,c;}
and you set a watch to t.c
you only want to get stopped if t.c changes not if t.a or t.b changes
but currently using the VALUE_LAZY seems to be quite unsure
On go32 target,
the code wanted to watch first t.c and then this entire t struct and that
is wrong of course !
So my mecanism remembers the last memory that has been set a watch
and after reject all watches of bigger memory regions including that memory !
For more complex watch, with intermediate value that can change
like if p is a pointer to the above struct t
watch p->c
will the watch both current location of t.c (if p is set to &t)
and location of p as it is not inside the memory region of t.c itself !
(Even if you imagine that you have complicated case where the same memory is
fetched several times it still should work correctly !)
Index: breakpoint.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/breakpoint.c,v
retrieving revision 1.1.1.16
diff -b -c -r1.1.1.16 breakpoint.c
*** breakpoint.c 1999/11/02 04:44:13 1.1.1.16
--- breakpoint.c 1999/11/04 10:30:09
***************
*** 951,956 ****
--- 951,959 ----
if (within_current_scope)
{
+ CORE_ADDR last_lval_address = 0;
+ int last_lval_size = 0;
+ int last_type = 0;
/* Evaluate the expression and cut the chain of values
produced off from the value chain.
***************
*** 967,977 ****
/* Look at each value on the value chain. */
for (; v; v = v->next)
{
! /* If it's a memory location, and GDB actually needed
! its contents to evaluate the expression, then we
! must watch it. */
! if (VALUE_LVAL (v) == lval_memory
! && ! VALUE_LAZY (v))
{
CORE_ADDR addr;
int len, type;
--- 970,982 ----
/* Look at each value on the value chain. */
for (; v; v = v->next)
{
! /* If it's a memory location, then we must watch it. */
! if ((VALUE_LVAL (v) == lval_memory) &&
! /* Unless its a bigger part from a small part we want to
! watch */
! !((VALUE_ADDRESS (v) + VALUE_OFFSET (v) <= last_lval_address) &&
! (VALUE_ADDRESS (v) + VALUE_OFFSET (v) + TYPE_LENGTH
(VALUE_TYPE (v))
! >= last_lval_address + last_lval_size)))
{
CORE_ADDR addr;
int len, type;
***************
*** 983,988 ****
--- 988,997 ----
type = hw_read;
else if (b->type == bp_access_watchpoint)
type = hw_access;
+ /* Non terminal are only important if
+ their value changes */
+ if (last_type)
+ type = hw_write;
val = target_insert_watchpoint (addr, len, type);
if (val == -1)
***************
*** 991,996 ****
--- 1000,1008 ----
break;
}
val = 0;
+ last_lval_size = len;
+ last_lval_address = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ last_type = type;
}
}
/* Failure to insert a watchpoint on any memory value in the
***************
*** 1309,1323 ****
&& !b->duplicate)
{
value_ptr v, n;
b->inserted = (is == mark_inserted);
/* Walk down the saved value chain. */
for (v = b->val_chain; v; v = v->next)
{
/* For each memory reference remove the watchpoint
at that address. */
! if (VALUE_LVAL (v) == lval_memory
! && ! VALUE_LAZY (v))
{
CORE_ADDR addr;
int len, type;
--- 1321,1352 ----
&& !b->duplicate)
{
value_ptr v, n;
+ CORE_ADDR last_lval_address = 0;
+ int last_lval_size = 0;
+ int last_type = 0;
b->inserted = (is == mark_inserted);
/* Walk down the saved value chain. */
for (v = b->val_chain; v; v = v->next)
{
/* For each memory reference remove the watchpoint
+ at that address. */
+ /* If it's a memory location, then we must watch it. */
+ if ((VALUE_LVAL (v) == lval_memory) &&
+ /* Unless its a bigger part from a small part we want to
+ watch */
+ !((VALUE_ADDRESS (v) + VALUE_OFFSET (v) <= last_lval_address) &&
+ (VALUE_ADDRESS (v) + VALUE_OFFSET (v) + TYPE_LENGTH
(VALUE_TYPE (v))
+ >= last_lval_address + last_lval_size)))
+ /* For each memory reference remove the watchpoint
at that address. */
! /* If it's a memory location, then we must watch it. */
! if ((VALUE_LVAL (v) == lval_memory) &&
! /* Unless its a bigger part from a small part we want to
! watch */
! !((VALUE_ADDRESS (v) + VALUE_OFFSET (v) <= last_lval_address) &&
! (VALUE_ADDRESS (v) + VALUE_OFFSET (v) + TYPE_LENGTH
(VALUE_TYPE (v))
! >= last_lval_address + last_lval_size)))
{
CORE_ADDR addr;
int len, type;
***************
*** 1329,1339 ****
--- 1358,1373 ----
type = hw_read;
else if (b->type == bp_access_watchpoint)
type = hw_access;
+ if (last_type)
+ type = hw_write;
val = target_remove_watchpoint (addr, len, type);
if (val == -1)
b->inserted = 1;
val = 0;
+ last_lval_size = len;
+ last_lval_address = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ last_type = type;
}
}
/* Failure to remove any of the hardware watchpoints comes here. */
Pierre Muller
Institut Charles Sadron
6,rue Boussingault
F 67083 STRASBOURG CEDEX (France)
mailto:muller@ics.u-strasbg.fr
Phone : (33)-3-88-41-40-07 Fax : (33)-3-88-41-40-99