[06/13] Use attribute::unsigned_constant for DW_AT_data_bit_offset

Message ID 20250320-attribute-madness-v1-6-79d42789f881@adacore.com
State New
Headers
Series More work on DW_FORM_* and sign handling |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_gdb_build--master-arm fail Patch failed to apply

Commit Message

Tom Tromey March 20, 2025, 7:27 p.m. UTC
  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(-)
  

Patch

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index bd3951a263c43597b1b77afa901e3c17947a71a4..18f03f0eb7ce552ef5383a34b1112cb12230678d 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -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;
 		}
 	    }
 	}