aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/breakpoint.c130
-rw-r--r--gdb/values.c2
3 files changed, 100 insertions, 45 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 18f51a9..2d12618 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2000-03-20 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * breakpoint.c (insert_breakpoints, remove_breakpoint)
+ (bpstat_stop_status, can_use_hardware_watchpoint): Don't insert,
+ remove, or check status of hardware watchpoints for entire structs
+ and arrays unless the user explicitly asked to watch that struct
+ or array.
+ (insert_breakpoints): Try to insert watchpoints for all the values
+ on the value chain, even if some of them fail to insert.
+
+ * values.c (value_primitive_field): Set the offset in struct value
+ we return when the field is a packed bitfield.
+
2000-03-20 Michael Snyder <msnyder@cleaver.cygnus.com>
* remote.c (remote_threads_extra_info): new function.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2ad3a78..b77a404 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -973,24 +973,39 @@ insert_breakpoints ()
if (VALUE_LVAL (v) == lval_memory
&& ! VALUE_LAZY (v))
{
- CORE_ADDR addr;
- int len, type;
-
- addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- len = TYPE_LENGTH (VALUE_TYPE (v));
- type = hw_write;
- if (b->type == bp_read_watchpoint)
- type = hw_read;
- else if (b->type == bp_access_watchpoint)
- type = hw_access;
-
- val = target_insert_watchpoint (addr, len, type);
- if (val == -1)
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ /* We only watch structs and arrays if user asked
+ for it explicitly, never if they just happen to
+ appear in the middle of some value chain. */
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
{
- b->inserted = 0;
- break;
+ CORE_ADDR addr;
+ int len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = hw_write;
+ if (b->type == bp_read_watchpoint)
+ type = hw_read;
+ else if (b->type == bp_access_watchpoint)
+ type = hw_access;
+
+ val = target_insert_watchpoint (addr, len, type);
+ if (val == -1)
+ {
+ /* Don't exit the loop, try to insert
+ every value on the value chain. That's
+ because we will be removing all the
+ watches below, and removing a
+ watchpoint we didn't insert could have
+ adverse effects. */
+ b->inserted = 0;
+ }
+ val = 0;
}
- val = 0;
}
}
/* Failure to insert a watchpoint on any memory value in the
@@ -1326,21 +1341,28 @@ remove_breakpoint (b, is)
if (VALUE_LVAL (v) == lval_memory
&& ! VALUE_LAZY (v))
{
- CORE_ADDR addr;
- int len, type;
-
- addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- len = TYPE_LENGTH (VALUE_TYPE (v));
- type = hw_write;
- if (b->type == bp_read_watchpoint)
- type = hw_read;
- else if (b->type == bp_access_watchpoint)
- type = hw_access;
-
- val = target_remove_watchpoint (addr, len, type);
- if (val == -1)
- b->inserted = 1;
- val = 0;
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR addr;
+ int len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = hw_write;
+ if (b->type == bp_read_watchpoint)
+ type = hw_read;
+ else if (b->type == bp_access_watchpoint)
+ type = hw_access;
+
+ val = target_remove_watchpoint (addr, len, type);
+ if (val == -1)
+ b->inserted = 1;
+ val = 0;
+ }
}
}
/* Failure to remove any of the hardware watchpoints comes here. */
@@ -2570,14 +2592,21 @@ bpstat_stop_status (pc, not_a_breakpoint)
if (VALUE_LVAL (v) == lval_memory
&& ! VALUE_LAZY (v))
{
- CORE_ADDR vaddr;
-
- vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- /* Exact match not required. Within range is sufficient.
- */
- if (addr >= vaddr &&
- addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
- found = 1;
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr;
+
+ vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ /* Exact match not required. Within range is
+ sufficient. */
+ if (addr >= vaddr &&
+ addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
+ found = 1;
+ }
}
}
if (found)
@@ -5514,6 +5543,7 @@ can_use_hardware_watchpoint (v)
struct value *v;
{
int found_memory_cnt = 0;
+ struct value *head = v;
/* Did the user specifically forbid us to use hardware watchpoints? */
if (!can_use_hw_watchpoints)
@@ -5551,13 +5581,23 @@ can_use_hardware_watchpoint (v)
{
/* Ahh, memory we actually used! Check if we can cover
it with hardware watchpoints. */
- CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- int len = TYPE_LENGTH (VALUE_TYPE (v));
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ /* We only watch structs and arrays if user asked for it
+ explicitly, never if they just happen to appear in a
+ middle of some value chain. */
+ if (v == head
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ int len = TYPE_LENGTH (VALUE_TYPE (v));
- if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
- return 0;
- else
- found_memory_cnt++;
+ if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+ return 0;
+ else
+ found_memory_cnt++;
+ }
}
}
else if (v->lval != not_lval && v->modifiable == 0)
diff --git a/gdb/values.c b/gdb/values.c
index 6f2642e..760d2f8 100644
--- a/gdb/values.c
+++ b/gdb/values.c
@@ -802,6 +802,8 @@ value_primitive_field (arg1, offset, fieldno, arg_type)
fieldno));
VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+ + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
}
else if (fieldno < TYPE_N_BASECLASSES (arg_type))
{