diff options
author | Daniel Jacobowitz <drow@false.org> | 2009-07-21 18:15:32 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2009-07-21 18:15:32 +0000 |
commit | 4ea48cc1cd4875e570047f5aff70387018a56645 (patch) | |
tree | 35e518fe24754a9342c08045ba1718d8e0c44f81 /gdb/valops.c | |
parent | 828d3400fb1a9914ab16ee05dfe2647af8c566c5 (diff) | |
download | gdb-4ea48cc1cd4875e570047f5aff70387018a56645.zip gdb-4ea48cc1cd4875e570047f5aff70387018a56645.tar.gz gdb-4ea48cc1cd4875e570047f5aff70387018a56645.tar.bz2 |
gdb/
* valops.c (value_fetch_lazy): Handle bitfields explicitly.
(value_assign): Remove unnecessary FIXME. Honor the container
type of bitfields if possible.
* value.c (struct value): Add parent field.
(value_parent): New function.
(value_free): Free the parent also.
(value_copy): Copy the parent also.
(value_primitive_field): Do not read the contents of a lazy
value to create a child bitfield value. Set bitpos and offset
according to the container type if possible.
(unpack_bits_as_long): Rename from unpack_field_as_long. Take
field_type, bitpos, and bitsize instead of type and fieldno.
(unpack_field_as_long): Use unpack_bits_as_long.
* value.h (value_parent, unpack_bits_as_long): New prototypes.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index 2d20b41..5e5c4ed 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -632,7 +632,25 @@ value_fetch_lazy (struct value *val) { gdb_assert (value_lazy (val)); allocate_value_contents (val); - if (VALUE_LVAL (val) == lval_memory) + if (value_bitsize (val)) + { + /* To read a lazy bitfield, read the entire enclosing value. This + prevents reading the same block of (possibly volatile) memory once + per bitfield. It would be even better to read only the containing + word, but we have no way to record that just specific bits of a + value have been fetched. */ + struct type *type = check_typedef (value_type (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 (parent) + offset, + value_bitpos (val), + value_bitsize (val)); + int length = TYPE_LENGTH (type); + store_signed_integer (value_contents_raw (val), length, byte_order, num); + } + else if (VALUE_LVAL (val) == lval_memory) { CORE_ADDR addr = value_address (val); int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); @@ -800,13 +818,20 @@ value_assign (struct value *toval, struct value *fromval) if (value_bitsize (toval)) { - /* We assume that the argument to read_memory is in units - of host chars. FIXME: Is that correct? */ changed_len = (value_bitpos (toval) + value_bitsize (toval) + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT; + /* If we can read-modify-write exactly the size of the + containing type (e.g. short or int) then do so. This + is safer for volatile bitfields mapped to hardware + registers. */ + if (changed_len < TYPE_LENGTH (type) + && TYPE_LENGTH (type) <= (int) sizeof (LONGEST) + && ((LONGEST) value_address (toval) % TYPE_LENGTH (type)) == 0) + changed_len = TYPE_LENGTH (type); + if (changed_len > (int) sizeof (LONGEST)) error (_("Can't handle bitfields which don't fit in a %d bit word."), (int) sizeof (LONGEST) * HOST_CHAR_BIT); |