From 3a1115a0cc0a0a98555ba99df76ad9bcfee08759 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 2 Aug 2013 16:41:08 +0000 Subject: [PATCH] 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. --- gdb/ChangeLog | 10 ++++++++++ gdb/breakpoint.c | 6 +++--- gdb/eval.c | 18 +++++++++++------- gdb/ppc-linux-nat.c | 4 ++-- gdb/testsuite/ChangeLog | 6 ++++++ gdb/testsuite/gdb.base/watchpoint.c | 7 +++++++ gdb/testsuite/gdb.base/watchpoint.exp | 3 +++ gdb/value.h | 3 ++- 8 files changed, 44 insertions(+), 13 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4e392733f52..af34dec4aa3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2013-08-02 Tom Tromey + + 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 * mi/mi-interp.c (mi_interpreter_resume): Remove call to diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 1e89407eadd..eec7b7c5499 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 539489f95cb..e83bfdf8f17 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 1f3f080f942..c518f77d3a8 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 25a1b01cb34..6ae1f5b5e0a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-08-02 Tom Tromey + + * gdb.base/watchpoint.c (struct foo5): New. + (nullptr): New global. + * gdb.base/watchpoint.exp (test_watch_location): Add test. + 2013-08-01 Doug Evans PR symtab/15691 diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c index e887f99aebb..92fb3b18647 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 e0f7adc797a..e0d4f810877 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 5e00c8999b0..599850e5f00 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); -- 2.30.2