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, 09/17] unavailable bitfields


With:

 (gdb) ptype foo2.foo
 type = struct foo_s {
     int a;
     int b;
     int array[10000];
     tuple tarray[8];
     void *ptr;
     int ss : 1;         <<<<<<< bitfield
 }


where foo2.foo has _not_ been completely collected:

We get:

 (gdb) p foo2.foo.ss
 $2 = 0

While we want:

 (gdb) p foo2.foo.ss
 $6 = <unavailable>

The unpack_field_as_XXX family of functions is completely agnostic
of struct value's metadata (unavailable-ness, optimized-out-ness):

                 v = value_from_longest
                   (TYPE_FIELD_TYPE (type, i), 
                    unpack_field_as_long (type, valaddr + offset, i));

In the case above, the contents at "valaddr + offset" are unavailable,
so unpack_field_as_long [this knows about bitfield offsets] returns
garbage, zero, usually.  Basically, the direction we're heading is that
operations that work outside of the value machinery tend to need to
disappear.  This

 unpack_field_as_long -> LONGEST (a scalar) -> value_from_longest pair

op is one such case, where the LONGEST in the middle loses
the unavailable-ness.

unpack_field_as_long, knows to handle bitfield offsets, and 
having the callers of unpack_field_as_long know which bytes of the
containing object would be required to extract the bitfield would
require doing most of the work unpack_bits_as_long does, twice: once by
the caller to return a new unavailable value; once by
unpack_bits_as_long itself.  So instead, I'm tweaking the unpack_... interface
to be able to pass down the struct value (unpack_value_...), and reimplement
the non-value functions on top of those, passing a NULL value.
Then, I've added a new value_field_bitfield that should be called instead
of donig "unpack_field_as_long -> LONGEST -> value_from_longest".

-- 
Pedro Alves

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

	gdb/
	* value.h (unpack_bits_as_long): Delete declaration.
	(unpack_value_bits_as_long): Declare.
	(unpack_value_field_as_long): Declare.
	(value_field_bitfield): Declare.
	* value.c (unpack_bits_as_long): Rename to...
	(unpack_value_bits_as_long): ... this.  Add embedded_offset and
	value parameters.  Return the extracted result in a new output
	parameter.  If the value contents are unavailable, return false,
	otherwise return true.
	(unpack_field_as_long): Rename to...
	(unpack_value_field_as_long): ... this.  Add embedded_offset and
	Add embedded_offset and value parameters.  Return the extracted
	result in a new output parameter. If the value contents are
	unavailable, return false, otherwise return true.
	(unpack_field_as_long): Reimplement as wrapper around
	unpack_value_field_as_long.
	(value_field_bitfield): New function.
	* valops.c (value_fetch_lazy): When fetching a bitfield, use
	unpack_value_bits_as_long.  Mark the value as unavailable, if it
	is unavailable.
	* jv-valprint.c (java_print_value_fields): Use value_field_bitfield.
	* p-valprint.c (pascal_object_print_value_fields): Use
	value_field_bitfield.
	* cp-valprint.c (cp_print_value_fields): Use value_field_bitfield.

---
 gdb/cp-valprint.c |    5 +--
 gdb/jv-valprint.c |    4 --
 gdb/p-valprint.c  |    8 +---
 gdb/valops.c      |   18 +++++++---
 gdb/value.c       |   89 +++++++++++++++++++++++++++++++++++++++++++++---------
 gdb/value.h       |   18 +++++++++-
 6 files changed, 108 insertions(+), 34 deletions(-)

Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2011-02-07 11:15:23.176706001 +0000
+++ src/gdb/value.h	2011-02-07 11:15:30.896705999 +0000
@@ -430,11 +430,25 @@ extern LONGEST unpack_long (struct type
 extern DOUBLEST unpack_double (struct type *type, const gdb_byte *valaddr,
 			       int *invp);
 extern CORE_ADDR unpack_pointer (struct type *type, const gdb_byte *valaddr);
-LONGEST unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
-			     int bitpos, int bitsize);
+
+extern int unpack_value_bits_as_long (struct type *field_type,
+				      const gdb_byte *valaddr,
+				      int embedded_offset, int bitpos,
+				      int bitsize,
+				      const struct value *original_value,
+				      LONGEST *result);
+
 extern LONGEST unpack_field_as_long (struct type *type,
 				     const gdb_byte *valaddr,
 				     int fieldno);
