Fix watch -location crash on inaccessible memory

Pedro Alves pedro@codesourcery.com
Tue Nov 9 18:30:00 GMT 2010


GDB is crashing dereferencing a NULL pointer if you try to watch an
inaccessible location with watch -location:

(top-gdb) bt 5 
#0  0x0000000000541d2a in value_type (value=0x0) at ../../src/gdb/value.c:354
#1  0x0000000000551668 in value_addr (arg1=0x0) at ../../src/gdb/valops.c:1557
#2  0x000000000052e540 in watch_command_1 (arg=0xbac22b "", accessflag=0, from_tty=1, just_location=1)
    at ../../src/gdb/breakpoint.c:8129
#3  0x000000000052ef3b in watch_maybe_just_location (arg=0xbac220 "*global_ptr", accessflag=0, from_tty=1)
    at ../../src/gdb/breakpoint.c:8411
#4  0x000000000052ef65 in watch_command (arg=0xbac216 "-location *global_ptr", from_tty=1)
    at ../../src/gdb/breakpoint.c:8417
(More stack frames follow...)

fetch_subexp_value's val "out" argument is only set to
non-NULL if the value was un-lazied successfully (that is, fetched
from memory).  If we want to get at the address of the
expression, the lazy value is enough (we don't need the actual
value of the expression), and that's what the 4th parameter of
fetch_subexp_value gives us.

Fixed thus.  Applied.  New test included.

-- 
Pedro Alves

2010-11-09  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* breakpoint.c (watch_command_1): Get a pointer of the lazy
	version of the expression's value, even if reading the value from
	memory fails.  When creating a -location watchpoint, get the
	value's address from the lazy value pointer.

	gdb/testsuite/
	* gdb.base/watchpoint.exp: Test "watch -location" with an
	innacessible location.

---
 gdb/breakpoint.c                      |    6 +++---
 gdb/testsuite/gdb.base/watchpoint.exp |    5 +++++
 2 files changed, 8 insertions(+), 3 deletions(-)

Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2010-10-16 01:01:59.000000000 +0100
+++ src/gdb/breakpoint.c	2010-11-09 17:25:12.000000000 +0000
@@ -8022,7 +8022,7 @@ watch_command_1 (char *arg, int accessfl
   struct breakpoint *b, *scope_breakpoint = NULL;
   struct expression *exp;
   struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
-  struct value *val, *mark;
+  struct value *val, *mark, *result;
   struct frame_info *frame;
   char *exp_start = NULL;
   char *exp_end = NULL;
@@ -8121,12 +8121,12 @@ watch_command_1 (char *arg, int accessfl
 
   exp_valid_block = innermost_block;
   mark = value_mark ();
-  fetch_subexp_value (exp, &pc, &val, NULL, NULL);
+  fetch_subexp_value (exp, &pc, &val, &result, NULL);
 
   if (just_location)
     {
       exp_valid_block = NULL;
-      val = value_addr (val);
+      val = value_addr (result);
       release_value (val);
       value_free_to_mark (mark);
     }
Index: src/gdb/testsuite/gdb.base/watchpoint.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.base/watchpoint.exp	2010-11-09 16:20:40.000000000 +0000
+++ src/gdb/testsuite/gdb.base/watchpoint.exp	2010-11-09 16:23:55.000000000 +0000
@@ -683,6 +683,11 @@ proc test_inaccessible_watchpoint {} {
 	    "$watchpoint_msg \[0-9\]+: \\*\\(int \\*\\) 0"
 	delete_breakpoints
 
+	# The same, but using -location through an indirection.
+	gdb_test "watch -location *global_ptr" \
+	    "$watchpoint_msg \[0-9\]+: \-location: \\*global_ptr"
+	delete_breakpoints
+
 	# This step requires two HW watchpoints.  Since PPC Server only has
 	# a single one, it will use a SW watchpoint in this case.
 	if [istarget powerpc64-*] {



More information about the Gdb-patches mailing list