aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2013-08-02 16:41:08 +0000
committerTom Tromey <tromey@redhat.com>2013-08-02 16:41:08 +0000
commit3a1115a0cc0a0a98555ba99df76ad9bcfee08759 (patch)
tree7bd5d53c3fa5d8723edfa7193d43c3ec43f9d932 /gdb
parent58b19776a6713e101fb71fab79ea70fa9af19e3a (diff)
downloadgdb-3a1115a0cc0a0a98555ba99df76ad9bcfee08759.zip
gdb-3a1115a0cc0a0a98555ba99df76ad9bcfee08759.tar.gz
gdb-3a1115a0cc0a0a98555ba99df76ad9bcfee08759.tar.bz2
fix PR symtab/15719
This patch fixes PR symtab/15719. The bug is that "watch -location" crashes on a certain expression. The problem is that fetch_subexp_value is catching an exception. For ordinary watchpoints this is ok; but for location watchpoints, it is better for the exception to propagate. Built and regtested on x86-64 Fedora 18. New test case included. PR symtab/15719: * breakpoint.c (update_watchpoint, watchpoint_check) (watch_command_1): Update. * eval.c (fetch_subexp_value): Add "preserve_errors" parameter. * ppc-linux-nat.c (check_condition): Update. * value.h (fetch_subexp_value): Update. * gdb.base/watchpoint.c (struct foo5): New. (nullptr): New global. * gdb.base/watchpoint.exp (test_watch_location): Add test.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog10
-rw-r--r--gdb/breakpoint.c6
-rw-r--r--gdb/eval.c18
-rw-r--r--gdb/ppc-linux-nat.c4
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.base/watchpoint.c7
-rw-r--r--gdb/testsuite/gdb.base/watchpoint.exp3
-rw-r--r--gdb/value.h3
8 files changed, 44 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4e39273..af34dec 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2013-08-02 Tom Tromey <tromey@redhat.com>
+
+ PR symtab/15719:
+ * breakpoint.c (update_watchpoint, watchpoint_check)
+ (watch_command_1): Update.
+ * eval.c (fetch_subexp_value): Add "preserve_errors"
+ parameter.
+ * ppc-linux-nat.c (check_condition): Update.
+ * value.h (fetch_subexp_value): Update.
+
2013-08-02 Andrew Burgess <aburgess@broadcom.com>
* mi/mi-interp.c (mi_interpreter_resume): Remove call to
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1e89407..eec7b7c 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1807,7 +1807,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
struct value *val_chain, *v, *result, *next;
struct program_space *frame_pspace;
- fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain);
+ fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
@@ -4822,7 +4822,7 @@ watchpoint_check (void *p)
return WP_VALUE_CHANGED;
mark = value_mark ();
- fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL);
+ fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0);
/* We use value_equal_contents instead of value_equal because
the latter coerces an array to a pointer, thus comparing just
@@ -11010,7 +11010,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
exp_valid_block = innermost_block;
mark = value_mark ();
- fetch_subexp_value (exp, &pc, &val, &result, NULL);
+ fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location);
if (just_location)
{
diff --git a/gdb/eval.c b/gdb/eval.c
index 539489f..e83bfdf 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -171,10 +171,12 @@ evaluate_subexpression_type (struct expression *exp, int subexp)
in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does
not need them.
- If a memory error occurs while evaluating the expression, *RESULTP will
- be set to NULL. *RESULTP may be a lazy value, if the result could
- not be read from memory. It is used to determine whether a value
- is user-specified (we should watch the whole value) or intermediate
+ If PRESERVE_ERRORS is true, then exceptions are passed through.
+ Otherwise, if PRESERVE_ERRORS is false, then if a memory error
+ occurs while evaluating the expression, *RESULTP will be set to
+ NULL. *RESULTP may be a lazy value, if the result could not be
+ read from memory. It is used to determine whether a value is
+ user-specified (we should watch the whole value) or intermediate
(we should watch only the bit used to locate the final value).
If the final value, or any intermediate value, could not be read
@@ -189,7 +191,8 @@ evaluate_subexpression_type (struct expression *exp, int subexp)
void
fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
- struct value **resultp, struct value **val_chain)
+ struct value **resultp, struct value **val_chain,
+ int preserve_errors)
{
struct value *mark, *new_mark, *result;
volatile struct gdb_exception ex;
@@ -210,13 +213,14 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
}
if (ex.reason < 0)
{
- /* Ignore memory errors, we want watchpoints pointing at
+ /* Ignore memory errors if we want watchpoints pointing at
inaccessible memory to still be created; otherwise, throw the
error to some higher catcher. */
switch (ex.error)
{
case MEMORY_ERROR:
- break;
+ if (!preserve_errors)
+ break;
default:
throw_exception (ex);
break;
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 1f3f080..c518f77 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1952,7 +1952,7 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
if (cond->elts[0].opcode != BINOP_EQUAL)
return 0;
- fetch_subexp_value (cond, &pc, &left_val, NULL, &left_chain);
+ fetch_subexp_value (cond, &pc, &left_val, NULL, &left_chain, 0);
num_accesses_left = num_memory_accesses (left_chain);
if (left_val == NULL || num_accesses_left < 0)
@@ -1962,7 +1962,7 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
return 0;
}
- fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain);
+ fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain, 0);
num_accesses_right = num_memory_accesses (right_chain);
if (right_val == NULL || num_accesses_right < 0)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 25a1b01..6ae1f5b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2013-08-02 Tom Tromey <tromey@redhat.com>
+
+ * gdb.base/watchpoint.c (struct foo5): New.
+ (nullptr): New global.
+ * gdb.base/watchpoint.exp (test_watch_location): Add test.
+
2013-08-01 Doug Evans <dje@google.com>
PR symtab/15691
diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c
index e887f99..92fb3b1 100644
--- a/gdb/testsuite/gdb.base/watchpoint.c
+++ b/gdb/testsuite/gdb.base/watchpoint.c
@@ -54,6 +54,13 @@ struct foo4
};
struct foo4 foo4;
+struct foo5
+{
+ struct { int x; } *p;
+};
+
+struct foo5 *nullptr;
+
void marker1 ()
{
}
diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.base/watchpoint.exp
index e0f7adc..e0d4f81 100644
--- a/gdb/testsuite/gdb.base/watchpoint.exp
+++ b/gdb/testsuite/gdb.base/watchpoint.exp
@@ -603,6 +603,9 @@ proc test_watch_location {} {
gdb_breakpoint [gdb_get_line_number "func5 breakpoint here"]
gdb_continue_to_breakpoint "func5 breakpoint here"
+ gdb_test "watch -location nullptr->p->x" \
+ "Cannot access memory at address 0x0"
+
gdb_test "watch -location *x" "atchpoint .*: .*" "watch -location .x"
gdb_test "continue" \
diff --git a/gdb/value.h b/gdb/value.h
index 5e00c89..599850e 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -728,7 +728,8 @@ extern struct value *evaluate_subexpression_type (struct expression *exp,
extern void fetch_subexp_value (struct expression *exp, int *pc,
struct value **valp, struct value **resultp,
- struct value **val_chain);
+ struct value **val_chain,
+ int preserve_errors);
extern char *extract_field_op (struct expression *exp, int *subexp);