This changes the DWARF reader to use attribute::unsigned_constant when
examining DW_AT_data_bit_offset.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680
---
gdb/dwarf2/read.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
@@ -10028,7 +10028,7 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
if (attr != nullptr)
{
- *offset = attr->constant_value (0);
+ *offset = attr->unsigned_constant ().value_or (0);
return 1;
}
}
@@ -10099,7 +10099,7 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
{
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
if (attr != nullptr)
- field->set_loc_bitpos (attr->constant_value (0));
+ field->set_loc_bitpos (attr->unsigned_constant ().value_or (0));
}
}
@@ -10177,6 +10177,7 @@ 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
@@ -10184,7 +10185,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
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 () + attr->constant_value (0));
+ fp->set_loc_bitpos (fp->loc_bitpos () + bit_offset);
}
else
{
@@ -10195,7 +10196,6 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
the field itself. The result is the bit offset of
the LSB of the field. */
int anonymous_size;
- int bit_offset = attr->constant_value (0);
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr != nullptr && attr->form_is_constant ())
@@ -13907,17 +13907,23 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
{
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
/* Only use the attributes if they make sense together. */
- if (attr == nullptr
- || (attr->form_is_constant ()
- && attr->constant_value (0) >= 0
- && (attr->constant_value (0) + real_bit_size
- <= 8 * type->length ())))
+ std::optional<ULONGEST> bit_offset;
+ if (attr == nullptr)
+ bit_offset = 0;
+ else if (attr->form_is_constant ())
+ {
+ bit_offset = attr->unsigned_constant ();
+ if (bit_offset.has_value ()
+ && *bit_offset + real_bit_size > 8 * type->length ())
+ bit_offset.reset ();
+ }
+ if (bit_offset.has_value ())
{
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size
= real_bit_size;
if (attr != nullptr)
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset
- = attr->constant_value (0);
+ = *bit_offset;
}
}
}