This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfc] Fix bitfield regressions on 64-bit big-endian targets
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: drow at false dot org (Daniel Jacobowitz)
- Cc: gdb-patches at sourceware dot org
- Date: Sun, 27 Sep 2009 23:48:34 +0200 (CEST)
- Subject: [rfc] Fix bitfield regressions on 64-bit big-endian targets
Daniel Jacobowitz wrote:
> value_offset for a bitfield is an offset to be added into the parent's
> contents. So including the parent's offset is incorrect; the attached
> test shows that we were reading the wrong location. With large enough
> offsets, we could wander off to another page of memory and fault.
This changes the value_offset for a bitfield, but does not adapt all
places where the offset is used; in particular value_assign still does
not take the parent's offset into account.
This causes a significant number of store.exp testsuite failures on
s390x-linux and ppc64-linux (and presumably other 64-bit big-endian
platforms).
The following patch updates value_assign to respect the parent offset,
which fixes all those failures.
Tested on s390(x)-linux and ppc(64)-linux with no regressions.
Does this look OK to you?
Bye,
Ulrich
ChangeLog:
* valops.c (value_assign): Respect parent offset when
assigning to a bitfield.
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.225
diff -c -p -r1.225 valops.c
*** gdb/valops.c 31 Aug 2009 20:18:45 -0000 1.225
--- gdb/valops.c 25 Sep 2009 18:37:40 -0000
*************** value_assign (struct value *toval, struc
*** 827,832 ****
--- 827,835 ----
if (value_bitsize (toval))
{
+ struct value *parent = value_parent (toval);
+ changed_addr = value_address (parent) + value_offset (toval);
+
changed_len = (value_bitpos (toval)
+ value_bitsize (toval)
+ HOST_CHAR_BIT - 1)
*************** value_assign (struct value *toval, struc
*** 838,854 ****
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);
! read_memory (value_address (toval), buffer, changed_len);
modify_field (type, buffer, value_as_long (fromval),
value_bitpos (toval), value_bitsize (toval));
- changed_addr = value_address (toval);
dest_buffer = buffer;
}
else
--- 841,856 ----
registers. */
if (changed_len < TYPE_LENGTH (type)
&& TYPE_LENGTH (type) <= (int) sizeof (LONGEST)
! && ((LONGEST) changed_addr % 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);
! read_memory (changed_addr, buffer, changed_len);
modify_field (type, buffer, value_as_long (fromval),
value_bitpos (toval), value_bitsize (toval));
dest_buffer = buffer;
}
else
*************** value_assign (struct value *toval, struc
*** 891,896 ****
--- 893,900 ----
{
if (value_bitsize (toval))
{
+ struct value *parent = value_parent (toval);
+ int offset = value_offset (parent) + value_offset (toval);
int changed_len;
gdb_byte buffer[sizeof (LONGEST)];
*************** value_assign (struct value *toval, struc
*** 903,917 ****
error (_("Can't handle bitfields which don't fit in a %d bit word."),
(int) sizeof (LONGEST) * HOST_CHAR_BIT);
! get_frame_register_bytes (frame, value_reg,
! value_offset (toval),
changed_len, buffer);
modify_field (type, buffer, value_as_long (fromval),
value_bitpos (toval), value_bitsize (toval));
! put_frame_register_bytes (frame, value_reg,
! value_offset (toval),
changed_len, buffer);
}
else
--- 907,919 ----
error (_("Can't handle bitfields which don't fit in a %d bit word."),
(int) sizeof (LONGEST) * HOST_CHAR_BIT);
! get_frame_register_bytes (frame, value_reg, offset,
changed_len, buffer);
modify_field (type, buffer, value_as_long (fromval),
value_bitpos (toval), value_bitsize (toval));
! put_frame_register_bytes (frame, value_reg, offset,
changed_len, buffer);
}
else
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com