Fix crash with DW_FORM_implicit_const
authorTom Tromey <tom@tromey.com>
Thu, 20 Jul 2023 21:48:46 +0000 (15:48 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 21 Jul 2023 20:03:23 +0000 (14:03 -0600)
Jakub pointed out that using DW_FORM_implicit_const with
DW_AT_bit_size would cause gdb to crash.  This happened because
DW_FORM_implicit_const is not an "unsigned" form, causing as_unsigned
to assert.  This patch fixes the problem.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30651
Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/dwarf2/read.c
gdb/testsuite/gdb.dwarf2/intbits.exp
gdb/testsuite/lib/dwarf.exp

index 3508f2c29ee0db79c2d5f4aef142fe4a4b97ef4b..b1f1c1d7257bc0220b30ddd5d381627a66151a8a 100644 (file)
@@ -15420,20 +15420,25 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT)
     {
       attr = dwarf2_attr (die, DW_AT_bit_size, cu);
-      if (attr != nullptr && attr->as_unsigned () <= 8 * type->length ())
+      if (attr != nullptr && attr->form_is_constant ())
        {
-         unsigned real_bit_size = attr->as_unsigned ();
-         attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
-         /* Only use the attributes if they make sense together.  */
-         if (attr == nullptr
-             || (attr->as_unsigned () + real_bit_size
-                 <= 8 * type->length ()))
+         unsigned real_bit_size = attr->constant_value (0);
+         if (real_bit_size >= 0 && real_bit_size <= 8 * type->length ())
            {
-             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->as_unsigned ();
+             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 ())))
+               {
+                 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);
+               }
            }
        }
     }
index c52e709316bf0ee54512a859762843ced28e36ec..cf44d26b721394a3dbd71a9d0b14d1aecf672fc0 100644 (file)
@@ -43,7 +43,7 @@ Dwarf::assemble ${asm_file} {
                {DW_AT_endianity @DW_END_little}
                {DW_AT_name "i7"}
                {DW_AT_byte_size 2 DW_FORM_udata}
-               {DW_AT_bit_size 7 DW_FORM_udata}
+               {DW_AT_bit_size 7 DW_FORM_implicit_const}
            }
 
            DW_TAG_variable {
index 434495df24a4eeba99e99bdb5e9430a79b557e54..f09da0430ab7b473fcea5d0b1bc19804972549aa 100644 (file)
@@ -693,6 +693,7 @@ namespace eval Dwarf {
                _op .ascii [_quote $value]
            }
 
+           DW_FORM_implicit_const -
            DW_FORM_flag_present {
                # We don't need to emit anything.
            }
@@ -917,6 +918,9 @@ namespace eval Dwarf {
            }
            _op .uleb128 $_constants($attr_name) $attr_name
            _op .uleb128 $_constants($attr_form) $attr_form_comment
+           if {$attr_form eq "DW_FORM_implicit_const"} {
+               _op .sleb128 $attr_value "the constant"
+           }
        }
     }