Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -9,7 +9,11 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSER_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSER_H +#include "DWARFDIE.h" #include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "lldb/Core/Declaration.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/CompilerDecl.h" @@ -59,4 +63,136 @@ static lldb::AccessType GetAccessTypeFromDWARF(uint32_t dwarf_accessibility); }; +/// Parsed form of all attributes that are relevant for type reconstruction. +/// Some attributes are relevant for all kinds of types (declaration), while +/// others are only meaningful to a specific type (is_virtual). +struct ParsedDWARFTypeAttributes { + explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); + + lldb::AccessType accessibility = lldb::eAccessNone; + const char *mangled_name = nullptr; + lldb_private::ConstString name; + lldb_private::Declaration decl; + DWARFDIE object_pointer; + DWARFFormValue abstract_origin; + DWARFFormValue containing_type; + DWARFFormValue signature; + DWARFFormValue specification; + DWARFFormValue type; + lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; + llvm::Optional byte_size; + size_t calling_convention = llvm::dwarf::DW_CC_normal; + uint32_t bit_stride = 0; + uint32_t byte_stride = 0; + uint32_t encoding = 0; + uint32_t attr_flags = 0; + + // clang-format off + enum DWARFAttributeFlags : unsigned { + /// Represents no attributes. + eDWARFAttributeNone = 0u, + /// Whether it is an artificially generated symbol. + eDWARFAttributeArtificial = 1u << 0, + /// Whether it has explicit property of member function. + eDWARFAttributeExplicit = 1u << 1, + /// Whether it is a forward declaration. + eDWARFAttributeForwardDecl = 1u << 2, + /// Whether it is an inlined symbol. + eDWARFAttributeInline = 1u << 3, + /// Whether it is a scoped enumeration (class enum). + eDWARFAttributeScopedEnum = 1u << 4, + /// Whether it has vector attribute. + eDWARFAttributeVector = 1u << 5, + /// Whether it has virtuality attribute. + eDWARFAttributeVirtual = 1u << 6, + /// Whether it is an external symbol. + eDWARFAttributeExternal = 1u << 7, + /// Whether it export symbols to the containing scope. + eDWARFAttributeExportSymbols = 1u << 8, + /// Whether it is an Objective-C direct call. + eDWARFAttributeObjCDirect = 1u << 9, + /// Whether it is an Objective-C complete type. + eDWARFAttributeObjCCompleteType = 1u << 10, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/eDWARFAttributeObjCCompleteType), + }; + // clang-format on + + void setIsArtificial() { + attr_flags |= eDWARFAttributeArtificial; + } + bool isArtificial() const { + return attr_flags & eDWARFAttributeArtificial; + } + + void setIsExplicit() { + attr_flags |= eDWARFAttributeExplicit; + } + bool isExplicit() const { + return attr_flags & eDWARFAttributeExplicit; + } + + void setIsForwardDeclaration() { + attr_flags |= eDWARFAttributeForwardDecl; + } + bool isForwardDeclaration() const { + return attr_flags & eDWARFAttributeForwardDecl; + } + + void setIsInline() { + attr_flags |= eDWARFAttributeInline; + } + bool isInline() const { + return attr_flags & eDWARFAttributeInline; + } + + void setIsScopedEnum() { + attr_flags |= eDWARFAttributeScopedEnum; + } + bool isScopedEnum() const { + return attr_flags & eDWARFAttributeScopedEnum; + } + + void setIsVector() { + attr_flags |= eDWARFAttributeVector; + } + bool isVector() const { + return attr_flags & eDWARFAttributeVector; + } + + void setIsVirtual() { + attr_flags |= eDWARFAttributeVirtual; + } + bool isVirtual() const { + return attr_flags & eDWARFAttributeVirtual; + } + + void setIsExternal() { + attr_flags |= eDWARFAttributeExternal; + } + bool isExternal() const { + return attr_flags & eDWARFAttributeExternal; + } + + void setIsExportsSymbols() { + attr_flags |= eDWARFAttributeExportSymbols; + } + bool isExportsSymbols() const { + return attr_flags & eDWARFAttributeExportSymbols; + } + + void setIsObjCDirectCall() { + attr_flags |= eDWARFAttributeObjCDirect; + } + bool isObjCDirectCall() const { + return attr_flags & eDWARFAttributeObjCDirect; + } + + void setIsObjCCompleteType() { + attr_flags |= eDWARFAttributeObjCCompleteType; + } + bool isObjCCompleteType() const { + return attr_flags & eDWARFAttributeObjCCompleteType; + } +}; + #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSER_H Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp @@ -9,6 +9,7 @@ #include "DWARFASTParser.h" #include "DWARFAttribute.h" #include "DWARFDIE.h" +#include "DWARFUnit.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/SymbolFile.h" @@ -112,3 +113,141 @@ } return eAccessNone; } + +ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) + continue; + switch (attr) { + case DW_AT_abstract_origin: + abstract_origin = form_value; + break; + + case DW_AT_accessibility: + accessibility = DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned()); + break; + + case DW_AT_artificial: + if (form_value.Boolean()) + setIsArtificial(); + break; + + case DW_AT_bit_stride: + bit_stride = form_value.Unsigned(); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + + case DW_AT_byte_stride: + byte_stride = form_value.Unsigned(); + break; + + case DW_AT_calling_convention: + calling_convention = form_value.Unsigned(); + break; + + case DW_AT_containing_type: + containing_type = form_value; + break; + + case DW_AT_decl_file: + // die.GetCU() can differ if DW_AT_specification uses DW_FORM_ref_addr. + decl.SetFile( + attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + + case DW_AT_declaration: + if (form_value.Boolean()) + setIsForwardDeclaration(); + break; + + case DW_AT_encoding: + encoding = form_value.Unsigned(); + break; + + case DW_AT_enum_class: + if (form_value.Boolean()) + setIsScopedEnum(); + break; + + case DW_AT_explicit: + if (form_value.Boolean()) + setIsExplicit(); + break; + + case DW_AT_external: + if (form_value.Unsigned()) + setIsExternal(); + break; + + case DW_AT_inline: + if (form_value.Boolean()) + setIsInline(); + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + mangled_name = form_value.AsCString(); + break; + + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + + case DW_AT_object_pointer: + object_pointer = form_value.Reference(); + break; + + case DW_AT_signature: + signature = form_value; + break; + + case DW_AT_specification: + specification = form_value; + break; + + case DW_AT_type: + type = form_value; + break; + + case DW_AT_virtuality: + if (form_value.Unsigned()) + setIsVirtual(); + break; + + case DW_AT_APPLE_objc_complete_type: + if (form_value.Signed()) + setIsObjCCompleteType(); + break; + + case DW_AT_APPLE_objc_direct: + setIsObjCDirectCall(); + break; + + case DW_AT_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + + case DW_AT_GNU_vector: + if (form_value.Boolean()) + setIsVector(); + break; + case DW_AT_export_symbols: + if (form_value.Boolean()) + setIsExportsSymbols(); + break; + } + } +} Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -252,39 +252,4 @@ lldb_private::ClangASTImporter::LayoutInfo &layout_info); }; -/// Parsed form of all attributes that are relevant for type reconstruction. -/// Some attributes are relevant for all kinds of types (declaration), while -/// others are only meaningful to a specific type (is_virtual) -struct ParsedDWARFTypeAttributes { - explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); - - lldb::AccessType accessibility = lldb::eAccessNone; - bool is_artificial = false; - bool is_complete_objc_class = false; - bool is_explicit = false; - bool is_forward_declaration = false; - bool is_inline = false; - bool is_scoped_enum = false; - bool is_vector = false; - bool is_virtual = false; - bool is_objc_direct_call = false; - bool exports_symbols = false; - clang::StorageClass storage = clang::SC_None; - const char *mangled_name = nullptr; - lldb_private::ConstString name; - lldb_private::Declaration decl; - DWARFDIE object_pointer; - DWARFFormValue abstract_origin; - DWARFFormValue containing_type; - DWARFFormValue signature; - DWARFFormValue specification; - DWARFFormValue type; - lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; - llvm::Optional byte_size; - size_t calling_convention = llvm::dwarf::DW_CC_normal; - uint32_t bit_stride = 0; - uint32_t byte_stride = 0; - uint32_t encoding = 0; -}; - #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -286,135 +286,6 @@ ForcefullyCompleteType(type); } -ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { - DWARFAttributes attributes; - size_t num_attributes = die.GetAttributes(attributes); - for (size_t i = 0; i < num_attributes; ++i) { - dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (!attributes.ExtractFormValueAtIndex(i, form_value)) - continue; - switch (attr) { - case DW_AT_abstract_origin: - abstract_origin = form_value; - break; - - case DW_AT_accessibility: - accessibility = DWARFASTParser::GetAccessTypeFromDWARF(form_value.Unsigned()); - break; - - case DW_AT_artificial: - is_artificial = form_value.Boolean(); - break; - - case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - - case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); - break; - - case DW_AT_calling_convention: - calling_convention = form_value.Unsigned(); - break; - - case DW_AT_containing_type: - containing_type = form_value; - break; - - case DW_AT_decl_file: - // die.GetCU() can differ if DW_AT_specification uses DW_FORM_ref_addr. - decl.SetFile( - attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - - case DW_AT_encoding: - encoding = form_value.Unsigned(); - break; - - case DW_AT_enum_class: - is_scoped_enum = form_value.Boolean(); - break; - - case DW_AT_explicit: - is_explicit = form_value.Boolean(); - break; - - case DW_AT_external: - if (form_value.Unsigned()) - storage = clang::SC_Extern; - break; - - case DW_AT_inline: - is_inline = form_value.Boolean(); - break; - - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: - mangled_name = form_value.AsCString(); - break; - - case DW_AT_name: - name.SetCString(form_value.AsCString()); - break; - - case DW_AT_object_pointer: - object_pointer = form_value.Reference(); - break; - - case DW_AT_signature: - signature = form_value; - break; - - case DW_AT_specification: - specification = form_value; - break; - - case DW_AT_type: - type = form_value; - break; - - case DW_AT_virtuality: - is_virtual = form_value.Boolean(); - break; - - case DW_AT_APPLE_objc_complete_type: - is_complete_objc_class = form_value.Signed(); - break; - - case DW_AT_APPLE_objc_direct: - is_objc_direct_call = true; - break; - - case DW_AT_APPLE_runtime_class: - class_language = (LanguageType)form_value.Signed(); - break; - - case DW_AT_GNU_vector: - is_vector = form_value.Boolean(); - break; - case DW_AT_export_symbols: - exports_symbols = form_value.Boolean(); - break; - } - } -} - static std::string GetUnitName(const DWARFDIE &die) { if (DWARFUnit *unit = die.GetCU()) return unit->GetAbsolutePath().GetPath(); @@ -764,7 +635,7 @@ const dw_tag_t tag = die.Tag(); TypeSP type_sp; - if (attrs.is_forward_declaration) { + if (attrs.isForwardDeclaration()) { type_sp = ParseTypeFromClangModule(sc, die, log); if (type_sp) return type_sp; @@ -833,7 +704,7 @@ attrs.name.GetStringRef(), GetClangDeclContextContainingDIE(die, nullptr), GetOwningClangModule(die), attrs.decl, enumerator_clang_type, - attrs.is_scoped_enum); + attrs.isScopedEnum()); } else { enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type); } @@ -1012,8 +883,8 @@ clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType( class_opaque_type, attrs.name.GetCString(), clang_type, - attrs.accessibility, attrs.is_artificial, is_variadic, - attrs.is_objc_direct_call); + attrs.accessibility, attrs.isArtificial(), is_variadic, + attrs.isObjCDirectCall()); type_handled = objc_method_decl != NULL; if (type_handled) { LinkDeclContextToDIE(objc_method_decl, die); @@ -1161,14 +1032,14 @@ m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), attrs.mangled_name, - clang_type, attrs.accessibility, attrs.is_virtual, - is_static, attrs.is_inline, attrs.is_explicit, - is_attr_used, attrs.is_artificial); + clang_type, attrs.accessibility, attrs.isVirtual(), + is_static, attrs.isInline(), attrs.isExplicit(), + is_attr_used, attrs.isArtificial()); type_handled = cxx_method_decl != NULL; // Artificial methods are always handled even when we // don't create a new declaration for them. - type_handled |= attrs.is_artificial; + type_handled |= attrs.isArtificial(); if (cxx_method_decl) { LinkDeclContextToDIE(cxx_method_decl, die); @@ -1265,8 +1136,8 @@ function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - GetOwningClangModule(die), name, clang_type, attrs.storage, - attrs.is_inline); + GetOwningClangModule(die), name, clang_type, attrs.isExternal() ? clang::SC_Extern : clang::SC_None, + attrs.isInline()); std::free(name_buf); if (has_template_params) { @@ -1276,7 +1147,7 @@ ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type, - attrs.storage, attrs.is_inline); + attrs.isExternal() ? clang::SC_Extern : clang::SC_None, attrs.isInline()); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( containing_decl_ctx, GetOwningClangModule(die), @@ -1350,7 +1221,7 @@ for (auto pos = array_info->element_orders.rbegin(); pos != end; ++pos) { num_elements = *pos; clang_type = m_ast.CreateArrayType(array_element_type, num_elements, - attrs.is_vector); + attrs.isVector()); array_element_type = clang_type; array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements @@ -1358,7 +1229,7 @@ } } else { clang_type = - m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector); + m_ast.CreateArrayType(array_element_type, 0, attrs.isVector()); } ConstString empty_name; TypeSP type_sp = std::make_shared( @@ -1618,12 +1489,12 @@ // // Note that there is no DW_AT_declaration and there are no children, // and the byte size is zero. - attrs.is_forward_declaration = true; + attrs.setIsForwardDeclaration(); } if (attrs.class_language == eLanguageTypeObjC || attrs.class_language == eLanguageTypeObjC_plus_plus) { - if (!attrs.is_complete_objc_class && + if (!attrs.isObjCCompleteType() && die.Supports_DW_AT_APPLE_objc_complete_type()) { // We have a valid eSymbolTypeObjCClass class symbol whose name // matches the current objective C class that we are trying to find @@ -1664,7 +1535,7 @@ } } - if (attrs.is_forward_declaration) { + if (attrs.isForwardDeclaration()) { // We have a forward declaration to a type and we need to try and // find a full declaration. We look in the current type index just in // case we have a forward declaration followed by an actual @@ -1783,7 +1654,7 @@ clang_type = m_ast.CreateRecordType( decl_ctx, GetOwningClangModule(die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, - &metadata, attrs.exports_symbols); + &metadata, attrs.isExportsSymbols()); } } @@ -1795,7 +1666,7 @@ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward, - TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); + TypePayloadClang(OptionalClangModuleID(), attrs.isObjCCompleteType())); // Add our type to the unique type map so we don't end up creating many // copies of the same type over and over in the ASTContext for our @@ -1807,7 +1678,7 @@ dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, *unique_ast_entry_up); - if (!attrs.is_forward_declaration) { + if (!attrs.isForwardDeclaration()) { // Always start the definition for a class type so that if the class // has child classes or types that require the class to be created // for use as their decl contexts the class will be ready to accept Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -9,8 +9,11 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFATTRIBUTE_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFATTRIBUTE_H +#include "DWARFDIE.h" #include "DWARFDefines.h" #include "DWARFFormValue.h" +#include "lldb/Core/Declaration.h" +#include "lldb/Utility/ConstString.h" #include "llvm/ADT/SmallVector.h" #include Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -10,6 +10,8 @@ #include "DWARFUnit.h" #include "DWARFDebugInfo.h" +using namespace lldb; + DWARFAttributes::DWARFAttributes() : m_infos() {} DWARFAttributes::~DWARFAttributes() = default;