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;
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
+ LONGEST bit_offset = attr->unsigned_constant ().value_or (0);
+
+ LONGEST anonymous_size = 0;
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ if (attr != nullptr && attr->form_is_constant ())
{
- /* 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);
- 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 ());
+ /* 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. */
/* 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,
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);