From: Tom Tromey Date: Thu, 6 Feb 2025 16:32:48 +0000 (-0700) Subject: Introduce and use attribute::unsigned_constant X-Git-Tag: binutils-2_45~1120 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e0a55ad42257771a6bed89130d45d0a24d417759;p=thirdparty%2Fbinutils-gdb.git Introduce and use attribute::unsigned_constant This introduces a new 'unsigned_constant' method on attribute. This method can be used to get the value as an unsigned number. Unsigned scalar forms are handled, and signed scalar forms are handled as well provided that the value is non-negative. Several spots in the reader that expect small DWARF-defined constants are updated to use this new method. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680 Approved-By: Simon Marchi --- diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c index 3eb32b65f14..49c0bc07d75 100644 --- a/gdb/dwarf2/attribute.c +++ b/gdb/dwarf2/attribute.c @@ -164,6 +164,27 @@ attribute::constant_value (int default_value) const /* See attribute.h. */ +std::optional +attribute::unsigned_constant () const +{ + if (form_is_strictly_signed ()) + { + if (u.snd >= 0) + return u.snd; + complaint (_("Attribute value is not unsigned (%s)"), + dwarf_form_name (form)); + } + else if (form_is_constant ()) + return u.unsnd; + + /* For DW_FORM_data16 see attribute::form_is_constant. */ + complaint (_("Attribute value is not a constant (%s)"), + dwarf_form_name (form)); + return {}; +} + +/* See attribute.h. */ + bool attribute::form_is_unsigned () const { @@ -216,21 +237,24 @@ attribute::form_requires_reprocessing () const dwarf_defaulted_attribute attribute::defaulted () const { - LONGEST value = constant_value (-1); + std::optional value = unsigned_constant (); - switch (value) + if (value.has_value ()) { - case DW_DEFAULTED_no: - case DW_DEFAULTED_in_class: - case DW_DEFAULTED_out_of_class: - return (dwarf_defaulted_attribute) value; + switch (*value) + { + case DW_DEFAULTED_no: + case DW_DEFAULTED_in_class: + case DW_DEFAULTED_out_of_class: + return (dwarf_defaulted_attribute) *value; + + default: + complaint (_("unrecognized DW_AT_defaulted value (%s)"), + plongest (*value)); + break; + } } - /* If the form was not constant, we already complained in - constant_value, so there's no need to complain again. */ - if (form_is_constant ()) - complaint (_("unrecognized DW_AT_defaulted value (%s)"), - plongest (value)); return DW_DEFAULTED_no; } @@ -239,21 +263,24 @@ attribute::defaulted () const dwarf_virtuality_attribute attribute::as_virtuality () const { - LONGEST value = constant_value (-1); + std::optional value = unsigned_constant (); - switch (value) + if (value.has_value ()) { - case DW_VIRTUALITY_none: - case DW_VIRTUALITY_virtual: - case DW_VIRTUALITY_pure_virtual: - return (dwarf_virtuality_attribute) value; + switch (*value) + { + case DW_VIRTUALITY_none: + case DW_VIRTUALITY_virtual: + case DW_VIRTUALITY_pure_virtual: + return (dwarf_virtuality_attribute) *value; + + default: + complaint (_("unrecognized DW_AT_virtuality value (%s)"), + plongest (*value)); + break; + } } - /* If the form was not constant, we already complained in - constant_value, so there's no need to complain again. */ - if (form_is_constant ()) - complaint (_("unrecognized DW_AT_virtuality value (%s)"), - plongest (value)); return DW_VIRTUALITY_none; } diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h index 6332b399c6d..824e92bf9cf 100644 --- a/gdb/dwarf2/attribute.h +++ b/gdb/dwarf2/attribute.h @@ -124,6 +124,18 @@ struct attribute bool form_is_section_offset () const; + /* Return an unsigned constant value. This only handles constant + forms (i.e., form_is_constant -- and not the extended list of + "unsigned" forms) and assumes an unsigned value is desired. This + can intended for use with DWARF-defined enumerations like DW_CC_* + or DW_INL_*, but also in situations where a nonnegative constant + integer is specified by DWARF. + + If a signed form and negative value is used, or if a non-constant + form is used, then complaint is issued and an empty value is + returned. */ + std::optional unsigned_constant () const; + /* Return non-zero if ATTR's value falls in the 'constant' class, or zero otherwise. When this function returns true, you can apply the constant_value method to it. diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c index 441a85272fb..3b80cd6c500 100644 --- a/gdb/dwarf2/cooked-indexer.c +++ b/gdb/dwarf2/cooked-indexer.c @@ -202,8 +202,11 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu, the DW_AT_calling_convention attribute was used instead as the only means available. We handle both variants then. */ case DW_AT_calling_convention: - if (attr.constant_value (DW_CC_normal) == DW_CC_program) - *flags |= IS_MAIN; + { + std::optional value = attr.unsigned_constant (); + if (value.has_value () && *value == DW_CC_program) + *flags |= IS_MAIN; + } break; case DW_AT_declaration: diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index f41723c6945..30205f2e8aa 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -8499,8 +8499,10 @@ dwarf2_func_is_main_p (struct die_info *die, struct dwarf2_cu *cu) if (dwarf2_flag_true_p (die, DW_AT_main_subprogram, cu)) return true; struct attribute *attr = dwarf2_attr (die, DW_AT_calling_convention, cu); - return (attr != nullptr - && attr->constant_value (DW_CC_normal) == DW_CC_program); + if (attr == nullptr) + return false; + std::optional value = attr->unsigned_constant (); + return value.has_value () && *value == DW_CC_program; } /* A helper to handle Ada's "Pragma Import" feature when it is applied @@ -8620,11 +8622,14 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_external, cu); bool external_p = attr != nullptr && attr->as_boolean (); attr = dwarf2_attr (die, DW_AT_inline, cu); - bool inlined_p - = (attr != nullptr - && attr->is_nonnegative () - && (attr->as_nonnegative () == DW_INL_inlined - || attr->as_nonnegative () == DW_INL_declared_inlined)); + bool inlined_p = false; + if (attr != nullptr) + { + std::optional value = attr->unsigned_constant (); + inlined_p = (value.has_value () + && (*value == DW_INL_inlined + || *value == DW_INL_declared_inlined)); + } attr = dwarf2_attr (die, DW_AT_declaration, cu); bool decl_p = attr != nullptr && attr->as_boolean (); if (!external_p && !inlined_p && !decl_p) @@ -10093,13 +10098,16 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu) attribute *attr = dwarf2_attr (die, DW_AT_accessibility, cu); if (attr != nullptr) { - LONGEST value = attr->constant_value (-1); - if (value == DW_ACCESS_public - || value == DW_ACCESS_protected - || value == DW_ACCESS_private) - return (dwarf_access_attribute) value; - complaint (_("Unhandled DW_AT_accessibility value (%s)"), - plongest (value)); + std::optional value = attr->unsigned_constant (); + if (value.has_value ()) + { + if (*value == DW_ACCESS_public + || *value == DW_ACCESS_protected + || *value == DW_ACCESS_private) + return (dwarf_access_attribute) *value; + complaint (_("Unhandled DW_AT_accessibility value (%s)"), + pulongest (*value)); + } } if (cu->header.version < 3 || cu->producer_is_gxx_lt_4_6 ()) @@ -11302,12 +11310,16 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) the die. Otherwise the calling convention remains set to the default value DW_CC_normal. */ attr = dwarf2_attr (die, DW_AT_calling_convention, cu); - if (attr != nullptr - && is_valid_DW_AT_calling_convention_for_type (attr->constant_value (0))) + if (attr != nullptr) { - ALLOCATE_CPLUS_STRUCT_TYPE (type); - TYPE_CPLUS_CALLING_CONVENTION (type) - = (enum dwarf_calling_convention) (attr->constant_value (0)); + std::optional value = attr->unsigned_constant (); + if (value.has_value () + && is_valid_DW_AT_calling_convention_for_type (*value)) + { + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_CPLUS_CALLING_CONVENTION (type) + = (enum dwarf_calling_convention) *value; + } } attr = dwarf2_attr (die, DW_AT_byte_size, cu); @@ -11773,19 +11785,23 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order) attribute *attr = dwarf2_attr (die, DW_AT_endianity, cu); if (attr != nullptr && attr->form_is_constant ()) { - int endianity = attr->constant_value (0); + std::optional endianity = attr->unsigned_constant (); - switch (endianity) + if (endianity.has_value ()) { - case DW_END_big: - new_order = BFD_ENDIAN_BIG; - break; - case DW_END_little: - new_order = BFD_ENDIAN_LITTLE; - break; - default: - complaint (_("DW_AT_endianity has unrecognized value %d"), endianity); - break; + switch (*endianity) + { + case DW_END_big: + new_order = BFD_ENDIAN_BIG; + break; + case DW_END_little: + new_order = BFD_ENDIAN_LITTLE; + break; + default: + complaint (_("DW_AT_endianity has unrecognized value %s"), + pulongest (*endianity)); + break; + } } } @@ -12439,9 +12455,10 @@ read_array_order (struct die_info *die, struct dwarf2_cu *cu) if (attr != nullptr) { - LONGEST val = attr->constant_value (-1); - if (val == DW_ORD_row_major || val == DW_ORD_col_major) - return (enum dwarf_array_dim_ordering) val; + std::optional val = attr->unsigned_constant (); + if (val.has_value () && + (*val == DW_ORD_row_major || *val == DW_ORD_col_major)) + return (enum dwarf_array_dim_ordering) *val; } /* GNU F77 is a special case, as at 08/2004 array type info is the @@ -12847,7 +12864,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type; struct attribute *attr_byte_size; struct attribute *attr_address_class; - int byte_size, addr_class; + int byte_size; struct type *target_type; target_type = die_type (die, cu); @@ -12866,8 +12883,10 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) byte_size = cu_header->addr_size; attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu); + ULONGEST addr_class; if (attr_address_class) - addr_class = attr_address_class->constant_value (DW_ADDR_none); + addr_class = (attr_address_class->unsigned_constant () + .value_or (DW_ADDR_none)); else addr_class = DW_ADDR_none; @@ -13269,10 +13288,14 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) the subroutine die. Otherwise set the calling convention to the default value DW_CC_normal. */ attr = dwarf2_attr (die, DW_AT_calling_convention, cu); - if (attr != nullptr - && is_valid_DW_AT_calling_convention_for_subroutine (attr->constant_value (0))) - TYPE_CALLING_CONVENTION (ftype) - = (enum dwarf_calling_convention) attr->constant_value (0); + if (attr != nullptr) + { + std::optional value = attr->unsigned_constant (); + if (value.has_value () + && is_valid_DW_AT_calling_convention_for_subroutine (*value)) + TYPE_CALLING_CONVENTION (ftype) + = (enum dwarf_calling_convention) *value; + } else if (cu->producer_is_xlc_opencl ()) TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL; else @@ -13863,12 +13886,17 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) struct objfile *objfile = cu->per_objfile->objfile; struct type *type; struct attribute *attr; - int encoding = 0, bits = 0; + ULONGEST encoding = 0; + int bits = 0; const char *name; attr = dwarf2_attr (die, DW_AT_encoding, cu); - if (attr != nullptr && attr->form_is_constant ()) - encoding = attr->constant_value (0); + if (attr != nullptr) + { + std::optional value = attr->unsigned_constant (); + if (value.has_value ()) + encoding = *value; + } attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr != nullptr) bits = attr->constant_value (0) * TARGET_CHAR_BIT; @@ -15699,7 +15727,7 @@ leb128_size (const gdb_byte *buf) /* Converts DWARF language names to GDB language names. */ enum language -dwarf_lang_to_enum_language (unsigned int lang) +dwarf_lang_to_enum_language (ULONGEST lang) { enum language language; @@ -19730,8 +19758,15 @@ cutu_reader::prepare_one_comp_unit (struct dwarf2_cu *cu, } else if (attr != nullptr) { - lang = dwarf_lang_to_enum_language (attr->constant_value (0)); - dw_lang = (dwarf_source_language) attr->constant_value (0); + std::optional lang_val = attr->unsigned_constant (); + if (lang_val.has_value ()) + { + lang = dwarf_lang_to_enum_language (*lang_val); + if (lang_val <= DW_LANG_hi_user) + dw_lang = (dwarf_source_language) *lang_val; + } + else + lang = language_minimal; } else lang = pretend_language; diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index be6549beec7..164c3136cf8 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -1047,7 +1047,7 @@ private: /* Converts DWARF language names to GDB language names. */ -enum language dwarf_lang_to_enum_language (unsigned int lang); +enum language dwarf_lang_to_enum_language (ULONGEST lang); /* Get the dwarf2_per_objfile associated to OBJFILE. */