+extern int unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
+				int embedded_offset, int fieldno,
+				const struct value *val, LONGEST *result);
+
+extern struct value *value_field_bitfield (struct type *type, int fieldno,
+					   const gdb_byte *valaddr,
+					   int embedded_offset,
+					   const struct value *val);
 
 extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num);
 
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c	2011-02-07 11:15:29.746705993 +0000
+++ src/gdb/value.c	2011-02-07 11:15:30.896705999 +0000
@@ -2393,9 +2393,13 @@ value_fn_field (struct value **arg1p, st
 }
 
 
-/* Unpack a bitfield of the specified FIELD_TYPE, from the anonymous
-   object at VALADDR.  The bitfield starts at BITPOS bits and contains
-   BITSIZE bits.
+/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
+   VALADDR + EMBEDDED_OFFSET, and store the result in *RESULT.
+   VALADDR points to the contents of ORIGINAL_VALUE.  The bitfield
+   starts at BITPOS bits and contains BITSIZE bits.
+
+   Returns false if the value contents are unavailable, otherwise
+   returns true, indicating a valid value has been stored in *RESULT.
 
    Extracting bits depends on endianness of the machine.  Compute the
    number of least significant bits to discard.  For big endian machines,
@@ -2408,15 +2412,18 @@ value_fn_field (struct value **arg1p, st
 
    If the field is signed, we also do sign extension.  */
 
-LONGEST
-unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
-		     int bitpos, int bitsize)
+int
+unpack_value_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
+			   int embedded_offset, int bitpos, int bitsize,
+			   const struct value *original_value,
+			   LONGEST *result)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (field_type));
   ULONGEST val;
   ULONGEST valmask;
   int lsbcount;
   int bytes_read;
+  int read_offset;
 
   /* Read the minimum number of bytes required; there may not be
      enough bytes to read an entire ULONGEST.  */
@@ -2426,7 +2433,13 @@ unpack_bits_as_long (struct type *field_
   else
     bytes_read = TYPE_LENGTH (field_type);
 
-  val = extract_unsigned_integer (valaddr + bitpos / 8,
+  read_offset = bitpos / 8;
+
+  if (!value_bytes_available (original_value, embedded_offset + read_offset,
+			      bytes_read))
+    return 0;
+
+  val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
 				  bytes_read, byte_order);
 
   /* Extract bits.  See comment above.  */
@@ -2452,20 +2465,68 @@ unpack_bits_as_long (struct type *field_
 	    }
 	}
     }
-  return (val);
-}
 
-/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
-   VALADDR.  See unpack_bits_as_long for more details.  */
+  *result = val;
+  return 1;
+}
 
