This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[unavailable values part 1, 01/17] base support for unavailable value contents


This adds the base support for marking chunks of a given
value's contents as unavailable.  It then makes it so that 
it is an error to get at the contents of such values with
value_contents() or value_contents_all(), similarly to how
it is also an error to do the same to optimized out values.
This in turn automaticaly makes it an error to use unavailable
values in expression evaluation.
Trying to print formatted or unformatted scalars (even if they're
part of a compound) is also caught already by this patch, where
we now print <unavailable> in place of "0" or some other garbage.
This was made simple and centralized since the introduction
of val_print_scalar_formatted in
<http://sourceware.org/ml/gdb-patches/2011-01/msg00505.html>
(yay for pieces falling in together!).

Python pretty-printing does not yet know what to do
to unavailable values, so this disables it.  Does not mean
someone can't add it later.

Note that nothing is actually marking chunks of a value's
contents as unavailable yet in this patch, so it's
not testable yet.

We give preference to printing <optimized out> rather
than <unavailable>, since if a value had been optimized out
at compile time, it can never be collected at run-time.

-- 
Pedro Alves

2011-02-07  Pedro Alves  <pedro@codesourcery.com>

	Base support for <unavailable> value contents.

	gdb/
	* value.h (value_bytes_available): Declare.
	(mark_value_bytes_unavailable): Declare.
	* value.c (struct range): New struct.
	(range_s): New typedef.
	(ranges_overlap): New function.
	(ranges_contain_p): New function.
	(ranges_copy): New function.
	(struct value) <unavailable>: New field.
	(value_bytes_available): New function.
	(mark_value_bytes_unavailable): New function.
	(require_not_optimized_out): Constify parameter.
	(require_available): New function.
	(value_contents_all, value_contents): Require all bytes be
	available.
	(value_free): Free `unavailable'.
	(value_copy): Copy `unavailable'.
	* valprint.h (val_print_unavailable): Declare.
	* valprint.c (valprint_check_validity): Rename `offset' parameter
	to `embedded_offset'.  If printing a scalar, check whether the
	value chunk is available.
	(val_print_unavailable): New.
	(val_print_scalar_formatted): Check whether the value is
	available.
	* python/py-prettyprint.c (apply_val_pretty_printer): Refuse
	pretty-printing unavailable values.

---
 gdb/python/py-prettyprint.c |    5 +
 gdb/valprint.c              |   22 +++++-
 gdb/valprint.h              |    2 
 gdb/value.c                 |  156 +++++++++++++++++++++++++++++++++++++++++++-
 gdb/value.h                 |   14 +++
 5 files changed, 194 insertions(+), 5 deletions(-)

Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2011-02-07 11:31:36.446706000 +0000
+++ src/gdb/value.h	2011-02-07 11:31:37.986706000 +0000
@@ -360,6 +360,20 @@ extern int value_bits_valid (const struc
 extern int value_bits_synthetic_pointer (const struct value *value,
 					 int offset, int length);
 
+/* Given a value, determine whether the contents bytes starting at
+   OFFSET and extending for LENGTH bytes are available.  This returns
+   zero if all bytes in the given range are available, zero if any
+   byte is unavailable.  */
+
+extern int value_bytes_available (const struct value *value,
+				  int offset, int length);
+
+/* Mark VALUE's content bytes starting at OFFSET and extending for
+   LENGTH bytes as unavailable.  */
+
+extern void mark_value_bytes_unavailable (struct value *value,
+					  int offset, int length);
+
 
 
 #include "symtab.h"
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c	2011-02-07 11:31:36.446706000 +0000
+++ src/gdb/value.c	2011-02-07 11:31:37.996706001 +0000
@@ -63,6 +63,67 @@ struct internal_function
   void *cookie;
 };
 
