This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [unavailable values part 1, 09/17] unavailable bitfields
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 10 Feb 2011 19:20:11 +0000
- Subject: Re: [unavailable values part 1, 09/17] unavailable bitfields
- References: <201102071432.10076.pedro@codesourcery.com>
On Thursday 10 February 2011 14:32:09, Pedro Alves wrote:
> 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.
...
> -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;
Except that I forgot to add a check for NULL original_value
here, and when I removed the NULL hack from value_entirely_available
(<http://sourceware.org/ml/gdb-patches/2011-02/msg00201.html>),
value_entirely_available crashed
running gdb.modula2/unbounded-array.exp (!).
Here's the updated patch fixing this. The reason it adds
a bit more indirection compared to the previous patch, is
so that callers from outside value.c don't see an interface
that allows passing in a NULL value...
--
Pedro Alves
2011-02-10 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_1): ... 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_value_bits_as_long): New.
(unpack_field_as_long): Rename to...
(unpack_value_field_as_long_1): ... 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_value_field_as_long): New.
(unpack_field_as_long_1): New.
(unpack_field_as_long): Reimplement as wrapper around
unpack_value_field_as_long_1.
(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 | 147 +++++++++++++++++++++++++++++++++++++++++++++---------
gdb/value.h | 18 +++++-
6 files changed, 156 insertions(+), 44 deletions(-)
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h 2011-02-10 18:54:10.347076001 +0000
+++ src/gdb/value.h 2011-02-10 18:54:42.737075995 +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-10 18:54:38.817075996 +0000
+++ src/gdb/value.c 2011-02-10 19:11:01.297075997 +0000
@@ -2532,30 +2532,24 @@ 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.
- Extracting bits depends on endianness of the machine. Compute the
- number of least significant bits to discard. For big endian machines,
- we compute the total number of bits in the anonymous object, subtract
- off the bit count from the MSB of the object to the MSB of the
- bitfield, then the size of the bitfield, which leaves the LSB discard
- count. For little endian machines, the discard count is simply the
- number of bits from the LSB of the anonymous object to the LSB of the
- bitfield.
-
- 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)
+/* Helper function for both unpack_value_bits_as_long and
+ unpack_bits_as_long. See those functions for more details on the
+ interface; the only difference is that this function accepts either
+ a NULL or a non-NULL ORIGINAL_VALUE. */
+
+static int
+unpack_value_bits_as_long_1 (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. */
@@ -2565,7 +2559,14 @@ 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 (original_value != NULL
+ && !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. */
@@ -2591,20 +2592,118 @@ unpack_bits_as_long (struct type *field_
}
}
}
- return (val);
+
+ *result = val;
+ return 1;
}
-/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
- VALADDR. See unpack_bits_as_long for more details. */
+/* 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, which must not be
+ NULL. The bitfield starts at BITPOS bits and contains BITSIZE
+ bits.
-LONGEST
-unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+ 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,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
+
+ If the field is signed, we also do sign extension. */
+
+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)
+{
+ gdb_assert (original_value != NULL);
+
+ return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
+ bitpos, bitsize, original_value, result);
+
+}
+
+/* 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. */
+
+static int
+unpack_value_field_as_long_1 (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_1 (field_type, valaddr, embedded_offset,
+ bitpos, bitsize, val,
+ result);
+}
+
+/* Unpack a field FIELDNO of the specified TYPE, from the object at
+ VALADDR + EMBEDDED_OFFSET. VALADDR points to the contents of
+ ORIGINAL_VALUE, which must not be NULL. 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)
+{
+ gdb_assert (val != NULL);
+
+ return unpack_value_field_as_long_1 (type, valaddr, embedded_offset,
+ fieldno, 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.
+ This function differs from unpack_value_field_as_long in that it
+ operates without a struct value object. */
+
+LONGEST
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+{
+ LONGEST result;
+
+ unpack_value_field_as_long_1 (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-10 18:54:08.417075998 +0000
+++ src/gdb/valops.c 2011-02-10 18:54:42.737075995 +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-10 18:54:10.357075994 +0000
+++ src/gdb/jv-valprint.c 2011-02-10 18:54:42.747075996 +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-10 18:54:08.417075998 +0000
+++ src/gdb/p-valprint.c 2011-02-10 18:54:42.747075996 +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-10 18:54:08.417075998 +0000
+++ src/gdb/cp-valprint.c 2011-02-10 18:54:42.747075996 +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);