diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 106835a7641..e2ba5f5917a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,34 @@ +2011-02-14 Pedro Alves + + * 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. + 2011-02-14 Pedro Alves * value.c (get_internalvar_integer): Also return the int value of diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index fff41d80f08..1a171ea20ce 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -323,9 +323,8 @@ cp_print_value_fields (struct type *type, struct type *real_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); diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c index bed9b2f396c..f49b1720237 100644 --- a/gdb/jv-valprint.c +++ b/gdb/jv-valprint.c @@ -416,9 +416,7 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr, { 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; diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c index 8e790702249..7031a771108 100644 --- a/gdb/p-valprint.c +++ b/gdb/p-valprint.c @@ -810,9 +810,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr, { 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 type *type, const gdb_byte *valaddr, 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); diff --git a/gdb/valops.c b/gdb/valops.c index 7fa87293fad..802242cf47e 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -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) { diff --git a/gdb/value.c b/gdb/value.c index ee53914707a..a15315ed4b5 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -2532,30 +2532,24 @@ value_fn_field (struct value **arg1p, struct fn_field *f, } -/* 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. +/* 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. */ - 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) +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_type, const gdb_byte *valaddr, 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_type, const gdb_byte *valaddr, } } } - 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 diff --git a/gdb/value.h b/gdb/value.h index 0feb92fc88a..5bd48e01e02 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -430,11 +430,25 @@ extern LONGEST unpack_long (struct type *type, const gdb_byte *valaddr); 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);