+/* Defines an [OFFSET, OFFSET + LENGTH) range.  */
+
+struct range
+{
+  /* Lowest offset in the range.  */
+  int offset;
+
+  /* Length of the range.  */
+  int length;
+};
+
+typedef struct range range_s;
+
+DEF_VEC_O(range_s);
+
+/* Returns true if the ranges defined by [offset1, offset1+len1) and
+   [offset2, offset2+len2) overlap.  */
+
+static int
+ranges_overlap (int offset1, int len1,
+		int offset2, int len2)
+{
+  ULONGEST h, l;
+
+  l = max (offset1, offset2);
+  h = min (offset1 + len1, offset2 + len2);
+  return (l < h);
+}
+
+/* Returns true if RANGES contains any range that overlaps [OFFSET,
+   OFFSET+LENGTH).  */
+
+static int
+ranges_contain_p (VEC(range_s) *ranges, int offset, int length)
+{
+  int i;
+  range_s *r;
+
+  for (i = 0; VEC_iterate (range_s, ranges, i, r); i++)
+    if (ranges_overlap (r->offset, r->length,
+			offset, length))
+      return 1;
+
+  return 0;
+}
+
+/* Returns a deep copy of RANGES.  */
+
+static VEC(range_s) *
+ranges_copy (VEC(range_s) *ranges)
+{
+  int i;
+  range_s *r;
+  VEC(range_s) *copy = NULL;
+
+  for (i = 0; VEC_iterate (range_s, ranges, i, r); i++)
+    VEC_safe_push (range_s, copy, r);
+
+  return copy;
+}
+
 static struct cmd_list_element *functionlist;
 
 struct value
@@ -206,6 +267,11 @@ struct value
      valid if lazy is nonzero.  */
   gdb_byte *contents;
 
+  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
+     rather than available, since the common and default case is for a
+     value to be available.  This is filled in at value read time.  */
+  VEC(range_s) *unavailable;
+
   /* The number of references to this value.  When a value is created,
      the value chain holds a reference, so REFERENCE_COUNT is 1.  If
      release_value is called, this value is removed from the chain but
@@ -214,6 +280,83 @@ struct value
   int reference_count;
 };
 
+int
+value_bytes_available (const struct value *value, int offset, int length)
+{
+  gdb_assert (!value->lazy);
+
+  return !ranges_contain_p (value->unavailable, offset, length);
+}
+
+void
+mark_value_bytes_unavailable (struct value *value, int offset, int length)
+{
+  struct range *r;
+  int i;
+
+  /* Insert the range sorted.  If there's overlap or the new range
+     would be contiguous with an existing range, merge.  */
+  for (i = 0; VEC_iterate (range_s, value->unavailable, i, r); i++)
+    {
+      if (ranges_overlap (r->offset, r->length, offset, length))
+	{
+	  ULONGEST l = min (r->offset, offset);
+	  ULONGEST h = max (r->offset + r->length, offset + length);
+
+	  r->offset = l;
+	  r->length = h - l;
+	  break;
+	}
+      else if (offset == r->offset + r->length)
+	{
+	  r->length += length;
+	  break;
+	}
+      else if (offset < r->offset)
+	{
+	  struct range *nr;
+
+	  nr = VEC_safe_insert (range_s, value->unavailable, i, NULL);
+	  nr->offset = offset;
+	  nr->length = length;
+	  break;
+	}
+    }
+
+  /* Check whether the ranges following the one we've just added can
+     be folded in.  */
+  if (i < VEC_length (range_s, value->unavailable))
+    {
+      /* Get the range we just touched.  */
+      struct range *t = VEC_index (range_s, value->unavailable, i);
+      int removed = 0;
+
+      for (; VEC_iterate (range_s, value->unavailable, i, r); i++)
+	if (r->offset <= t->offset + t->length)
+	  {
+	    ULONGEST l, h;
+
+	    l = min (t->offset, r->offset);
+	    h = max (t->offset + t->length, r->offset + r->length);
+
+	    t->offset = l;
+	    t->length = h - l;
+
+	    removed++;
+	  }
+
+      if (removed != 0)
+	VEC_truncate (range_s, value->unavailable,
+		      VEC_length (range_s, value->unavailable) - removed);
+    }
+  else
+    {
+      r = VEC_safe_push (range_s, value->unavailable, NULL);
+      r->offset = offset;
+      r->length = length;
+    }
+}
+
 /* Prototypes for local functions.  */
 
 static void show_values (char *, int);
@@ -420,12 +563,19 @@ value_enclosing_type (struct value *valu
 }
 
 static void
-require_not_optimized_out (struct value *value)
+require_not_optimized_out (const struct value *value)
 {
   if (value->optimized_out)
     error (_("value has been optimized out"));
 }
 