-LONGEST
-unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+/* Unpack a field FIELDNO of the specified TYPE, from the object at
+   VALADDR + EMBEDDED_OFFSET.  VALADDR points to the contents of
+   ORIGINAL_VALUE.  See unpack_value_bits_as_long for more
+   details.  */
+
+int
+unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
+			    int embedded_offset, int fieldno,
+			    const struct value *val, LONGEST *result)
 {
   int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
   int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
   struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
 
-  return unpack_bits_as_long (field_type, valaddr, bitpos, bitsize);
+  return unpack_value_bits_as_long (field_type, valaddr, embedded_offset,
+				    bitpos, bitsize, val,
+				    result);
+}
+
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous
+   object at VALADDR.  See unpack_value_bits_as_long for more
+   details.  */
+
+LONGEST
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+{
+  LONGEST result;
+
+  unpack_value_field_as_long (type, valaddr, 0, fieldno, NULL, &result);
+  return result;
+}
+
+/* Return a new value with type TYPE, which is FIELDNO field of the
+   object at VALADDR + EMBEDDEDOFFSET.  VALADDR points to the contents
+   of VAL.  If the VAL's contents required to extract the bitfield
+   from are unavailable, the new value is correspondingly marked as
+   unavailable.  */
+
+struct value *
+value_field_bitfield (struct type *type, int fieldno,
+		      const gdb_byte *valaddr,
+		      int embedded_offset, const struct value *val)
+{
+  LONGEST l;
+
+  if (!unpack_value_field_as_long (type, valaddr, embedded_offset, fieldno,
+				   val, &l))
+    {
+      struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+      struct value *retval = allocate_value (field_type);
+      mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (field_type));
+      return retval;
+    }
+  else
+    {
+      return value_from_longest (TYPE_FIELD_TYPE (type, fieldno), l);
+    }
 }
 
 /* Modify the value of a bitfield.  ADDR points to a block of memory in
Index: src/gdb/valops.c
===================================================================
--- src.orig/gdb/valops.c	2011-02-07 11:15:02.926705996 +0000
+++ src/gdb/valops.c	2011-02-07 11:15:30.906706000 +0000
@@ -989,11 +989,7 @@ value_fetch_lazy (struct value *val)
       enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
       struct value *parent = value_parent (val);
       LONGEST offset = value_offset (val);
-      LONGEST num = unpack_bits_as_long (value_type (val),
-					 (value_contents_for_printing (parent)
-					  + offset),
-					 value_bitpos (val),
-					 value_bitsize (val));
+      LONGEST num;
       int length = TYPE_LENGTH (type);
 
       if (!value_bits_valid (val,
@@ -1001,7 +997,17 @@ value_fetch_lazy (struct value *val)
 			     value_bitsize (val)))
 	error (_("value has been optimized out"));
 
-      store_signed_integer (value_contents_raw (val), length, byte_order, num);
+      if (!unpack_value_bits_as_long (value_type (val),
+				      value_contents_for_printing (parent),
+				      offset,
+				      value_bitpos (val),
+				      value_bitsize (val), parent, &num))
+	mark_value_bytes_unavailable (val,
+				      value_embedded_offset (val),
+				      length);
+      else
+	store_signed_integer (value_contents_raw (val), length,
+			      byte_order, num);
     }
   else if (VALUE_LVAL (val) == lval_memory)
     {
Index: src/gdb/jv-valprint.c
===================================================================
--- src.orig/gdb/jv-valprint.c	2011-02-07 11:15:23.186706002 +0000
+++ src/gdb/jv-valprint.c	2011-02-07 11:15:30.916706001 +0000
@@ -416,9 +416,7 @@ java_print_value_fields (struct type *ty
 		{
 		  struct value_print_options opts;
 
-		  v = value_from_longest
-		    (TYPE_FIELD_TYPE (type, i),
-		     unpack_field_as_long (type, valaddr + offset, i));
+		  v = value_field_bitfield (type, i, valaddr, offset, val);
 
 		  opts = *options;
 		  opts.deref_ref = 0;
Index: src/gdb/p-valprint.c
===================================================================
--- src.orig/gdb/p-valprint.c	2011-02-07 10:54:23.096706002 +0000
+++ src/gdb/p-valprint.c	2011-02-07 11:15:30.916706001 +0000
@@ -810,9 +810,7 @@ pascal_object_print_value_fields (struct
 		{
 		  struct value_print_options opts = *options;
 
-		  v = value_from_longest (TYPE_FIELD_TYPE (type, i),
-				   unpack_field_as_long (type,
-							 valaddr + offset, i));
+		  v = value_field_bitfield (type, i, valaddr, offset, val);
 
 		  opts.deref_ref = 0;
 		  common_val_print (v, stream, recurse + 1, &opts,
@@ -831,9 +829,7 @@ pascal_object_print_value_fields (struct
 		     v4.17 specific.  */
 		  struct value *v;
 
-		  v = value_from_longest
-		    (TYPE_FIELD_TYPE (type, i),
-		     unpack_field_as_long (type, valaddr + offset, i));
+		  v = value_field_bitfield (type, i, valaddr, offset, val);
 
 		  if (v == NULL)
 		    val_print_optimized_out (stream);
Index: src/gdb/cp-valprint.c
===================================================================
--- src.orig/gdb/cp-valprint.c	2011-02-02 18:58:36.037898991 +0000
+++ src/gdb/cp-valprint.c	2011-02-07 11:15:30.916706001 +0000
@@ -323,9 +323,8 @@ cp_print_value_fields (struct type *type
 		  struct value_print_options opts = *options;
 
 		  opts.deref_ref = 0;
-		  v = value_from_longest
-		    (TYPE_FIELD_TYPE (type, i), 
-		     unpack_field_as_long (type, valaddr + offset, i));
+
+		  v = value_field_bitfield (type, i, valaddr, offset, val);
 
 		  common_val_print (v, stream, recurse + 1, &opts,
 				    current_language);


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