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,
|
dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
||||||
struct dwarf2_cu *cu)
|
struct dwarf2_cu *cu)
|
||||||
{
|
{
|
||||||
struct objfile *objfile = cu->per_objfile->objfile;
|
|
||||||
struct gdbarch *gdbarch = objfile->arch ();
|
|
||||||
struct nextfield *new_field;
|
struct nextfield *new_field;
|
||||||
struct attribute *attr;
|
struct attribute *attr;
|
||||||
struct field *fp;
|
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);
|
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
|
||||||
if (attr != nullptr && attr->form_is_constant ())
|
if (attr != nullptr && attr->form_is_constant ())
|
||||||
{
|
{
|
||||||
ULONGEST bit_offset = attr->unsigned_constant ().value_or (0);
|
LONGEST 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;
|
|
||||||
|
|
||||||
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
|
LONGEST anonymous_size = 0;
|
||||||
if (attr != nullptr && attr->form_is_constant ())
|
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
|
/* The size of the anonymous object containing
|
||||||
indicated size (in bytes). */
|
the bit field is explicit, so use the
|
||||||
anonymous_size = attr->unsigned_constant ().value_or (0);
|
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 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply_bit_offset_to_field (*fp, bit_offset, anonymous_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get name of field. */
|
/* Get name of field. */
|
||||||
|
|||||||
@@ -2678,6 +2678,44 @@ compute_variant_fields (struct type *type,
|
|||||||
|
|
||||||
/* See gdbtypes.h. */
|
/* 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
|
void
|
||||||
resolve_dynamic_field (struct field &field,
|
resolve_dynamic_field (struct field &field,
|
||||||
const property_addr_info *addr_stack,
|
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 struct property_addr_info *addr_stack,
|
||||||
const frame_info_ptr &frame);
|
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 struct type *check_typedef (struct type *);
|
||||||
|
|
||||||
extern void check_stub_method_group (struct type *, int);
|
extern void check_stub_method_group (struct type *, int);
|
||||||
|
|||||||
Reference in New Issue
Block a user