fix PR symtab/15719
authorTom Tromey <tromey@redhat.com>
Fri, 2 Aug 2013 16:41:08 +0000 (16:41 +0000)
committerTom Tromey <tromey@redhat.com>
Fri, 2 Aug 2013 16:41:08 +0000 (16:41 +0000)
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
gdb/breakpoint.c
gdb/eval.c
gdb/ppc-linux-nat.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/watchpoint.c
gdb/testsuite/gdb.base/watchpoint.exp
gdb/value.h

index 4e392733f52bd0964fea495915bf99ace8cbde2b..af34dec4aa3b4d781553f2cf6ab5db051abc7551 100644 (file)
@@ -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
index 1e89407eadd19f1e5430db3256b9ff0ac577e90a..eec7b7c54991e4dd2439c9bd9b15d554f284c12c 100644 (file)
@@ -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)
     {
index 539489f95cbfc5271ae9e91172009c20925a137d..e83bfdf8f17b7ab241868af2bd51ba862f9f02dd 100644 (file)
@@ -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;
index 1f3f080f94270a1b684d50eebed93651ce7b6c5c..c518f77d3a82cccf55b5444c82bf8221dba6d830 100644 (file)
@@ -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)
index 25a1b01cb34a2af308afd5677076658129c7aa4a..6ae1f5b5e0ae0e2e5e64507bc539cd72f47dca77 100644 (file)
@@ -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
index e887f99aebbc244110a0329ef09391b9ae935b62..92fb3b18647688be5ec58b016c8d865bb55685a9 100644 (file)
@@ -54,6 +54,13 @@ struct foo4
 };
 struct foo4 foo4;
 
+struct foo5
+{
+  struct { int x; } *p;
+};
+
+struct foo5 *nullptr;
+
 void marker1 ()
 {
 }
index e0f7adc797a9b9f95949e035662882fa56587c6c..e0d4f810877f00e56f1d595f1c2a41a003aaeb78 100644 (file)
@@ -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" \
index 5e00c8999b02d3c7181f1ba3a8144745197bed9d..599850e5f009f672734729392ec3b9a96caab605 100644 (file)
@@ -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);