+static void
+require_available (const struct value *value)
+{
+  if (!VEC_empty (range_s, value->unavailable))
+    error (_("value is not available"));
+}
+
 const gdb_byte *
 value_contents_for_printing (struct value *value)
 {
@@ -446,6 +596,7 @@ value_contents_all (struct value *value)
 {
   const gdb_byte *result = value_contents_for_printing (value);
   require_not_optimized_out (value);
+  require_available (value);
   return result;
 }
 
@@ -478,6 +629,7 @@ value_contents (struct value *value)
 {
   const gdb_byte *result = value_contents_writeable (value);
   require_not_optimized_out (value);
+  require_available (value);
   return result;
 }
 
@@ -703,6 +855,7 @@ value_free (struct value *val)
 	}
 
       xfree (val->contents);
+      VEC_free (range_s, val->unavailable);
     }
   xfree (val);
 }
@@ -833,6 +986,7 @@ value_copy (struct value *arg)
 	      TYPE_LENGTH (value_enclosing_type (arg)));
 
     }
+  val->unavailable = ranges_copy (arg->unavailable);
   val->parent = arg->parent;
   if (val->parent)
     value_incref (val->parent);
Index: src/gdb/valprint.h
===================================================================
--- src.orig/gdb/valprint.h	2011-02-07 11:31:36.446706000 +0000
+++ src/gdb/valprint.h	2011-02-07 11:31:37.996706001 +0000
@@ -154,4 +154,6 @@ int read_string (CORE_ADDR addr, int len
 
 extern void val_print_optimized_out (struct ui_file *stream);
 
+extern void val_print_unavailable (struct ui_file *stream);
+
 #endif
Index: src/gdb/valprint.c
===================================================================
--- src.orig/gdb/valprint.c	2011-02-07 11:31:36.446706000 +0000
+++ src/gdb/valprint.c	2011-02-07 11:31:37.996706001 +0000
@@ -260,7 +260,7 @@ scalar_type_p (struct type *type)
 static int
 valprint_check_validity (struct ui_file *stream,
 			 struct type *type,
-			 int offset,
+			 int embedded_offset,
 			 const struct value *val)
 {
   CHECK_TYPEDEF (type);
@@ -269,19 +269,25 @@ valprint_check_validity (struct ui_file
       && TYPE_CODE (type) != TYPE_CODE_STRUCT
       && TYPE_CODE (type) != TYPE_CODE_ARRAY)
     {
-      if (! value_bits_valid (val, TARGET_CHAR_BIT * offset,
-			      TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+      if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
+			     TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
 	  val_print_optimized_out (stream);
 	  return 0;
 	}
 
-      if (value_bits_synthetic_pointer (val, TARGET_CHAR_BIT * offset,
+      if (value_bits_synthetic_pointer (val, TARGET_CHAR_BIT * embedded_offset,
 					TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
 	  fputs_filtered (_("<synthetic pointer>"), stream);
 	  return 0;
 	}
+
+      if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
+	{
+	  val_print_unavailable (stream);
+	  return 0;
+	}
     }
 
   return 1;
@@ -293,6 +299,12 @@ val_print_optimized_out (struct ui_file
   fprintf_filtered (stream, _("<optimized out>"));
 }
 
+void
+val_print_unavailable (struct ui_file *stream)
+{
+  fprintf_filtered (stream, _("<unavailable>"));
+}
+
 /* Print using the given LANGUAGE the data of type TYPE located at
    VALADDR + EMBEDDED_OFFSET (within GDB), which came from the
    inferior at address ADDRESS + EMBEDDED_OFFSET, onto stdio stream
@@ -560,6 +572,8 @@ val_print_scalar_formatted (struct type
   if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
 			      TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     val_print_optimized_out (stream);
+  else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
+    val_print_unavailable (stream);
   else
     print_scalar_formatted (valaddr + embedded_offset, type,
 			    options, size, stream);
Index: src/gdb/python/py-prettyprint.c
===================================================================
--- src.orig/gdb/python/py-prettyprint.c	2011-02-07 11:31:36.446706000 +0000
+++ src/gdb/python/py-prettyprint.c	2011-02-07 11:31:37.996706001 +0000
@@ -690,6 +690,11 @@ apply_val_pretty_printer (struct type *t
   struct cleanup *cleanups;
   int result = 0;
   enum string_repr_result print_result;
+
+  /* No pretty-printer support for unavailable values.  */
+  if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
+    return 0;
+
   cleanups = ensure_python_env (gdbarch, language);
 
   /* Instantiate the printer.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]