mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
Introduce apply_bit_offset_to_field helper function
This patch makes a new function, apply_bit_offset_to_field, that is used to handle the logic of DW_AT_bit_offset. Currently there is just a single caller, but the next patch will change this.
This commit is contained in:
@@ -9940,8 +9940,6 @@ static void
|
||||
dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
||||
struct dwarf2_cu *cu)
|
||||
{
|
||||
struct objfile *objfile = cu->per_objfile->objfile;
|
||||
struct gdbarch *gdbarch = objfile->arch ();
|
||||
struct nextfield *new_field;
|
||||
struct attribute *attr;
|
||||
struct field *fp;
|
||||
@@ -10008,46 +10006,19 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
||||
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
|
||||
if (attr != nullptr && attr->form_is_constant ())
|
||||
{
|
||||
ULONGEST bit_offset = attr->unsigned_constant ().value_or (0);
|
||||
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
|
||||
{
|
||||
/* For big endian bits, the DW_AT_bit_offset gives the
|
||||
additional bit offset from the MSB of the containing
|
||||
anonymous object to the MSB of the field. We don't
|
||||
have to do anything special since we don't need to
|
||||
know the size of the anonymous object. */
|
||||
fp->set_loc_bitpos (fp->loc_bitpos () + bit_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For little endian bits, compute the bit offset to the
|
||||
MSB of the anonymous object, subtract off the number of
|
||||
bits from the MSB of the field to the MSB of the
|
||||
object, and then subtract off the number of bits of
|
||||
the field itself. The result is the bit offset of
|
||||
the LSB of the field. */
|
||||
int anonymous_size;
|
||||
LONGEST bit_offset = attr->unsigned_constant ().value_or (0);
|
||||
|
||||
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
|
||||
if (attr != nullptr && attr->form_is_constant ())
|
||||
{
|
||||
/* The size of the anonymous object containing
|
||||
the bit field is explicit, so use the
|
||||
indicated size (in bytes). */
|
||||
anonymous_size = attr->unsigned_constant ().value_or (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The size of the anonymous object containing
|
||||
the bit field must be inferred from the type
|
||||
attribute of the data member containing the
|
||||
bit field. */
|
||||
anonymous_size = fp->type ()->length ();
|
||||
}
|
||||
fp->set_loc_bitpos (fp->loc_bitpos ()
|
||||
+ anonymous_size * bits_per_byte
|
||||
- bit_offset - fp->bitsize ());
|
||||
LONGEST anonymous_size = 0;
|
||||
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
|
||||
if (attr != nullptr && attr->form_is_constant ())
|
||||
{
|
||||
/* The size of the anonymous object containing
|
||||
the bit field is explicit, so use the
|
||||
indicated size (in bytes). */
|
||||
anonymous_size = attr->unsigned_constant ().value_or (0);
|
||||
}
|
||||
|
||||
apply_bit_offset_to_field (*fp, bit_offset, anonymous_size);
|
||||
}
|
||||
|
||||
/* Get name of field. */
|
||||
|
||||
@@ -2678,6 +2678,44 @@ compute_variant_fields (struct type *type,
|
||||
|
||||
/* See gdbtypes.h. */
|
||||
|
||||
void
|
||||
apply_bit_offset_to_field (struct field &field, LONGEST bit_offset,
|
||||
LONGEST explicit_byte_size)
|
||||
{
|
||||
struct type *field_type = field.type ();
|
||||
struct gdbarch *gdbarch = field_type->arch ();
|
||||
LONGEST current_bitpos = field.loc_bitpos ();
|
||||
|
||||
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
|
||||
{
|
||||
/* For big endian bits, the DW_AT_bit_offset gives the
|
||||
additional bit offset from the MSB of the containing
|
||||
anonymous object to the MSB of the field. We don't
|
||||
have to do anything special since we don't need to
|
||||
know the size of the anonymous object. */
|
||||
field.set_loc_bitpos (current_bitpos + bit_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For little endian bits, compute the bit offset to the
|
||||
MSB of the anonymous object, subtract off the number of
|
||||
bits from the MSB of the field to the MSB of the
|
||||
object, and then subtract off the number of bits of
|
||||
the field itself. The result is the bit offset of
|
||||
the LSB of the field. */
|
||||
LONGEST object_size = explicit_byte_size;
|
||||
if (object_size == 0)
|
||||
object_size = field_type->length ();
|
||||
|
||||
field.set_loc_bitpos (current_bitpos
|
||||
+ 8 * object_size
|
||||
- bit_offset
|
||||
- field.bitsize ());
|
||||
}
|
||||
}
|
||||
|
||||
/* See gdbtypes.h. */
|
||||
|
||||
void
|
||||
resolve_dynamic_field (struct field &field,
|
||||
const property_addr_info *addr_stack,
|
||||
|
||||
@@ -2641,6 +2641,29 @@ extern void resolve_dynamic_field (struct field &field,
|
||||
const struct property_addr_info *addr_stack,
|
||||
const frame_info_ptr &frame);
|
||||
|
||||
/* A helper function that handles the DWARF semantics for
|
||||
DW_AT_bit_offset.
|
||||
|
||||
DWARF 3 specified DW_AT_bit_offset in a funny way, making it simple
|
||||
to use on big-endian targets but somewhat difficult for
|
||||
little-endian. This function handles the logic here.
|
||||
|
||||
While DW_AT_bit_offset was deprecated in DWARF 4 (and removed
|
||||
entirely from DWARF 5), it is still useful because it is the only
|
||||
way to describe a field that appears at a non-constant bit
|
||||
offset.
|
||||
|
||||
FIELD is updated in-place. It is assumed that FIELD already has a
|
||||
constant bit position. BIT_OFFSET is the value of the
|
||||
DW_AT_bit_offset attribute, and EXPLICIT_BYTE_SIZE is either the
|
||||
value of a DW_AT_byte_size from the field's DIE -- indicating an
|
||||
explicit size of the enclosing anonymous object -- or it may be 0,
|
||||
indicating that the field's type size should be used. */
|
||||
|
||||
extern void apply_bit_offset_to_field (struct field &field,
|
||||
LONGEST bit_offset,
|
||||
LONGEST explicit_byte_size);
|
||||
|
||||
extern struct type *check_typedef (struct type *);
|
||||
|
||||
extern void check_stub_method_group (struct type *, int);
|
||||
|
||||
Reference in New Issue
Block a user