diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF')
32 files changed, 1500 insertions, 2593 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 9ae047da13258..0a5073b8cd9eb 100644 --- a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -21,30 +21,30 @@ std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( Module &module, DWARFDataExtractor apple_names, DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) { - auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_names, debug_str, ".apple_names"); if (!apple_names_table_up->IsValid()) apple_names_table_up.reset(); auto apple_namespaces_table_up = - llvm::make_unique<DWARFMappedHash::MemoryTable>( + std::make_unique<DWARFMappedHash::MemoryTable>( apple_namespaces, debug_str, ".apple_namespaces"); if (!apple_namespaces_table_up->IsValid()) apple_namespaces_table_up.reset(); - auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_types, debug_str, ".apple_types"); if (!apple_types_table_up->IsValid()) apple_types_table_up.reset(); - auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_objc, debug_str, ".apple_objc"); if (!apple_objc_table_up->IsValid()) apple_objc_table_up.reset(); if (apple_names_table_up || apple_names_table_up || apple_types_table_up || apple_objc_table_up) - return llvm::make_unique<AppleDWARFIndex>( + return std::make_unique<AppleDWARFIndex>( module, std::move(apple_names_table_up), std::move(apple_namespaces_table_up), std::move(apple_types_table_up), std::move(apple_objc_table_up)); @@ -110,6 +110,7 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, const bool has_qualified_name_hash = m_apple_types_up->GetHeader().header_data.ContainsAtom( DWARFMappedHash::eAtomTypeQualNameHash); + const ConstString type_name(context[0].name); const dw_tag_t tag = context[0].tag; if (has_tag && has_qualified_name_hash) { @@ -119,12 +120,32 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( type_name.GetStringRef(), tag, qualified_name_hash, offsets); - } else if (has_tag) { + return; + } + + if (has_tag) { + // When searching for a scoped type (for example, + // "std::vector<int>::const_iterator") searching for the innermost + // name alone ("const_iterator") could yield many false + // positives. By searching for the parent type ("vector<int>") + // first we can avoid extracting type DIEs from object files that + // would fail the filter anyway. + if (!has_qualified_name_hash && (context.GetSize() > 1) && + (context[1].tag == DW_TAG_class_type || + context[1].tag == DW_TAG_structure_type)) { + DIEArray class_matches; + m_apple_types_up->FindByName(context[1].name, class_matches); + if (class_matches.empty()) + return; + } + if (log) m_module.LogMessage(log, "FindByNameAndTag()"); m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); - } else - m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); + return; + } + + m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); } void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index e7927b31b9c31..7ee4727cde914 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -28,7 +28,6 @@ public: virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb_private::Log *log, bool *type_is_new_ptr) = 0; virtual lldb_private::Function * @@ -48,8 +47,8 @@ public: virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) = 0; - virtual std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) = 0; + virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) = 0; static llvm::Optional<lldb_private::SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index b85ab54a10d3a..636e6032b8775 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -9,7 +9,6 @@ #include <stdlib.h> #include "DWARFASTParserClang.h" -#include "DWARFDIE.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDefines.h" @@ -28,7 +27,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Target/Language.h" @@ -144,23 +143,27 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { // If this type comes from a Clang module, look in the DWARF section // of the pcm file in the module cache. Clang generates DWO skeleton // units as breadcrumbs to find them. - std::vector<CompilerContext> decl_context; + llvm::SmallVector<CompilerContext, 4> decl_context; die.GetDeclContext(decl_context); TypeMap dwo_types; - if (!dwo_module_sp->GetSymbolVendor()->FindTypes(decl_context, true, - dwo_types)) { + // The type in the Clang module must have the same language as the current CU. + LanguageSet languages; + languages.Insert(die.GetCU()->GetLanguageType()); + dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types); + if (dwo_types.Empty()) { if (!IsClangModuleFwdDecl(die)) return TypeSP(); - // Since this this type is defined in one of the Clang modules imported by - // this symbol file, search all of them. + // Since this type is defined in one of the Clang modules imported + // by this symbol file, search all of them. auto &sym_file = die.GetCU()->GetSymbolFileDWARF(); for (const auto &name_module : sym_file.getExternalTypeModules()) { if (!name_module.second) continue; - SymbolVendor *sym_vendor = name_module.second->GetSymbolVendor(); - if (sym_vendor->FindTypes(decl_context, true, dwo_types)) + name_module.second->GetSymbolFile()->FindTypes(decl_context, + languages, dwo_types); + if (dwo_types.GetSize()) break; } } @@ -188,7 +191,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward)); - dwarf->GetTypeList()->Insert(type_sp); + dwarf->GetTypeList().Insert(type_sp); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); if (tag_decl) @@ -228,42 +231,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, } } -namespace { -/// 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 ParsedTypeAttributes { - explicit ParsedTypeAttributes(const DWARFDIE &die); - - AccessType accessibility = 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; - clang::StorageClass storage = clang::SC_None; - const char *mangled_name = nullptr; - ConstString name; - Declaration decl; - DWARFDIE object_pointer; - DWARFFormValue abstract_origin; - DWARFFormValue containing_type; - DWARFFormValue signature; - DWARFFormValue specification; - DWARFFormValue type; - LanguageType class_language = eLanguageTypeUnknown; - llvm::Optional<uint64_t> 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; -}; -} // namespace - -ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) { +ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { DWARFAttributes attributes; size_t num_attributes = die.GetAttributes(attributes); for (size_t i = 0; i < num_attributes; ++i) { @@ -390,13 +358,17 @@ static std::string GetUnitName(const DWARFDIE &die) { } TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, - const DWARFDIE &die, Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) { if (type_is_new_ptr) *type_is_new_ptr = false; if (!die) return nullptr; + + Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS)); + SymbolFileDWARF *dwarf = die.GetDWARF(); if (log) { DWARFDIE context_die; @@ -420,11 +392,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - ParsedTypeAttributes attrs(die); + ParsedDWARFTypeAttributes attrs(die); if (DWARFDIE signature_die = attrs.signature.Reference()) { if (TypeSP type_sp = - ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { + ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); if (clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(signature_die)) @@ -434,7 +406,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, return nullptr; } - TypeList *type_list = dwarf->GetTypeList(); if (type_is_new_ptr) *type_is_new_ptr = true; @@ -562,7 +533,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, bool function_type_is_new_pointer; TypeSP lldb_function_type_sp = ParseTypeFromDWARF( - sc, function_type, log, &function_type_is_new_pointer); + sc, function_type, &function_type_is_new_pointer); if (lldb_function_type_sp) { clang_type = m_ast.CreateBlockPointerType( @@ -660,370 +631,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: { - // UniqueDWARFASTType is large, so don't create a local variables on - // the stack, put it on the heap. This function is often called - // recursively and clang isn't good and sharing the stack space for - // variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up( - new UniqueDWARFASTType()); - - ConstString unique_typename(attrs.name); - Declaration unique_decl(attrs.decl); - - if (attrs.name) { - if (Language::LanguageIsCPlusPlus(cu_language)) { - // For C++, we rely solely upon the one definition rule that says - // only one thing can exist at a given decl context. We ignore the - // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) - unique_typename = ConstString(qualified_name); - unique_decl.Clear(); - } - - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), - *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } - - if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC) { - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - attrs.is_forward_declaration = true; - } - - if (attrs.class_language == eLanguageTypeObjC || - attrs.class_language == eLanguageTypeObjC_plus_plus) { - if (!attrs.is_complete_objc_class && - 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 - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = - dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, attrs.name, true); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - if (attrs.is_forward_declaration) { - // 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 - // declarations in the DWARF. If this fails, we need to look - // elsewhere... - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, trying to find complete type", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - - // See if the type comes from a DWO module and if so, track down that - // type. - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - assert(tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - // If your decl context is a record that was imported from another - // AST context (in the gmodules case), we need to make sure the type - // backing the Decl is complete before adding children to it. This is - // not an issue in the non-gmodules case because the debug info will - // always contain a full definition of parent types in that case. - CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - attrs.name.GetCString()); - - if (attrs.accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - attrs.accessibility = default_accessibility; - } - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - - if (attrs.name.GetStringRef().contains('<')) { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, - attrs.name.GetCString(), - tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); - } - - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; - - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } - } - - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType( - decl_ctx, attrs.accessibility, attrs.name.GetCString(), - tag_decl_kind, attrs.class_language, &metadata); - } - } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, - attrs.byte_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &attrs.decl, clang_type, - Type::eResolveStateForward); - - type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); - - // 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 - // module - unique_ast_entry_up->m_type_sp = type_sp; - unique_ast_entry_up->m_die = die; - unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); - dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, - *unique_ast_entry_up); - - if (attrs.is_forward_declaration && die.HasChildren()) { - // Check to see if the DIE actually has a definition, some version of - // GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have - // subprogram, members, or inheritance, so we can't trust it - DWARFDIE child_die = die.GetFirstChild(); - while (child_die) { - switch (child_die.Tag()) { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die.Clear(); - attrs.is_forward_declaration = false; - break; - default: - child_die = child_die.GetSibling(); - break; - } - } - } - - if (!attrs.is_forward_declaration) { - // 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 - // these child definitions. - if (!die.HasChildren()) { - // No children for this struct/union/class, lets finish it - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), attrs.name.GetCString()); - } - - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = - ClangASTContext::GetAsRecordDecl(clang_type); - - if (record_decl) { - GetClangASTImporter().InsertRecordDecl( - record_decl, ClangASTImporter::LayoutInfo()); - } - } - } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (attrs.class_language != eLanguageTypeObjC && - attrs.class_language != eLanguageTypeObjC_plus_plus) - ClangASTContext::StartTagDeclarationDefinition(clang_type); - - // Leave this as a forward declaration until we need to know the - // details of the type. lldb_private::Type will automatically call - // the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" When the definition - // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( - ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - // Can't assume m_ast.GetSymbolFile() is actually a - // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple - // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie() - [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = - die.GetID(); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - } - } - - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) { - record_decl->setHasTrivialSpecialMemberForCall(); - } - } - - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) - record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); - } - - } break; + assert((!type_sp && !clang_type) && + "Did not expect partially computed structure-like type"); + TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs); + return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp); + } case DW_TAG_enumeration_type: { if (attrs.is_forward_declaration) { @@ -1395,8 +1007,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, is_attr_used, attrs.is_artificial); 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; - if (type_handled) { + if (cxx_method_decl) { LinkDeclContextToDIE( ClangASTContext::GetAsDeclContext(cxx_method_decl), die); @@ -1407,12 +1022,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName( object_pointer_name.c_str()); - if (log) - log->Printf( - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast<void *>(cxx_method_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast<void *>(cxx_method_decl)); } m_ast.SetMetadata(cxx_method_decl, metadata); } else { @@ -1520,11 +1134,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf("Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast<void *>(function_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast<void *>(function_decl)); } m_ast.SetMetadata(function_decl, metadata); } @@ -1651,31 +1265,418 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, break; } - if (type_sp.get()) { - DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + // TODO: We should consider making the switch above exhaustive to simplify + // control flow in ParseTypeFromDWARF. Then, we could simply replace this + // return statement with a call to llvm_unreachable. + return UpdateSymbolContextScopeForType(sc, die, type_sp); +} + +TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( + const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) { + if (!type_sp) + return type_sp; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + TypeList &type_list = dwarf->GetTypeList(); + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit || + sc_parent_tag == DW_TAG_partial_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } else { + symbol_context_scope = sc.module_sp.get(); + } + + if (symbol_context_scope != NULL) + type_sp->SetSymbolContextScope(symbol_context_scope); - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit || - sc_parent_tag == DW_TAG_partial_unit) { - symbol_context_scope = sc.comp_unit; - } else if (sc.function != NULL && sc_parent_die) { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } else - symbol_context_scope = sc.module_sp.get(); + // We are ready to put this type into the uniqued list up at the module + // level. + type_list.Insert(type_sp); - if (symbol_context_scope != NULL) { - type_sp->SetSymbolContextScope(symbol_context_scope); + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; +} + +TypeSP +DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs) { + TypeSP type_sp; + CompilerType clang_type; + const dw_tag_t tag = die.Tag(); + SymbolFileDWARF *dwarf = die.GetDWARF(); + LanguageType cu_language = die.GetLanguage(); + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS); + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively and + // clang isn't good at sharing the stack space for variables in different + // blocks. + auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>(); + + ConstString unique_typename(attrs.name); + Declaration unique_decl(attrs.decl); + + if (attrs.name) { + if (Language::LanguageIsCPlusPlus(cu_language)) { + // For C++, we rely solely upon the one definition rule that says + // only one thing can exist at a given decl context. We ignore the + // file and line that things are declared on. + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); + } + + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + LinkDeclContextToDIE( + GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); + return type_sp; + } } + } - // We are ready to put this type into the uniqued list up at the module - // level - type_list->Insert(type_sp); + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_union_type) { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_class_type) { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + attrs.is_forward_declaration = true; + } + + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && + 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 + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, attrs.name, true); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " + "incomplete objc type, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + + if (attrs.is_forward_declaration) { + // 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 + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, trying to find complete type", + static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + + // See if the type comes from a DWO module and if so, track down that + // type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert(tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); + + // If your decl context is a record that was imported from another + // AST context (in the gmodules case), we need to make sure the type + // backing the Decl is complete before adding children to it. This is + // not an issue in the non-gmodules case because the debug info will + // always contain a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + attrs.name.GetCString()); + + if (attrs.accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + attrs.accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + + if (attrs.name.GetStringRef().contains('<')) { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, + template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); + } + return TypeSP(); + } + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, class_template_decl, tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); + } + } + + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType( + decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, + attrs.class_language, &metadata); + } + } + + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang types for + // function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, + attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateForward); + + type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); + + // 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 + // module + unique_ast_entry_up->m_type_sp = type_sp; + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); + dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, + *unique_ast_entry_up); + + if (attrs.is_forward_declaration && die.HasChildren()) { + // Check to see if the DIE actually has a definition, some version of + // GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have + // subprogram, members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) { + switch (child_die.Tag()) { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + attrs.is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } + + if (!attrs.is_forward_declaration) { + // 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 + // these child definitions. + if (!die.HasChildren()) { + // No children for this struct/union/class, lets finish it + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); + } + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = + ClangASTContext::GetAsRecordDecl(clang_type); + + if (record_decl) { + GetClangASTImporter().InsertRecordDecl( + record_decl, ClangASTImporter::LayoutInfo()); + } + } + } else if (clang_type_was_created) { + // Start the definition if the class is not objective C since the + // underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ + // class/union/structs we want to start the definition in case the + // class is needed as the declaration context for a contained class + // or type without the need to complete that type.. + + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition(clang_type); + + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie() + [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = + die.GetID(); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + } + } + + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl && record_decl->getDefinition()) { + record_decl->setHasTrivialSpecialMemberForCall(); + } + } + + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); } return type_sp; } @@ -2181,14 +2182,16 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, return false; } -std::vector<DWARFDIE> DWARFASTParserClang::GetDIEForDeclContext( +void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) { - std::vector<DWARFDIE> result; - for (auto it = m_decl_ctx_to_die.find( - (clang::DeclContext *)decl_context.GetOpaqueDeclContext()); - it != m_decl_ctx_to_die.end(); it++) - result.push_back(it->second); - return result; + auto opaque_decl_ctx = + (clang::DeclContext *)decl_context.GetOpaqueDeclContext(); + for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx); + it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx; + it = m_decl_ctx_to_die.erase(it)) + for (DWARFDIE decl = it->second.GetFirstChild(); decl; + decl = decl.GetSibling()) + GetClangDeclForDIE(decl); } CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) { @@ -2530,9 +2533,11 @@ bool DWARFASTParserClang::ParseChildMembers( if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * nullptr, // RegisterContext * - module_sp, debug_info_data, die.GetCU(), block_offset, - block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -2965,11 +2970,12 @@ bool DWARFASTParserClang::ParseChildMembers( uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp, - debug_info_data, die.GetCU(), - block_offset, block_length, - eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + if (DWARFExpression::Evaluate( + nullptr, nullptr, module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -3270,6 +3276,8 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, array_info.element_orders.push_back(num_elements); } } break; + default: + break; } } return array_info; @@ -3672,11 +3680,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_size != dst_size) { if (src_size != 0 && dst_size != 0) { - if (log) - log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " - "but they didn't have the same size (src=%d, dst=%d)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_size, dst_size); + LLDB_LOGF(log, + "warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " + "but they didn't have the same size (src=%d, dst=%d)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), src_size, + dst_size); } fast_path = false; @@ -3690,12 +3698,12 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); if (src_die.Tag() != dst_die.Tag()) { - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_die.GetTagAsCString(), - dst_die.GetOffset(), dst_die.GetTagAsCString()); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_die.GetTagAsCString(), + dst_die.GetOffset(), dst_die.GetTagAsCString()); fast_path = false; } @@ -3706,12 +3714,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_name == dst_name || (strcmp(src_name, dst_name) == 0)) continue; - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_name, dst_die.GetOffset(), - dst_name); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_name, dst_die.GetOffset(), dst_name); fast_path = false; } @@ -3733,32 +3740,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x for " - "0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x for " + "0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "uniquing type %p (uid=0x%" PRIx64 + ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } else { @@ -3778,39 +3784,36 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf("uniquing type %p (uid=0x%" PRIx64 - ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), - src_child_type->GetID(), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } else { - if (log) - log->Printf("warning: couldn't find a match for 0x%8.8x", - dst_die.GetOffset()); + LLDB_LOGF(log, "warning: couldn't find a match for 0x%8.8x", + dst_die.GetOffset()); failures.push_back(dst_die); } @@ -3836,32 +3839,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } @@ -3872,10 +3874,10 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( ConstString dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx); - if (log) - log->Printf("warning: need to create artificial method for 0x%8.8x for " - "method '%s'", - dst_die.GetOffset(), dst_name_artificial.GetCString()); + LLDB_LOGF(log, + "warning: need to create artificial method for 0x%8.8x for " + "method '%s'", + dst_die.GetOffset(), dst_name_artificial.GetCString()); failures.push_back(dst_die); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 5b5d83d659325..106f9254a4495 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -15,7 +15,10 @@ #include "llvm/ADT/SmallVector.h" #include "DWARFASTParser.h" +#include "DWARFDIE.h" #include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "LogChannelDWARF.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/ClangASTContext.h" @@ -29,6 +32,8 @@ class CompileUnit; class DWARFDebugInfoEntry; class SymbolFileDWARF; +struct ParsedDWARFTypeAttributes; + class DWARFASTParserClang : public DWARFASTParser { public: DWARFASTParserClang(lldb_private::ClangASTContext &ast); @@ -37,7 +42,7 @@ public: // DWARFASTParser interface. lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, lldb_private::Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) override; lldb_private::Function * @@ -51,8 +56,8 @@ public: lldb_private::CompilerDecl GetDeclForUIDFromDWARF(const DWARFDIE &die) override; - std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override; + void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) override; lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; @@ -63,9 +68,28 @@ public: lldb_private::ClangASTImporter &GetClangASTImporter(); protected: + /// Protected typedefs and members. + /// @{ class DelayedAddObjCClassProperty; typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList; + typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> + DIEToDeclContextMap; + typedef std::multimap<const clang::DeclContext *, const DWARFDIE> + DeclContextToDIEMap; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> + DIEToDeclMap; + typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; + + lldb_private::ClangASTContext &m_ast; + DIEToDeclMap m_die_to_decl; + DeclToDIEMap m_decl_to_die; + DIEToDeclContextMap m_die_to_decl_ctx; + DeclContextToDIEMap m_decl_ctx_to_die; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; + /// @} + clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); @@ -103,6 +127,10 @@ protected: bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die); + /// Parse a structure, class, or union type DIE. + lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); + lldb_private::Type *GetTypeForDIE(const DWARFDIE &die); clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); @@ -123,29 +151,52 @@ protected: void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die); + /// If \p type_sp is valid, calculate and set its symbol context scope, and + /// update the type list for its backing symbol file. + /// + /// Returns \p type_sp. + lldb::TypeSP + UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log); // Return true if this type is a declaration to a type in an external // module. lldb::ModuleSP GetModuleForType(const DWARFDIE &die); +}; - typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> - DIEToDeclContextMap; - // typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> - // DeclContextToDIEMap; - typedef std::multimap<const clang::DeclContext *, const DWARFDIE> - DeclContextToDIEMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> - DIEToDeclMap; - typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; - - lldb_private::ClangASTContext &m_ast; - DIEToDeclMap m_die_to_decl; - DeclToDIEMap m_decl_to_die; - DIEToDeclContextMap m_die_to_decl_ctx; - DeclContextToDIEMap m_decl_ctx_to_die; - std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; +/// 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; + 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<uint64_t> 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 // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index 6128163a29269..741669b05754b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() - : m_code(InvalidCode), m_tag(0), m_has_children(0), m_attributes() {} + : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0), + m_attributes() {} DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) @@ -33,7 +34,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, return DWARFEnumState::Complete; m_attributes.clear(); - m_tag = data.GetULEB128(offset_ptr); + m_tag = static_cast<dw_tag_t>(data.GetULEB128(offset_ptr)); if (m_tag == DW_TAG_null) return llvm::make_error<llvm::object::GenericBinaryError>( "abbrev decl requires non-null tag."); @@ -68,7 +69,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, } bool DWARFAbbreviationDeclaration::IsValid() { - return m_code != 0 && m_tag != 0; + return m_code != 0 && m_tag != llvm::dwarf::DW_TAG_null; } uint32_t diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index 96adb72c95322..033105efdc533 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/Log.h" using namespace lldb_private; @@ -29,7 +30,7 @@ dw_tag_t DWARFBaseDIE::Tag() const { if (m_die) return m_die->Tag(); else - return 0; + return llvm::dwarf::DW_TAG_null; } const char *DWARFBaseDIE::GetTagAsCString() const { @@ -102,19 +103,22 @@ SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const { return nullptr; } -lldb_private::TypeSystem *DWARFBaseDIE::GetTypeSystem() const { - if (m_cu) - return m_cu->GetTypeSystem(); - else - return nullptr; +llvm::Expected<lldb_private::TypeSystem &> DWARFBaseDIE::GetTypeSystem() const { + if (!m_cu) + return llvm::make_error<llvm::StringError>( + "Unable to get TypeSystem, no compilation unit available", + llvm::inconvertibleErrorCode()); + return m_cu->GetTypeSystem(); } DWARFASTParser *DWARFBaseDIE::GetDWARFParser() const { - lldb_private::TypeSystem *type_system = GetTypeSystem(); - if (type_system) - return type_system->GetDWARFParser(); - else + auto type_system_or_err = GetTypeSystem(); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DWARFASTParser"); return nullptr; + } + return type_system_or_err->GetDWARFParser(); } bool DWARFBaseDIE::HasChildren() const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 0058043017cdb..9652d7946e876 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -12,6 +12,8 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" + class DIERef; class DWARFASTParser; class DWARFAttributes; @@ -55,7 +57,7 @@ public: llvm::Optional<DIERef> GetDIERef() const; - lldb_private::TypeSystem *GetTypeSystem() const; + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem() const; DWARFASTParser *GetDWARFParser() const; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 9d97ca15a2529..5ee0687995a1d 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -342,7 +342,8 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { } } -void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { +void DWARFDIE::GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const { const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) return; @@ -351,40 +352,33 @@ void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { parent.GetDeclContext(context); switch (tag) { case DW_TAG_module: - context.push_back( - CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + context.push_back({CompilerContextKind::Module, ConstString(GetName())}); break; case DW_TAG_namespace: - context.push_back(CompilerContext(CompilerContextKind::Namespace, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); break; case DW_TAG_structure_type: - context.push_back(CompilerContext(CompilerContextKind::Structure, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); break; case DW_TAG_union_type: - context.push_back( - CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + context.push_back({CompilerContextKind::Union, ConstString(GetName())}); break; case DW_TAG_class_type: - context.push_back( - CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + context.push_back({CompilerContextKind::Class, ConstString(GetName())}); break; case DW_TAG_enumeration_type: - context.push_back(CompilerContext(CompilerContextKind::Enumeration, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); break; case DW_TAG_subprogram: - context.push_back(CompilerContext(CompilerContextKind::Function, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Function, ConstString(GetPubname())}); break; case DW_TAG_variable: - context.push_back(CompilerContext(CompilerContextKind::Variable, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Variable, ConstString(GetPubname())}); break; case DW_TAG_typedef: - context.push_back( - CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); break; default: break; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 7753ec9008cb5..a779c589611a9 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -78,8 +78,8 @@ public: /// Return this DIE's decl context as it is needed to look up types /// in Clang's -gmodules debug info format. - void - GetDeclContext(std::vector<lldb_private::CompilerContext> &context) const; + void GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const; // Getting attribute values from the DIE. // diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index ccf33e6dc3414..c8da2381353e3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -66,8 +66,8 @@ void DWARFDebugAranges::Dump(Log *log) const { for (size_t i = 0; i < num_entries; ++i) { const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); if (entry) - log->Printf("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, - entry->GetRangeBase(), entry->GetRangeEnd()); + LLDB_LOGF(log, "0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, + entry->GetRangeBase(), entry->GetRangeEnd()); } } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 100f35f8c6b02..1e04baca2c58c 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -38,7 +38,7 @@ llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { if (m_cu_aranges_up) return *m_cu_aranges_up; - m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>(); + m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); const DWARFDataExtractor &debug_aranges_data = m_context.getOrLoadArangesData(); if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 2f55b7d40ed9e..8c0fbeb4b717b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -192,7 +192,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, *offset_ptr = offset; return true; } else { - m_tag = 0; + m_tag = llvm::dwarf::DW_TAG_null; m_has_children = false; return true; // NULL debug tag entry } @@ -340,18 +340,14 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - *frame_base = DWARFExpression(module, data, cu, - block_offset, block_length); + *frame_base = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), cu); } else { - const DWARFDataExtractor &debug_loc_data = dwarf.DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - cu, debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - *frame_base = - DWARFExpression(module, debug_loc_data, cu, - debug_loc_offset, loc_list_length); + DataExtractor data = dwarf.DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + *frame_base = DWARFExpression(module, data, cu); if (lo_pc != LLDB_INVALID_ADDRESS) { assert(lo_pc >= cu->GetBaseAddress()); frame_base->SetLocationListSlide(lo_pc - diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 1e7b5f27642d3..25c885608d859 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -31,7 +31,7 @@ public: DWARFDebugInfoEntry() : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), - m_has_children(false), m_abbr_idx(0), m_tag(0) {} + m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {} explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } bool operator==(const DWARFDebugInfoEntry &rhs) const; @@ -178,8 +178,9 @@ protected: // a single NULL terminating child. m_has_children : 1; uint16_t m_abbr_idx; - uint16_t m_tag; // A copy of the DW_TAG value so we don't have to go through - // the compile unit abbrev table + /// A copy of the DW_TAG value so we don't have to go through the compile + /// unit abbrev table + dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; }; #endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp deleted file mode 100644 index 953089fee22b5..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugLine.h" - -//#define ENABLE_DEBUG_PRINTF // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!! -#include <assert.h> - -#include <memory> - -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/Module.h" -#include "lldb/Host/Host.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Timer.h" - -#include "DWARFUnit.h" -#include "LogChannelDWARF.h" -#include "SymbolFileDWARF.h" - -using namespace lldb; -using namespace lldb_private; -using namespace std; - -// Parse -// -// Parse all information in the debug_line_data into an internal -// representation. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { - m_lineTableMap.clear(); - lldb::offset_t offset = 0; - LineTable::shared_ptr line_table_sp(new LineTable); - while (debug_line_data.ValidOffset(offset)) { - const lldb::offset_t debug_line_offset = offset; - - if (line_table_sp.get() == nullptr) - break; - - if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) { - // Make sure we don't don't loop infinitely - if (offset <= debug_line_offset) - break; - // DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", - // debug_line_offset); - m_lineTableMap[debug_line_offset] = line_table_sp; - line_table_sp = std::make_shared<LineTable>(); - } else - ++offset; // Try next byte in line table - } -} - -void DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor &debug_line_data) { - if (m_lineTableMap.empty()) - Parse(debug_line_data); -} - -// DWARFDebugLine::GetLineTable -DWARFDebugLine::LineTable::shared_ptr -DWARFDebugLine::GetLineTable(const dw_offset_t offset) const { - DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr; - LineTableConstIter pos = m_lineTableMap.find(offset); - if (pos != m_lineTableMap.end()) - line_table_shared_ptr = pos->second; - return line_table_shared_ptr; -} - -// Parse -// -// Parse the entire line table contents calling callback each time a new -// prologue is parsed and every time a new row is to be added to the line -// table. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, - void *userData) { - lldb::offset_t offset = 0; - if (debug_line_data.ValidOffset(offset)) { - if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr)) - ++offset; // Skip to next byte in .debug_line section - } -} - -namespace { -struct EntryDescriptor { - dw_sleb128_t code; - dw_sleb128_t form; -}; - -static std::vector<EntryDescriptor> -ReadDescriptors(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr) { - std::vector<EntryDescriptor> ret; - uint8_t n = debug_line_data.GetU8(offset_ptr); - for (uint8_t i = 0; i < n; ++i) { - EntryDescriptor ent; - ent.code = debug_line_data.GetULEB128(offset_ptr); - ent.form = debug_line_data.GetULEB128(offset_ptr); - ret.push_back(ent); - } - return ret; -} -} // namespace - -// DWARFDebugLine::ParsePrologue -bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, - Prologue *prologue, DWARFUnit *dwarf_cu) { - const lldb::offset_t prologue_offset = *offset_ptr; - - // DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr); - - prologue->Clear(); - uint32_t i; - const char *s; - prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr); - prologue->version = debug_line_data.GetU16(offset_ptr); - if (prologue->version < 2 || prologue->version > 5) - return false; - - if (prologue->version >= 5) { - prologue->address_size = debug_line_data.GetU8(offset_ptr); - prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr); - } - - prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr); - const lldb::offset_t end_prologue_offset = - prologue->prologue_length + *offset_ptr; - prologue->min_inst_length = debug_line_data.GetU8(offset_ptr); - if (prologue->version >= 4) - prologue->maximum_operations_per_instruction = - debug_line_data.GetU8(offset_ptr); - else - prologue->maximum_operations_per_instruction = 1; - prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr); - prologue->line_base = debug_line_data.GetU8(offset_ptr); - prologue->line_range = debug_line_data.GetU8(offset_ptr); - prologue->opcode_base = debug_line_data.GetU8(offset_ptr); - - prologue->standard_opcode_lengths.reserve(prologue->opcode_base - 1); - - for (i = 1; i < prologue->opcode_base; ++i) { - uint8_t op_len = debug_line_data.GetU8(offset_ptr); - prologue->standard_opcode_lengths.push_back(op_len); - } - - if (prologue->version >= 5) { - std::vector<EntryDescriptor> dirEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < dirCount; ++i) { - for (EntryDescriptor &ent : dirEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (ent.code != DW_LNCT_path) { - if (!value.SkipValue(debug_line_data, offset_ptr)) - return false; - continue; - } - - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - prologue->include_directories.push_back(value.AsCString()); - } - } - - std::vector<EntryDescriptor> filesEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen; - uint8_t n = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < n; ++i) { - FileNameEntry entry; - for (EntryDescriptor &ent : filesEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - - switch (ent.code) { - case DW_LNCT_path: - entry.name = value.AsCString(); - break; - case DW_LNCT_directory_index: - entry.dir_idx = value.Unsigned(); - break; - case DW_LNCT_timestamp: - entry.mod_time = value.Unsigned(); - break; - case DW_LNCT_size: - entry.length = value.Unsigned(); - break; - case DW_LNCT_MD5: - assert(value.Unsigned() == 16); - std::uninitialized_copy_n(value.BlockData(), 16, - entry.checksum.Bytes.begin()); - break; - default: - break; - } - } - - if (seen.insert(entry.checksum.words()).second) - prologue->file_names.push_back(entry); - } - } else { - while (*offset_ptr < end_prologue_offset) { - s = debug_line_data.GetCStr(offset_ptr); - if (s && s[0]) - prologue->include_directories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.GetCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.name = name; - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - prologue->file_names.push_back(fileEntry); - } else - break; - } - } - - // XXX GNU as is broken for 64-Bit DWARF - if (*offset_ptr != end_prologue_offset) { - Host::SystemLog(Host::eSystemLogWarning, - "warning: parsing line table prologue at 0x%8.8" PRIx64 - " should have ended at 0x%8.8" PRIx64 - " but it ended at 0x%8.8" PRIx64 "\n", - prologue_offset, end_prologue_offset, *offset_ptr); - } - return end_prologue_offset; -} - -bool DWARFDebugLine::ParseSupportFiles( - const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) { - lldb::offset_t offset = stmt_list; - - Prologue prologue; - if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) { - Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue " - "at 0x%8.8x (parsing ended around " - "0x%8.8" PRIx64 "\n", - stmt_list, offset); - return false; - } - - FileSpec file_spec; - std::string remapped_file; - - for (uint32_t file_idx = 1; - prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(), - dwarf_cu->GetPathStyle(), file_spec); - ++file_idx) { - if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) - file_spec.SetFile(remapped_file, FileSpec::Style::native); - support_files.Append(file_spec); - } - return true; -} - -// ParseStatementTable -// -// Parse a single line table (prologue and all rows) and call the callback -// function once for the prologue (row in state will be zero) and each time a -// row is to be added to the line table. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) { - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE)); - Prologue::shared_ptr prologue(new Prologue()); - - const dw_offset_t debug_line_offset = *offset_ptr; - - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])", - debug_line_offset); - - if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) { - if (log) - log->Error("failed to parse DWARF line table prologue"); - // Restore our offset and return false to indicate failure! - *offset_ptr = debug_line_offset; - return false; - } - - if (log) - prologue->Dump(log); - - const dw_offset_t end_offset = - debug_line_offset + prologue->total_length + - (debug_line_data.GetDWARFSizeofInitialLength()); - - State state(prologue, log, callback, userData); - - while (*offset_ptr < end_offset) { - // DEBUG_PRINTF("0x%8.8x: ", *offset_ptr); - uint8_t opcode = debug_line_data.GetU8(offset_ptr); - - if (opcode == 0) { - // Extended Opcodes always start with a zero opcode followed by a uleb128 - // length so you can skip ones you don't know about - lldb::offset_t ext_offset = *offset_ptr; - dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr); - dw_offset_t arg_size = len - (*offset_ptr - ext_offset); - - // DEBUG_PRINTF("Extended: <%2u> ", len); - uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr); - switch (sub_opcode) { - case DW_LNE_end_sequence: - // Set the end_sequence register of the state machine to true and - // append a row to the matrix using the current values of the state- - // machine registers. Then reset the registers to the initial values - // specified above. Every statement program sequence must end with a - // DW_LNE_end_sequence instruction which creates a row whose address is - // that of the byte after the last target machine instruction of the - // sequence. - state.end_sequence = true; - state.AppendRowToMatrix(*offset_ptr); - state.Reset(); - break; - - case DW_LNE_set_address: - // Takes a single relocatable address as an operand. The size of the - // operand is the size appropriate to hold an address on the target - // machine. Set the address register to the value given by the - // relocatable address. All of the other statement program opcodes that - // affect the address register add a delta to it. This instruction - // stores a relocatable value into it instead. - if (arg_size == 4) - state.address = debug_line_data.GetU32(offset_ptr); - else // arg_size == 8 - state.address = debug_line_data.GetU64(offset_ptr); - break; - - case DW_LNE_define_file: - // Takes 4 arguments. The first is a null terminated string containing - // a source file name. The second is an unsigned LEB128 number - // representing the directory index of the directory in which the file - // was found. The third is an unsigned LEB128 number representing the - // time of last modification of the file. The fourth is an unsigned - // LEB128 number representing the length in bytes of the file. The time - // and length fields may contain LEB128(0) if the information is not - // available. - // - // The directory index represents an entry in the include_directories - // section of the statement program prologue. The index is LEB128(0) if - // the file was found in the current directory of the compilation, - // LEB128(1) if it was found in the first directory in the - // include_directories section, and so on. The directory index is - // ignored for file names that represent full path names. - // - // The files are numbered, starting at 1, in the order in which they - // appear; the names in the prologue come before names defined by the - // DW_LNE_define_file instruction. These numbers are used in the file - // register of the state machine. - { - FileNameEntry fileEntry; - fileEntry.name = debug_line_data.GetCStr(offset_ptr); - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - state.prologue->file_names.push_back(fileEntry); - } - break; - - default: - // Length doesn't include the zero opcode byte or the length itself, - // but it does include the sub_opcode, so we have to adjust for that - // below - (*offset_ptr) += arg_size; - break; - } - } else if (opcode < prologue->opcode_base) { - switch (opcode) { - // Standard Opcodes - case DW_LNS_copy: - // Takes no arguments. Append a row to the matrix using the current - // values of the state-machine registers. Then set the basic_block - // register to false. - state.AppendRowToMatrix(*offset_ptr); - break; - - case DW_LNS_advance_pc: - // Takes a single unsigned LEB128 operand, multiplies it by the - // min_inst_length field of the prologue, and adds the result to the - // address register of the state machine. - state.address += - debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length; - break; - - case DW_LNS_advance_line: - // Takes a single signed LEB128 operand and adds that value to the line - // register of the state machine. - state.line += debug_line_data.GetSLEB128(offset_ptr); - break; - - case DW_LNS_set_file: - // Takes a single unsigned LEB128 operand and stores it in the file - // register of the state machine. - state.file = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_set_column: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.column = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_negate_stmt: - // Takes no arguments. Set the is_stmt register of the state machine to - // the logical negation of its current value. - state.is_stmt = !state.is_stmt; - break; - - case DW_LNS_set_basic_block: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.basic_block = true; - break; - - case DW_LNS_const_add_pc: - // Takes no arguments. Add to the address register of the state machine - // the address increment value corresponding to special opcode 255. The - // motivation for DW_LNS_const_add_pc is this: when the statement - // program needs to advance the address by a small amount, it can use a - // single special opcode, which occupies a single byte. When it needs - // to advance the address by up to twice the range of the last special - // opcode, it can use DW_LNS_const_add_pc followed by a special opcode, - // for a total of two bytes. Only if it needs to advance the address by - // more than twice that range will it need to use both - // DW_LNS_advance_pc and a special opcode, requiring three or more - // bytes. - { - uint8_t adjust_opcode = 255 - prologue->opcode_base; - dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * - prologue->min_inst_length; - state.address += addr_offset; - } - break; - - case DW_LNS_fixed_advance_pc: - // Takes a single uhalf operand. Add to the address register of the - // state machine the value of the (unencoded) operand. This is the only - // extended opcode that takes an argument that is not a variable length - // number. The motivation for DW_LNS_fixed_advance_pc is this: existing - // assemblers cannot emit DW_LNS_advance_pc or special opcodes because - // they cannot encode LEB128 numbers or judge when the computation of a - // special opcode overflows and requires the use of DW_LNS_advance_pc. - // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead, - // sacrificing compression. - state.address += debug_line_data.GetU16(offset_ptr); - break; - - case DW_LNS_set_prologue_end: - // Takes no arguments. Set the prologue_end register of the state - // machine to true - state.prologue_end = true; - break; - - case DW_LNS_set_epilogue_begin: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.epilogue_begin = true; - break; - - case DW_LNS_set_isa: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.isa = debug_line_data.GetULEB128(offset_ptr); - break; - - default: - // Handle any unknown standard opcodes here. We know the lengths of - // such opcodes because they are specified in the prologue as a - // multiple of LEB128 operands for each opcode. - { - uint8_t i; - assert(static_cast<size_t>(opcode - 1) < - prologue->standard_opcode_lengths.size()); - const uint8_t opcode_length = - prologue->standard_opcode_lengths[opcode - 1]; - for (i = 0; i < opcode_length; ++i) - debug_line_data.Skip_LEB128(offset_ptr); - } - break; - } - } else { - // Special Opcodes - - // A special opcode value is chosen based on the amount that needs - // to be added to the line and address registers. The maximum line - // increment for a special opcode is the value of the line_base field in - // the header, plus the value of the line_range field, minus 1 (line base - // + line range - 1). If the desired line increment is greater than the - // maximum line increment, a standard opcode must be used instead of a - // special opcode. The "address advance" is calculated by dividing the - // desired address increment by the minimum_instruction_length field from - // the header. The special opcode is then calculated using the following - // formula: - // - // opcode = (desired line increment - line_base) + (line_range * address - // advance) + opcode_base - // - // If the resulting opcode is greater than 255, a standard opcode must be - // used instead. - // - // To decode a special opcode, subtract the opcode_base from the opcode - // itself to give the adjusted opcode. The amount to increment the - // address register is the result of the adjusted opcode divided by the - // line_range multiplied by the minimum_instruction_length field from the - // header. That is: - // - // address increment = (adjusted opcode / line_range) * - // minimum_instruction_length - // - // The amount to increment the line register is the line_base plus the - // result of the adjusted opcode modulo the line_range. That is: - // - // line increment = line_base + (adjusted opcode % line_range) - - uint8_t adjust_opcode = opcode - prologue->opcode_base; - dw_addr_t addr_offset = - (adjust_opcode / prologue->line_range) * prologue->min_inst_length; - int32_t line_offset = - prologue->line_base + (adjust_opcode % prologue->line_range); - state.line += line_offset; - state.address += addr_offset; - state.AppendRowToMatrix(*offset_ptr); - } - } - - state.Finalize(*offset_ptr); - - return end_offset; -} - -// ParseStatementTableCallback -static void ParseStatementTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData; - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table, so lets keep a reference to the - // prologue using the supplied shared pointer - line_table->prologue = state.prologue; - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - // We have a new row, lets append it - line_table->AppendRow(state); - } -} - -// ParseStatementTable -// -// Parse a line table at offset and populate the LineTable class with the -// prologue and all rows. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - LineTable *line_table, DWARFUnit *dwarf_cu) { - return ParseStatementTable(debug_line_data, offset_ptr, - ParseStatementTableCallback, line_table, dwarf_cu); -} - -inline bool DWARFDebugLine::Prologue::IsValid() const { - return SymbolFileDWARF::SupportedVersion(version); -} - -// DWARFDebugLine::Prologue::Dump -void DWARFDebugLine::Prologue::Dump(Log *log) { - uint32_t i; - - log->Printf("Line table prologue:"); - log->Printf(" total_length: 0x%8.8x", total_length); - log->Printf(" version: %u", version); - log->Printf("prologue_length: 0x%8.8x", prologue_length); - log->Printf("min_inst_length: %u", min_inst_length); - log->Printf("default_is_stmt: %u", default_is_stmt); - log->Printf(" line_base: %i", line_base); - log->Printf(" line_range: %u", line_range); - log->Printf(" opcode_base: %u", opcode_base); - - for (i = 0; i < standard_opcode_lengths.size(); ++i) { - log->Printf("standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i + 1), - standard_opcode_lengths[i]); - } - - if (!include_directories.empty()) { - for (i = 0; i < include_directories.size(); ++i) { - log->Printf("include_directories[%3u] = '%s'", i + 1, - include_directories[i]); - } - } - - if (!file_names.empty()) { - log->PutCString(" Dir Mod Time File Len File Name"); - log->PutCString(" ---- ---------- ---------- " - "---------------------------"); - for (i = 0; i < file_names.size(); ++i) { - const FileNameEntry &fileEntry = file_names[i]; - log->Printf("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s", i + 1, - fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length, - fileEntry.name); - } - } -} - -// DWARFDebugLine::ParsePrologue::Append -// -// Append the contents of the prologue to the binary stream buffer -// void -// DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const -//{ -// uint32_t i; -// -// buff.Append32(total_length); -// buff.Append16(version); -// buff.Append32(prologue_length); -// buff.Append8(min_inst_length); -// buff.Append8(default_is_stmt); -// buff.Append8(line_base); -// buff.Append8(line_range); -// buff.Append8(opcode_base); -// -// for (i=0; i<standard_opcode_lengths.size(); ++i) -// buff.Append8(standard_opcode_lengths[i]); -// -// for (i=0; i<include_directories.size(); ++i) -// buff.AppendCStr(include_directories[i].c_str()); -// buff.Append8(0); // Terminate the include directory section with empty -// string -// -// for (i=0; i<file_names.size(); ++i) -// { -// buff.AppendCStr(file_names[i].name.c_str()); -// buff.Append32_as_ULEB128(file_names[i].dir_idx); -// buff.Append32_as_ULEB128(file_names[i].mod_time); -// buff.Append32_as_ULEB128(file_names[i].length); -// } -// buff.Append8(0); // Terminate the file names section with empty string -//} - -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, - const FileSpec &comp_dir, - FileSpec::Style style, - FileSpec &file) const { - uint32_t idx = file_idx - 1; // File indexes are 1 based... - if (idx < file_names.size()) { - file.SetFile(file_names[idx].name, style); - if (file.IsRelative()) { - if (file_names[idx].dir_idx > 0) { - const uint32_t dir_idx = file_names[idx].dir_idx - 1; - if (dir_idx < include_directories.size()) { - file.PrependPathComponent(include_directories[dir_idx]); - if (!file.IsRelative()) - return true; - } - } - - if (comp_dir) - file.PrependPathComponent(comp_dir); - } - return true; - } - return false; -} - -void DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row &state) { - rows.push_back(state); -} - -// Compare function for the binary search in -// DWARFDebugLine::LineTable::LookupAddress() -static bool FindMatchingAddress(const DWARFDebugLine::Row &row1, - const DWARFDebugLine::Row &row2) { - return row1.address < row2.address; -} - -// DWARFDebugLine::LineTable::LookupAddress -uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, - dw_addr_t cu_high_pc) const { - uint32_t index = UINT32_MAX; - if (!rows.empty()) { - // Use the lower_bound algorithm to perform a binary search since we know - // that our line table data is ordered by address. - DWARFDebugLine::Row row; - row.address = address; - Row::const_iterator begin_pos = rows.begin(); - Row::const_iterator end_pos = rows.end(); - Row::const_iterator pos = - lower_bound(begin_pos, end_pos, row, FindMatchingAddress); - if (pos == end_pos) { - if (address < cu_high_pc) - return rows.size() - 1; - } else { - // Rely on fact that we are using a std::vector and we can do pointer - // arithmetic to find the row index (which will be one less that what we - // found since it will find the first position after the current address) - // since std::vector iterators are just pointers to the container type. - index = pos - begin_pos; - if (pos->address > address) { - if (index > 0) - --index; - else - index = UINT32_MAX; - } - } - } - return index; // Failed to find address -} - -// DWARFDebugLine::Row::Row -DWARFDebugLine::Row::Row(bool default_is_stmt) - : address(0), line(1), column(0), file(1), is_stmt(default_is_stmt), - basic_block(false), end_sequence(false), prologue_end(false), - epilogue_begin(false), isa(0) {} - -// Called after a row is appended to the matrix -void DWARFDebugLine::Row::PostAppend() { - basic_block = false; - prologue_end = false; - epilogue_begin = false; -} - -// DWARFDebugLine::Row::Reset -void DWARFDebugLine::Row::Reset(bool default_is_stmt) { - address = 0; - line = 1; - column = 0; - file = 1; - is_stmt = default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - isa = 0; -} -// DWARFDebugLine::Row::Dump -void DWARFDebugLine::Row::Dump(Log *log) const { - log->Printf("0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s", address, line, - column, file, isa, is_stmt ? " is_stmt" : "", - basic_block ? " basic_block" : "", - prologue_end ? " prologue_end" : "", - epilogue_begin ? " epilogue_begin" : "", - end_sequence ? " end_sequence" : ""); -} - -// Compare function LineTable structures -static bool AddressLessThan(const DWARFDebugLine::Row &a, - const DWARFDebugLine::Row &b) { - return a.address < b.address; -} - -// Insert a row at the correct address if the addresses can be out of order -// which can only happen when we are linking a line table that may have had -// it's contents rearranged. -void DWARFDebugLine::Row::Insert(Row::collection &state_coll, - const Row &state) { - // If we don't have anything yet, or if the address of the last state in our - // line table is less than the current one, just append the current state - if (state_coll.empty() || AddressLessThan(state_coll.back(), state)) { - state_coll.push_back(state); - } else { - // Do a binary search for the correct entry - pair<Row::iterator, Row::iterator> range(equal_range( - state_coll.begin(), state_coll.end(), state, AddressLessThan)); - - // If the addresses are equal, we can safely replace the previous entry - // with the current one if the one it is replacing is an end_sequence - // entry. We currently always place an extra end sequence when ever we exit - // a valid address range for a function in case the functions get - // rearranged by optimizations or by order specifications. These extra end - // sequences will disappear by getting replaced with valid consecutive - // entries within a compile unit if there are no gaps. - if (range.first == range.second) { - state_coll.insert(range.first, state); - } else { - if ((distance(range.first, range.second) == 1) && - range.first->end_sequence == true) { - *range.first = state; - } else { - state_coll.insert(range.second, state); - } - } - } -} - -// DWARFDebugLine::State::State -DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l, - DWARFDebugLine::State::Callback cb, void *userData) - : Row(p->default_is_stmt), prologue(p), log(l), callback(cb), - callbackUserData(userData), row(StartParsingLineTable) { - // Call the callback with the initial row state of zero for the prologue - if (callback) - callback(0, *this, callbackUserData); -} - -// DWARFDebugLine::State::Reset -void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); } - -// DWARFDebugLine::State::AppendRowToMatrix -void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) { - // Each time we are to add an entry into the line table matrix call the - // callback function so that someone can do something with the current state - // of the state machine (like build a line table or dump the line table!) - if (log) { - if (row == 0) { - log->PutCString("Address Line Column File ISA Flags"); - log->PutCString( - "------------------ ------ ------ ------ --- -------------"); - } - Dump(log); - } - - ++row; // Increase the row number before we call our callback for a real row - if (callback) - callback(offset, *this, callbackUserData); - PostAppend(); -} - -// DWARFDebugLine::State::Finalize -void DWARFDebugLine::State::Finalize(dw_offset_t offset) { - // Call the callback with a special row state when we are done parsing a line - // table - row = DoneParsingLineTable; - if (callback) - callback(offset, *this, callbackUserData); -} - -// void -// DWARFDebugLine::AppendLineTableData -//( -// const DWARFDebugLine::Prologue* prologue, -// const DWARFDebugLine::Row::collection& state_coll, -// const uint32_t addr_size, -// BinaryStreamBuf &debug_line_data -//) -//{ -// if (state_coll.empty()) -// { -// // We have no entries, just make an empty line table -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// } -// else -// { -// DWARFDebugLine::Row::const_iterator pos; -// Row::const_iterator end = state_coll.end(); -// bool default_is_stmt = prologue->default_is_stmt; -// const DWARFDebugLine::Row reset_state(default_is_stmt); -// const DWARFDebugLine::Row* prev_state = &reset_state; -// const int32_t max_line_increment_for_special_opcode = -// prologue->MaxLineIncrementForSpecialOpcode(); -// for (pos = state_coll.begin(); pos != end; ++pos) -// { -// const DWARFDebugLine::Row& curr_state = *pos; -// int32_t line_increment = 0; -// dw_addr_t addr_offset = curr_state.address - prev_state->address; -// dw_addr_t addr_advance = (addr_offset) / prologue->min_inst_length; -// line_increment = (int32_t)(curr_state.line - prev_state->line); -// -// // If our previous state was the reset state, then let's emit the -// // address to keep GDB's DWARF parser happy. If we don't start each -// // sequence with a DW_LNE_set_address opcode, the line table won't -// // get slid properly in GDB. -// -// if (prev_state == &reset_state) -// { -// debug_line_data.Append8(0); // Extended opcode -// debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of -// opcode bytes -// debug_line_data.Append8(DW_LNE_set_address); -// debug_line_data.AppendMax64(curr_state.address, addr_size); -// addr_advance = 0; -// } -// -// if (prev_state->file != curr_state.file) -// { -// debug_line_data.Append8(DW_LNS_set_file); -// debug_line_data.Append32_as_ULEB128(curr_state.file); -// } -// -// if (prev_state->column != curr_state.column) -// { -// debug_line_data.Append8(DW_LNS_set_column); -// debug_line_data.Append32_as_ULEB128(curr_state.column); -// } -// -// // Don't do anything fancy if we are at the end of a sequence -// // as we don't want to push any extra rows since the -// DW_LNE_end_sequence -// // will push a row itself! -// if (curr_state.end_sequence) -// { -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push the end sequence on! -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// -// prev_state = &reset_state; -// } -// else -// { -// if (line_increment || addr_advance) -// { -// if (line_increment > max_line_increment_for_special_opcode) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// line_increment = 0; -// } -// -// uint32_t special_opcode = (line_increment >= -// prologue->line_base) ? ((line_increment - -// prologue->line_base) + (prologue->line_range * addr_advance) -// + prologue->opcode_base) : 256; -// if (special_opcode > 255) -// { -// // Both the address and line won't fit in one special -// opcode -// // check to see if just the line advance will? -// uint32_t special_opcode_line = ((line_increment >= -// prologue->line_base) && (line_increment != 0)) ? -// ((line_increment - prologue->line_base) + -// prologue->opcode_base) : 256; -// -// -// if (special_opcode_line > 255) -// { -// // Nope, the line advance won't fit by itself, check -// the address increment by itself -// uint32_t special_opcode_addr = addr_advance ? -// ((0 - prologue->line_base) + -// (prologue->line_range * addr_advance) + -// prologue->opcode_base) : 256; -// -// if (special_opcode_addr > 255) -// { -// // Neither the address nor the line will fit in -// a -// // special opcode, we must manually enter both -// then -// // do a DW_LNS_copy to push a row (special -// opcode -// // automatically imply a new row is pushed) -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push a row onto the line table manually -// debug_line_data.Append8(DW_LNS_copy); -// -// } -// else -// { -// // The address increment alone will fit into a -// special opcode -// // so modify our line change, then issue a -// special opcode -// // for the address increment and it will push a -// row into the -// // line table -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line -// table -// debug_line_data.Append8(special_opcode_addr); -// } -// } -// else -// { -// // The line change alone will fit into a special -// opcode -// // so modify our address increment first, then issue -// a -// // special opcode for the line change and it will -// push -// // a row into the line table -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode_line); -// } -// } -// else -// { -// // Advance of line and address will fit into a single -// byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode); -// } -// } -// prev_state = &curr_state; -// } -// } -// } -//} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h deleted file mode 100644 index 0d236ca686b50..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ /dev/null @@ -1,227 +0,0 @@ -//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFDebugLine_h_ -#define SymbolFileDWARF_DWARFDebugLine_h_ - -#include <map> -#include <string> -#include <vector> - -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-private.h" - -#include "DWARFDataExtractor.h" -#include "DWARFDefines.h" - -#include "llvm/Support/MD5.h" - -class DWARFUnit; -class SymbolFileDWARF; - -// DWARFDebugLine -class DWARFDebugLine { -public: - // FileNameEntry - struct FileNameEntry { - FileNameEntry() - : name(nullptr), dir_idx(0), mod_time(0), length(0), checksum() {} - - const char *name; - dw_sleb128_t dir_idx; - dw_sleb128_t mod_time; - dw_sleb128_t length; - llvm::MD5::MD5Result checksum; - }; - - // Prologue - struct Prologue { - - Prologue() - : total_length(0), version(0), prologue_length(0), min_inst_length(0), - default_is_stmt(0), line_base(0), line_range(0), opcode_base(0), - standard_opcode_lengths(), include_directories(), file_names() {} - - typedef std::shared_ptr<Prologue> shared_ptr; - - uint32_t total_length; // The size in bytes of the statement information for - // this compilation unit (not including the - // total_length field itself). - uint16_t - version; // Version identifier for the statement information format. - - uint8_t address_size; - uint8_t segment_selector_size; - - uint32_t prologue_length; // The number of bytes following the - // prologue_length field to the beginning of the - // first byte of the statement program itself. - uint8_t min_inst_length; // The size in bytes of the smallest target machine - // instruction. Statement program opcodes that - // alter the address register first multiply their - // operands by this value. - uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum - // number of individual - // operations that may be - // encoded in an instruction. - uint8_t default_is_stmt; // The initial value of theis_stmtregister. - int8_t line_base; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t line_range; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t opcode_base; // The number assigned to the first special opcode. - std::vector<uint8_t> standard_opcode_lengths; - std::vector<const char *> include_directories; - std::vector<FileNameEntry> file_names; - - int32_t MaxLineIncrementForSpecialOpcode() const { - return line_base + (int8_t)line_range - 1; - } - bool IsValid() const; - // void Append(BinaryStreamBuf& buff) const; - void Dump(lldb_private::Log *log); - void Clear() { - total_length = version = prologue_length = min_inst_length = line_base = - line_range = opcode_base = 0; - line_base = 0; - standard_opcode_lengths.clear(); - include_directories.clear(); - file_names.clear(); - } - bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir, - lldb_private::FileSpec::Style style, - lldb_private::FileSpec &file) const; - }; - - // Standard .debug_line state machine structure - struct Row { - typedef std::vector<Row> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - Row(bool default_is_stmt = false); - virtual ~Row() {} - void PostAppend(); - void Reset(bool default_is_stmt); - void Dump(lldb_private::Log *log) const; - static void Insert(Row::collection &state_coll, const Row &state); - - dw_addr_t address; // The program-counter value corresponding to a machine - // instruction generated by the compiler. - uint32_t line; // An unsigned integer indicating a source line number. Lines - // are numbered beginning at 1. The compiler may emit the - // value 0 in cases where an instruction cannot be attributed - // to any source line. - uint16_t column; // An unsigned integer indicating a column number within a - // source line. Columns are numbered beginning at 1. The - // value 0 is reserved to indicate that a statement begins - // at the 'left edge' of the line. - uint16_t file; // An unsigned integer indicating the identity of the source - // file corresponding to a machine instruction. - uint8_t is_stmt : 1, // A boolean indicating that the current instruction is - // the beginning of a statement. - basic_block : 1, // A boolean indicating that the current instruction is - // the beginning of a basic block. - end_sequence : 1, // A boolean indicating that the current address is - // that of the first byte after the end of a sequence - // of target machine instructions. - prologue_end : 1, // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an entry breakpoint of a function. - epilogue_begin : 1; // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an exit breakpoint of a function. - uint32_t isa; // An unsigned integer whose value encodes the applicable - // instruction set architecture for the current instruction. - }; - - // LineTable - struct LineTable { - typedef std::shared_ptr<LineTable> shared_ptr; - - LineTable() : prologue(), rows() {} - - void AppendRow(const DWARFDebugLine::Row &state); - void Clear() { - prologue.reset(); - rows.clear(); - } - - uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const; - - Prologue::shared_ptr prologue; - Row::collection rows; - }; - - // State - struct State : public Row { - typedef void (*Callback)(dw_offset_t offset, const State &state, - void *userData); - - // Special row codes used when calling the callback - enum { StartParsingLineTable = 0, DoneParsingLineTable = -1 }; - - State(Prologue::shared_ptr &prologue_sp, lldb_private::Log *log, - Callback callback, void *userData); - - void AppendRowToMatrix(dw_offset_t offset); - - void Finalize(dw_offset_t offset); - - void Reset(); - - Prologue::shared_ptr prologue; - lldb_private::Log *log; - Callback callback; // Callback function that gets called each time an entry - // is to be added to the matrix - void *callbackUserData; - int row; // The row number that starts at zero for the prologue, and - // increases for each row added to the matrix - private: - DISALLOW_COPY_AND_ASSIGN(State); - }; - - static bool - ParseSupportFiles(const lldb::ModuleSP &module_sp, - const lldb_private::DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, - lldb_private::FileSpecList &support_files, - DWARFUnit *dwarf_cu); - static bool - ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, Prologue *prologue, - DWARFUnit *dwarf_cu = nullptr); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, State::Callback callback, - void *userData, DWARFUnit *dwarf_cu); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, LineTable *line_table, - DWARFUnit *dwarf_cu); - static void Parse(const lldb_private::DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, void *userData); - // static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, - // const DWARFDebugLine::Row::collection& state_coll, const uint32_t - // addr_size, BinaryStreamBuf &debug_line_data); - - DWARFDebugLine() : m_lineTableMap() {} - - void Parse(const lldb_private::DWARFDataExtractor &debug_line_data); - void ParseIfNeeded(const lldb_private::DWARFDataExtractor &debug_line_data); - LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const; - -protected: - typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap; - typedef LineTableMap::iterator LineTableIter; - typedef LineTableMap::const_iterator LineTableConstIter; - - LineTableMap m_lineTableMap; -}; - -#endif // SymbolFileDWARF_DWARFDebugLine_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 207c71211c9a5..0b08fa09f9063 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -123,11 +123,6 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu, return false; } -uint64_t DWARFDebugRanges::GetOffset(size_t Index) const { - lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5"); - return 0; -} - bool DWARFDebugRngLists::ExtractRangeList( const DWARFDataExtractor &data, uint8_t addrSize, lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index baf2667f0afea..c398259056b3e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -24,7 +24,6 @@ public: virtual void Extract(lldb_private::DWARFContext &context) = 0; virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const = 0; - virtual uint64_t GetOffset(size_t Index) const = 0; }; class DWARFDebugRanges final : public DWARFDebugRangesBase { @@ -34,7 +33,6 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor &debug_ranges_data, @@ -62,7 +60,7 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; + uint64_t GetOffset(size_t Index) const; protected: bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index d0d70dd5123e1..6501ac27f27d4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -23,7 +23,7 @@ class DWARFDeclContext { public: struct Entry { - Entry() : tag(0), name(nullptr) {} + Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {} Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index 3bf0bb0882273..2ae1bbc9f5074 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -59,6 +59,8 @@ const char *DW_OP_value_to_name(uint32_t val) { } DRC_class DW_OP_value_to_class(uint32_t val) { + // FIXME: If we just used llvm's DWARFExpression printer, we could delete + // all this code (and more in lldb's DWARFExpression.cpp). switch (val) { case 0x03: return DRC_ONEOPERAND; @@ -358,6 +360,8 @@ DRC_class DW_OP_value_to_class(uint32_t val) { return DRC_DWARFv3 | DRC_ONEOPERAND; case 0x9a: return DRC_DWARFv3 | DRC_ONEOPERAND; + case 0xa3: /* DW_OP_entry_value */ + return DRC_TWOOPERANDS; case 0xf0: return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */ case 0xe0: diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 33e83d1fe57f6..9964cf4b893c4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -438,7 +438,7 @@ lldb::ByteOrder DWARFUnit::GetByteOrder() const { return m_dwarf.GetObjectFile()->GetByteOrder(); } -TypeSystem *DWARFUnit::GetTypeSystem() { +llvm::Expected<TypeSystem &> DWARFUnit::GetTypeSystem() { return m_dwarf.GetTypeSystemForLanguage(GetLanguageType()); } @@ -540,19 +540,15 @@ void DWARFUnit::ParseProducerInfo() { } else if (strstr(producer_cstr, "clang")) { static RegularExpression g_clang_version_regex( llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); - RegularExpression::Match regex_match(3); + llvm::SmallVector<llvm::StringRef, 4> matches; if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), - ®ex_match)) { - std::string str; - if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) - m_producer_version_major = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) - m_producer_version_minor = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) - m_producer_version_update = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); + &matches)) { + m_producer_version_major = + StringConvert::ToUInt32(matches[1].str().c_str(), UINT32_MAX, 10); + m_producer_version_minor = + StringConvert::ToUInt32(matches[2].str().c_str(), UINT32_MAX, 10); + m_producer_version_update = + StringConvert::ToUInt32(matches[3].str().c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } else if (strstr(producer_cstr, "GNU")) @@ -870,7 +866,7 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const { llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) const { - const DWARFDebugRangesBase *debug_rnglists = m_dwarf.GetDebugRngLists(); + const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists(); if (!debug_rnglists) return llvm::make_error<llvm::object::GenericBinaryError>( "No debug_rnglists section"); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 8aa1e449f3ed5..87e0de283de4b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -153,7 +153,7 @@ public: lldb::ByteOrder GetByteOrder() const; - lldb_private::TypeSystem *GetTypeSystem(); + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem(); const DWARFDebugAranges &GetFunctionAranges(); diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index 9746ad76c9300..007ef2e05e598 100644 --- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -24,7 +24,7 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, return llvm::make_error<llvm::StringError>("debug info null", llvm::inconvertibleErrorCode()); } - auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(), + auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(), debug_str.GetAsLLVM()); if (llvm::Error E = index_up->extract()) return std::move(E); @@ -105,7 +105,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -125,7 +125,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, uint64_t cu_offset = cu.GetOffset(); for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -248,7 +248,7 @@ void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { Tag tag = entry_or->tag(); diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index 62b0ad37a9fc0..88a29f4a26723 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -125,7 +125,7 @@ DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset) : die_base_offset(_die_base_offset), atoms(), atom_mask(0), min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) { // Define an array of DIE offsets by first defining an array, and then define - // the atom type for the array, in this case we have an array of DIE offsets + // the atom type for the array, in this case we have an array of DIE offsets. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); } @@ -208,9 +208,10 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, const uint32_t atom_count = data.GetU32(&offset); if (atom_count == 0x00060003u) { - // Old format, deal with contents of old pre-release format - while (data.GetU32(&offset)) + // Old format, deal with contents of old pre-release format. + while (data.GetU32(&offset)) { /* do nothing */; + } // Hardcode to the only known value for now. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); @@ -226,7 +227,7 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, size_t DWARFMappedHash::Prologue::GetByteSize() const { // Add an extra count to the atoms size for the zero termination Atom that - // gets written to disk + // gets written to disk. return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); } @@ -286,7 +287,7 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, break; default: - // We can always skip atoms we don't know about + // We can always skip atoms we don't know about. break; } } @@ -308,8 +309,8 @@ DWARFMappedHash::MemoryTable::GetStringForKeyType(KeyType key) const { bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset, HashData &hash_data) const { lldb::offset_t offset = hash_data_offset; - offset += 4; // Skip string table offset that contains offset of hash name in - // .debug_str + // Skip string table offset that contains offset of hash name in .debug_str. + offset += 4; const uint32_t count = m_data.GetU32(&offset); if (count > 0) { hash_data.resize(count); @@ -335,7 +336,7 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) { *hash_data_offset_ptr = UINT32_MAX; @@ -345,9 +346,8 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { // We have at least one HashData entry, and we have enough data to parse at // least "count" HashData entries. @@ -370,21 +370,22 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( if (match) pair.value.push_back(die_info); } else { - // Something went wrong while reading the data + // Something went wrong while reading the data. *hash_data_offset_ptr = UINT32_MAX; return eResultError; } } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -402,7 +403,7 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) return eResultError; @@ -410,9 +411,8 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { const bool match = regex.Execute(llvm::StringRef(strp_cstr)); if (!match && m_header.header_data.HashDataHasFixedByteSize()) { @@ -438,14 +438,15 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -466,7 +467,7 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex( if (prev_hash_data_offset == hash_data_offset) break; - // Check the result of getting our hash data + // Check the result of getting our hash data. switch (hash_result) { case eResultKeyMatch: case eResultKeyMismatch: diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index a01612b595286..56d9bc5488770 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -24,37 +24,41 @@ class DWARFMappedHash { public: enum AtomType : uint16_t { eAtomTypeNULL = 0u, - eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding - eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that - // contains the item in question - eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 - // (if no tags exceed 255) or DW_FORM_data2 - eAtomTypeNameFlags = 4u, // Flags from enum NameFlags - eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, - eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name - // (since all hash entries are basename only) - // For example a type like "std::vector<int>::iterator" would have a name of - // "iterator" - // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not - // have to pull - // in debug info for a type when we know the fully qualified name. + /// DIE offset, check form for encoding. + eAtomTypeDIEOffset = 1u, + /// DIE offset of the compiler unit header that contains the item in + /// question. + eAtomTypeCUOffset = 2u, + /// DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed + /// 255) or DW_FORM_data2. + eAtomTypeTag = 3u, + // Flags from enum NameFlags. + eAtomTypeNameFlags = 4u, + // Flags from enum TypeFlags. + eAtomTypeTypeFlags = 5u, + /// A 32 bit hash of the full qualified name (since all hash entries are + /// basename only) For example a type like "std::vector<int>::iterator" + /// would have a name of "iterator" and a 32 bit hash for + /// "std::vector<int>::iterator" to allow us to not have to pull in debug + /// info for a type when we know the fully qualified name. + eAtomTypeQualNameHash = 6u }; - // Bit definitions for the eAtomTypeTypeFlags flags + /// Bit definitions for the eAtomTypeTypeFlags flags. enum TypeFlags { - // Always set for C++, only set for ObjC if this is the - // @implementation for class + /// Always set for C++, only set for ObjC if this is the + /// @implementation for class. eTypeFlagClassIsImplementation = (1u << 1) }; struct DIEInfo { dw_offset_t die_offset = DW_INVALID_OFFSET; - dw_tag_t tag = 0; + dw_tag_t tag = llvm::dwarf::DW_TAG_null; - /// Any flags for this DIEInfo + /// Any flags for this DIEInfo. uint32_t type_flags = 0; - /// A 32 bit hash of the fully qualified name + /// A 32 bit hash of the fully qualified name. uint32_t qualified_name_hash = 0; DIEInfo() = default; @@ -94,7 +98,7 @@ public: bool HashDataHasFixedByteSize() const; - // DIE offset base so die offsets in hash_data can be CU relative + /// DIE offset base so die offsets in hash_data can be CU relative. dw_offset_t die_base_offset; AtomArray atoms; uint32_t atom_mask; @@ -113,8 +117,8 @@ public: lldb::offset_t *offset_ptr, DIEInfo &hash_data) const; }; - // A class for reading and using a saved hash table from a block of data - // in memory + /// A class for reading and using a saved hash table from a block of data in + /// memory. class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> { diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index e2ddcfc5d64be..c982d59c2830c 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -8,6 +8,7 @@ #include "SymbolFileDWARF.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -43,7 +44,7 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" @@ -58,7 +59,6 @@ #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugLine.h" #include "DWARFDebugMacro.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" @@ -72,6 +72,7 @@ #include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDwp.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/FileSystem.h" #include <algorithm> @@ -113,18 +114,12 @@ using namespace lldb_private; namespace { -static constexpr PropertyDefinition g_properties[] = { - {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr, - {}, - "If the DW_AT_comp_dir matches any of these paths the symbolic " - "links will be resolved at DWARF parse time."}, - {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {}, - "Ignore indexes present in the object files and always index DWARF " - "manually."}}; +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFProperties.inc" enum { - ePropertySymLinkPaths, - ePropertyIgnoreIndexes, +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFPropertiesEnum.inc" }; class PluginProperties : public Properties { @@ -135,7 +130,7 @@ public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_symbolfiledwarf_properties); } FileSpecList GetSymLinkPaths() { @@ -159,7 +154,66 @@ static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -} // anonymous namespace end +} // namespace + +static const llvm::DWARFDebugLine::LineTable * +ParseLLVMLineTable(lldb_private::DWARFContext &context, + llvm::DWARFDebugLine &line, dw_offset_t line_offset, + dw_offset_t unit_offset) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + + llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = context.GetAsLLVM(); + llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table = + line.getOrParseLineTable( + data, line_offset, ctx, nullptr, [&](llvm::Error e) { + LLDB_LOG_ERROR(log, std::move(e), + "SymbolFileDWARF::ParseLineTable failed to parse"); + }); + + if (!line_table) { + LLDB_LOG_ERROR(log, line_table.takeError(), + "SymbolFileDWARF::ParseLineTable failed to parse"); + return nullptr; + } + return *line_table; +} + +static FileSpecList ParseSupportFilesFromPrologue( + const lldb::ModuleSP &module, + const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, + llvm::StringRef compile_dir = {}, FileSpec first_file = {}) { + FileSpecList support_files; + support_files.Append(first_file); + + const size_t number_of_files = prologue.FileNames.size(); + for (size_t idx = 1; idx <= number_of_files; ++idx) { + std::string original_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file, + style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(); + continue; + } + + std::string remapped_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + remapped_file, style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(original_file, style); + continue; + } + + module->RemapSourceFile(llvm::StringRef(original_file), remapped_file); + support_files.EmplaceBack(remapped_file, style); + } + + return support_files; +} FileSpecList SymbolFileDWARF::GetSymlinkPaths() { return GetGlobalPluginProperties()->GetSymLinkPaths(); @@ -197,20 +251,16 @@ const char *SymbolFileDWARF::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader."; } -SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARF(obj_file, +SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARF(std::move(objfile_sp), /*dwo_section_list*/ nullptr); } -TypeList *SymbolFileDWARF::GetTypeList() { - // This method can be called without going through the symbol vendor so we - // need to lock the module. +TypeList &SymbolFileDWARF::GetTypeList() { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) return debug_map_symfile->GetTypeList(); - else - return m_obj_file->GetModule()->GetTypeList(); + return SymbolFile::GetTypeList(); } void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, @@ -264,6 +314,8 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer) != 0; break; + default: + break; } if (add_type) { @@ -283,11 +335,11 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, } } -size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, - TypeClass type_mask, TypeList &type_list) +void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, + TypeClass type_mask, TypeList &type_list) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); TypeSet type_set; CompileUnit *comp_unit = nullptr; @@ -297,8 +349,8 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, if (comp_unit) { dwarf_cu = GetDWARFCompileUnit(comp_unit); - if (dwarf_cu == nullptr) - return 0; + if (!dwarf_cu) + return; GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextUnitOffset(), type_mask, type_set); } else { @@ -315,16 +367,13 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, } std::set<CompilerType> compiler_type_set; - size_t num_types_added = 0; for (Type *type : type_set) { CompilerType compiler_type = type->GetForwardCompilerType(); if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) { compiler_type_set.insert(compiler_type); type_list.Insert(type->shared_from_this()); - ++num_types_added; } } - return num_types_added; } // Gets the first parent that is a lexical block, function or inlined @@ -342,19 +391,21 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: return die; + default: + break; } } return DWARFDIE(); } -SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile, +SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp, SectionList *dwo_section_list) - : SymbolFile(objfile), + : SymbolFile(std::move(objfile_sp)), UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to // when this class parses .o files to // contain the .o file index/ID m_debug_map_module_wp(), m_debug_map_symfile(nullptr), - m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), + m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list), m_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_unique_ast_type_map() {} @@ -374,17 +425,17 @@ UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; } -TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - TypeSystem *type_system; - if (debug_map_symfile) { - type_system = debug_map_symfile->GetTypeSystemForLanguage(language); - } else { - type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); +llvm::Expected<TypeSystem &> +SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) + return debug_map_symfile->GetTypeSystemForLanguage(language); + + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); } - return type_system; + return type_system_or_err; } void SymbolFileDWARF::InitializeObject() { @@ -420,7 +471,7 @@ void SymbolFileDWARF::InitializeObject() { } } - m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), + m_index = std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), DebugInfo()); } @@ -430,9 +481,9 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file != nullptr) { + if (m_objfile_sp != nullptr) { const Section *section = nullptr; - const SectionList *section_list = m_obj_file->GetSectionList(); + const SectionList *section_list = m_objfile_sp->GetSectionList(); if (section_list == nullptr) return 0; @@ -462,10 +513,12 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { abbrev->GetUnsupportedForms(invalid_forms); if (!invalid_forms.empty()) { StreamString error; - error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : ""); + error.Printf("unsupported DW_FORM value%s:", + invalid_forms.size() > 1 ? "s" : ""); for (auto form : invalid_forms) error.Printf(" %#x", form); - m_obj_file->GetModule()->ReportWarning("%s", error.GetString().str().c_str()); + m_objfile_sp->GetModule()->ReportWarning( + "%s", error.GetString().str().c_str()); return 0; } } @@ -477,10 +530,10 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { debug_line_file_size = section->GetFileSize(); } else { const char *symfile_dir_cstr = - m_obj_file->GetFileSpec().GetDirectory().GetCString(); + m_objfile_sp->GetFileSpec().GetDirectory().GetCString(); if (symfile_dir_cstr) { if (strcasestr(symfile_dir_cstr, ".dsym")) { - if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) { + if (m_objfile_sp->GetType() == ObjectFile::eTypeDebugInfo) { // We have a dSYM file that didn't have a any debug info. If the // string table has a size of 1, then it was made from an // executable with no debug info, or from an executable that was @@ -489,7 +542,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true) .get(); if (section && section->GetFileSize() == 1) { - m_obj_file->GetModule()->ReportWarning( + m_objfile_sp->GetModule()->ReportWarning( "empty dSYM file detected, dSYM was created with an " "executable with no debug info."); } @@ -519,7 +572,7 @@ SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); const SectionList *section_list = module_sp->GetSectionList(); if (!section_list) return; @@ -529,7 +582,7 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, return; data.Clear(); - m_obj_file->ReadSectionData(section_sp.get(), data); + m_objfile_sp->ReadSectionData(section_sp.get(), data); } const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { @@ -556,7 +609,7 @@ DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; - auto abbr = llvm::make_unique<DWARFDebugAbbrev>(); + auto abbr = std::make_unique<DWARFDebugAbbrev>(); llvm::Error error = abbr->parse(debug_abbrev_data); if (error) { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); @@ -579,7 +632,7 @@ DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0) - m_info = llvm::make_unique<DWARFDebugInfo>(*this, m_context); + m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); } return m_info.get(); } @@ -604,7 +657,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { return nullptr; } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { +DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { if (!m_ranges) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -619,7 +672,7 @@ DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { return m_ranges.get(); } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRngLists() { +DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() { if (!m_rnglists) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -648,7 +701,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { cu_sp = m_debug_map_symfile->GetCompileUnit(this); dwarf_cu.SetUserData(cu_sp.get()); } else { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); if (module_sp) { const DWARFDIE cu_die = dwarf_cu.DIE(); if (cu_die) { @@ -677,8 +730,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { dwarf_cu.SetUserData(cu_sp.get()); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - dwarf_cu.GetID(), cu_sp); + SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp); } } } @@ -715,7 +767,7 @@ llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { return m_lldb_cu_to_dwarf_unit[cu_idx]; } -uint32_t SymbolFileDWARF::GetNumCompileUnits() { +uint32_t SymbolFileDWARF::CalculateNumCompileUnits() { DWARFDebugInfo *info = DebugInfo(); if (!info) return 0; @@ -741,17 +793,21 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, const DWARFDIE &die) { ASSERT_MODULE_LOCK(this); - if (die.IsValid()) { - TypeSystem *type_system = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - - if (type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast) - return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); - } + if (!die.IsValid()) + return nullptr; + + auto type_system_or_err = + GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse function"); + return nullptr; } - return nullptr; + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); + if (!dwarf_ast) + return nullptr; + + return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); } bool SymbolFileDWARF::FixupAddress(Address &addr) { @@ -763,7 +819,7 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) { return true; } lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetLanguageType(); @@ -772,7 +828,7 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (!dwarf_cu) return 0; @@ -790,21 +846,23 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { return functions_added; } +void SymbolFileDWARF::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + UpdateExternalModuleListIfNeeded(); + + for (auto &p : m_external_type_modules) { + ModuleSP module = p.second; + f(module); + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) + module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f); + } +} + bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { - ASSERT_MODULE_LOCK(this); - if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) { - const dw_offset_t stmt_list = unit->GetLineTableOffset(); - if (stmt_list != DW_INVALID_OFFSET) { - // All file indexes in DWARF are one based and a file of index zero is - // supposed to be the compile unit itself. - support_files.Append(comp_unit); - return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(), - m_context.getOrLoadLineData(), - stmt_list, support_files, unit); - } - } - return false; + if (!comp_unit.GetLineTable()) + ParseLineTable(comp_unit); + return true; } FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { @@ -833,16 +891,26 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { auto iter_bool = m_type_unit_support_files.try_emplace(offset); FileSpecList &list = iter_bool.first->second; if (iter_bool.second) { - list.Append(FileSpec()); - DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(), - m_context.getOrLoadLineData(), offset, - list, &tu); + uint64_t line_table_offset = offset; + llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = m_context.GetAsLLVM(); + llvm::DWARFDebugLine::Prologue prologue; + llvm::Error error = prologue.parse(data, &line_table_offset, ctx); + if (error) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, std::move(error), + "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse " + "the line table prologue"); + } else { + list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), + prologue, tu.GetPathStyle()); + } } return list; } bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetIsOptimized(); @@ -852,7 +920,7 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARF::ParseImportedModules( const lldb_private::SymbolContext &sc, std::vector<SourceModule> &imported_modules) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); assert(sc.comp_unit); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (!dwarf_cu) @@ -901,102 +969,63 @@ bool SymbolFileDWARF::ParseImportedModules( return true; } -struct ParseDWARFLineTableCallbackInfo { - LineTable *line_table; - std::unique_ptr<LineSequence> sequence_up; - lldb::addr_t addr_mask; -}; - -// ParseStatementTableCallback -static void ParseDWARFLineTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - ParseDWARFLineTableCallbackInfo *info = - (ParseDWARFLineTableCallbackInfo *)userData; - LineTable *line_table = info->line_table; - - // If this is our first time here, we need to create a sequence container. - if (!info->sequence_up) { - info->sequence_up.reset(line_table->CreateLineSequenceContainer()); - assert(info->sequence_up.get()); - } - line_table->AppendLineEntryToSequence( - info->sequence_up.get(), state.address & info->addr_mask, state.line, - state.column, state.file, state.is_stmt, state.basic_block, - state.prologue_end, state.epilogue_begin, state.end_sequence); - if (state.end_sequence) { - // First, put the current sequence into the line table. - line_table->InsertSequence(info->sequence_up.get()); - // Then, empty it to prepare for the next sequence. - info->sequence_up->Clear(); - } - } -} - bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (comp_unit.GetLineTable() != nullptr) return true; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); - if (dwarf_cu_die) { - const dw_offset_t cu_line_offset = - dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, - DW_INVALID_OFFSET); - if (cu_line_offset != DW_INVALID_OFFSET) { - std::unique_ptr<LineTable> line_table_up(new LineTable(&comp_unit)); - if (line_table_up) { - ParseDWARFLineTableCallbackInfo info; - info.line_table = line_table_up.get(); - - /* - * MIPS: - * The SymbolContext may not have a valid target, thus we may not be - * able - * to call Address::GetOpcodeLoadAddress() which would clear the bit - * #0 - * for MIPS. Use ArchSpec to clear the bit #0. - */ - switch (GetObjectFile()->GetArchitecture().GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - info.addr_mask = ~((lldb::addr_t)1); - break; - default: - info.addr_mask = ~((lldb::addr_t)0); - break; - } + if (!dwarf_cu) + return false; - lldb::offset_t offset = cu_line_offset; - DWARFDebugLine::ParseStatementTable( - m_context.getOrLoadLineData(), &offset, - ParseDWARFLineTableCallback, &info, dwarf_cu); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) { - // We have an object file that has a line table with addresses that - // are not linked. We need to link the line table and convert the - // addresses that are relative to the .o file into addresses for - // the main executable. - comp_unit.SetLineTable( - debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); - } else { - comp_unit.SetLineTable(line_table_up.release()); - return true; - } - } - } + const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); + if (!dwarf_cu_die) + return false; + + const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned( + DW_AT_stmt_list, DW_INVALID_OFFSET); + if (cu_line_offset == DW_INVALID_OFFSET) + return false; + + llvm::DWARFDebugLine line; + const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable( + m_context, line, cu_line_offset, dwarf_cu->GetOffset()); + + if (!line_table) + return false; + + // FIXME: Rather than parsing the whole line table and then copying it over + // into LLDB, we should explore using a callback to populate the line table + // while we parse to reduce memory usage. + std::unique_ptr<LineTable> line_table_up = + std::make_unique<LineTable>(&comp_unit); + LineSequence *sequence = line_table_up->CreateLineSequenceContainer(); + for (auto &row : line_table->Rows) { + line_table_up->AppendLineEntryToSequence( + sequence, row.Address.Address, row.Line, row.Column, row.File, + row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, + row.EndSequence); + if (row.EndSequence) { + line_table_up->InsertSequence(sequence); + sequence = line_table_up->CreateLineSequenceContainer(); } } - return false; + + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { + // We have an object file that has a line table with addresses that are not + // linked. We need to link the line table and convert the addresses that + // are relative to the .o file into addresses for the main executable. + comp_unit.SetLineTable( + debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); + } else { + comp_unit.SetLineTable(line_table_up.release()); + } + + comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( + comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(), + dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit))); + + return true; } lldb_private::DebugMacrosSP @@ -1022,7 +1051,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { } bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu == nullptr) @@ -1114,7 +1143,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 ") which has a base that is less than the function's low PC " "0x%" PRIx64 ". Please file a bug and attach the file at the " - "start of this error message", + "start of this error message", block->GetID(), range_base, range.GetRangeEnd(), subprogram_low_pc); } @@ -1188,15 +1217,10 @@ bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) { } void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) { - TypeSystem *type_system = decl_ctx.GetTypeSystem(); - DWARFASTParser *ast_parser = type_system->GetDWARFParser(); - std::vector<DWARFDIE> decl_ctx_die_list = - ast_parser->GetDIEForDeclContext(decl_ctx); - - for (DWARFDIE decl_ctx_die : decl_ctx_die_list) - for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; - decl = decl.GetSibling()) - ast_parser->GetDeclForUIDFromDWARF(decl); + auto *type_system = decl_ctx.GetTypeSystem(); + if (type_system != nullptr) + type_system->GetDWARFParser()->EnsureAllDIEsInDeclContextHaveBeenParsed( + decl_ctx); } user_id_t SymbolFileDWARF::GetUID(DIERef ref) { @@ -1281,8 +1305,6 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { CompilerDeclContext SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1293,8 +1315,6 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { } Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1341,8 +1361,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, // Get the type, which could be a forward declaration if (log) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " - "resolve parent forward type for 0x%8.8x", + log, + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " + "resolve parent forward type for 0x%8.8x", die.GetOffset(), die.GetTagAsCString(), die.GetName(), decl_ctx_die.GetOffset()); } break; @@ -1504,7 +1525,6 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { ->GetDIE(die_ref); } - DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) return debug_info->GetDIE(die_ref); @@ -1567,7 +1587,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (dwo_obj_file == nullptr) return nullptr; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); + return std::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1607,7 +1627,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } } dwo_module_spec.GetArchitecture() = - m_obj_file->GetModule()->GetArchitecture(); + m_objfile_sp->GetModule()->GetArchitecture(); // When LLDB loads "external" modules it looks at the presence of // DW_AT_GNU_dwo_name. However, when the already created module @@ -1621,8 +1641,8 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // printed. However, as one can notice in this case we don't // actually need to try to load the already loaded module // (corresponding to .dwo) so we simply skip it. - if (m_obj_file->GetFileSpec().GetFileNameExtension() == ".dwo" && - llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) + if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" && + llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath()) .endswith(dwo_module_spec.GetFileSpec().GetPath())) { continue; } @@ -1694,6 +1714,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::" @@ -1837,6 +1858,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; @@ -1849,7 +1871,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *dc_cu, full_match); if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_obj_file->GetModule()); + SymbolContext sc(m_objfile_sp->GetModule()); sc.comp_unit = dc_cu; uint32_t file_idx = UINT32_MAX; @@ -1961,9 +1983,16 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( } TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); - TypeSystem *type_system = GetTypeSystemForLanguage( + auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); - if (decl_ctx_type_system == type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to match namespace decl using TypeSystem"); + return false; + } + + if (decl_ctx_type_system == &type_system_or_err.get()) return true; // The type systems match, return true // The namespace AST was valid, and it does not match... @@ -1976,9 +2005,10 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( return false; } -uint32_t SymbolFileDWARF::FindGlobalVariables( +void SymbolFileDWARF::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) @@ -1990,11 +2020,11 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( max_matches); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2012,7 +2042,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); // Loop invariant: Variables up to this index have been checked for context @@ -2081,12 +2111,12 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( name.GetCString(), static_cast<const void *>(parent_decl_ctx), max_matches, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { +void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, + uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2098,8 +2128,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, } DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2108,7 +2138,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->GetGlobalVariables(regex, die_offsets); SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); const size_t num_matches = die_offsets.size(); @@ -2132,9 +2162,6 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->ReportInvalidDIERef(die_ref, regex.GetText()); } } - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, @@ -2210,10 +2237,12 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, return false; } -uint32_t SymbolFileDWARF::FindFunctions( - ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + FunctionNameType name_type_mask, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (name = '%s')", name.AsCString()); @@ -2226,21 +2255,17 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, append=%u, sc_list)", - name.GetCString(), name_type_mask, append); + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, sc_list)", + name.GetCString(), name_type_mask); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; // If name is empty then we won't find anything. if (name.IsEmpty()) - return 0; + return; // Remember how many sc_list are in the list before we search in case we are // appending the results to a variable list. @@ -2255,7 +2280,7 @@ uint32_t SymbolFileDWARF::FindFunctions( std::vector<DWARFDIE> dies; m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); - for (const DWARFDIE &die: dies) { + for (const DWARFDIE &die : dies) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } @@ -2265,18 +2290,18 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => " - "%u", - name.GetCString(), name_type_mask, include_inlines, append, + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", " + "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u", + name.GetCString(), name_type_mask, include_inlines, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); @@ -2285,22 +2310,13 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (log) { GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", - regex.GetText().str().c_str(), append); + log, "SymbolFileDWARF::FindFunctions (regex=\"%s\", sc_list)", + regex.GetText().str().c_str()); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - DWARFDebugInfo *info = DebugInfo(); if (!info) - return 0; - - // Remember how many sc_list are in the list before we search in case we are - // appending the results to a variable list. - uint32_t original_size = sc_list.GetSize(); + return; DIEArray offsets; m_index->GetFunctions(regex, offsets); @@ -2315,9 +2331,6 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } - - // Return the number of variable that were appended to the list - return sc_list.GetSize() - original_size; } void SymbolFileDWARF::GetMangledNamesForFunction( @@ -2345,156 +2358,141 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -uint32_t SymbolFileDWARF::FindTypes( +void SymbolFileDWARF::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - // If we aren't appending the results to this list, then clear the list - if (!append) - types.Clear(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Make sure we haven't already searched this SymbolFile before... if (searched_symbol_files.count(this)) - return 0; - else - searched_symbol_files.insert(this); + return; + + searched_symbol_files.insert(this); DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { if (parent_decl_ctx) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "%p (\"%s\"), append=%u, max_matches=%u, type_list)", + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "%p (\"%s\"), max_matches=%u, type_list)", name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches); + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches); else GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "NULL, append=%u, max_matches=%u, type_list)", - name.GetCString(), append, max_matches); + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "NULL, max_matches=%u, type_list)", + name.GetCString(), max_matches); } if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - const uint32_t initial_types_size = types.GetSize(); - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - if (types.GetSize() >= max_matches) - break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } - } - const uint32_t num_matches = types.GetSize() - initial_types_size; - if (log && num_matches) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches, - num_matches); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= NULL, append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), append, max_matches, num_matches); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); + if (die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + Type *matching_type = ResolveType(die, true, true); + if (matching_type) { + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + if (types.GetSize() >= max_matches) + break; } + } else { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } - return num_matches; - } else { + } + + // Next search through the reachable Clang modules. This only applies for + // DWARF objects compiled with -gmodules that haven't been processed by + // dsymutil. + if (num_die_matches < max_matches) { UpdateExternalModuleListIfNeeded(); - for (const auto &pair : m_external_type_modules) { - ModuleSP external_module_sp = pair.second; - if (external_module_sp) { - SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); - if (sym_vendor) { - const uint32_t num_external_matches = - sym_vendor->FindTypes(name, parent_decl_ctx, append, max_matches, - searched_symbol_files, types); - if (num_external_matches) - return num_external_matches; - } - } - } + for (const auto &pair : m_external_type_modules) + if (ModuleSP external_module_sp = pair.second) + if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) + sym_file->FindTypes(name, parent_decl_ctx, max_matches, + searched_symbol_files, types); } - return 0; + if (log && types.GetSize()) { + if (parent_decl_ctx) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= %p (\"%s\"), max_matches=%u, type_list) => %u", + name.GetCString(), static_cast<const void *>(parent_decl_ctx), + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches, + types.GetSize()); + } else { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= NULL, max_matches=%u, type_list) => %u", + name.GetCString(), max_matches, types.GetSize()); + } + } } -size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - - if (context.empty()) - return 0; +void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (pattern.empty()) + return; - ConstString name = context.back().name; + ConstString name = pattern.back().name; if (!name) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - size_t num_matches = 0; - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); - if (die) { - std::vector<CompilerContext> die_context; - die.GetDeclContext(die_context); - if (die_context != context) - continue; - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - ++num_matches; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } + if (!die) { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); + continue; } - return num_matches; + if (!languages[die.GetCU()->GetLanguageType()]) + continue; + + llvm::SmallVector<CompilerContext, 4> die_context; + die.GetDeclContext(die_context); + if (!contextMatches(die_context, pattern)) + continue; + + if (Type *matching_type = ResolveType(die, true, true)) + // We found a type pointer, now find the shared pointer form our type + // list. + types.InsertUnique(matching_type->shared_from_this()); } - return 0; } CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2536,8 +2534,9 @@ SymbolFileDWARF::FindNamespace(ConstString name, } if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " - "CompilerDeclContext(%p/%p) \"%s\"", + log, + "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " + "CompilerDeclContext(%p/%p) \"%s\"", name.GetCString(), static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()), static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()), @@ -2632,11 +2631,10 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { return DWARFDIE(); } -Symbol * -SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { +Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { Symbol *objc_class_symbol = nullptr; - if (m_obj_file) { - Symtab *symtab = m_obj_file->GetSymtab(); + if (m_objfile_sp) { + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { objc_class_symbol = symtab->FindFirstSymbolWithNameAndType( objc_class_name, eSymbolTypeObjCClass, Symtab::eDebugNo, @@ -2653,8 +2651,7 @@ SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { // worry about the debug map // DWARF file // if we are doing darwin DWARF in .o file debugging. -bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( - DWARFUnit *cu) { +bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) { if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) @@ -2681,8 +2678,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( // This function can be used when a DIE is found that is a forward declaration // DIE and we want to try and find a type that has the complete definition. TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, ConstString type_name, - bool must_be_implementation) { + const DWARFDIE &die, ConstString type_name, bool must_be_implementation) { TypeSP type_sp; @@ -2727,7 +2723,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( DEBUG_PRINTF("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", die.GetID(), - m_obj_file->GetFileSpec().GetFilename().AsCString( + m_objfile_sp->GetFileSpec().GetFilename().AsCString( "<Unknown>"), type_die.GetID(), type_cu->GetID()); @@ -2849,8 +2845,9 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( DWARF_LOG_LOOKUPS)); if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" - "s, qualified-name='%s')", + log, + "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" + "s, qualified-name='%s')", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName()); } @@ -2863,10 +2860,18 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( // use this to ensure any matches we find are in a language that this // type system supports const LanguageType language = dwarf_decl_ctx.GetLanguage(); - TypeSystem *type_system = (language == eLanguageTypeUnknown) - ? nullptr - : GetTypeSystemForLanguage(language); - + TypeSystem *type_system = nullptr; + if (language != eLanguageTypeUnknown) { + auto type_system_or_err = GetTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Cannot get TypeSystem for language {}", + Language::GetNameForLanguageType(language)); + } else { + type_system = &type_system_or_err.get(); + } + } if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { const DIERef &die_ref = die_offsets[i]; @@ -2916,9 +2921,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') trying die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') trying die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), type_dwarf_decl_ctx.GetQualifiedName()); @@ -2937,9 +2943,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( std::string qualified_name; type_die.GetQualifiedName(qualified_name); GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') ignoring die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') ignoring die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), qualified_name.c_str()); @@ -2960,21 +2967,21 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, if (!die) return {}; - TypeSystem *type_system = + auto type_system_or_err = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - if (!type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse type"); return {}; + } - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); if (!dwarf_ast) return {}; - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr); + TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr); if (type_sp) { - TypeList *type_list = GetTypeList(); - if (type_list) - type_list->Insert(type_sp); + GetTypeList().Insert(type_sp); if (die.Tag() == DW_TAG_subprogram) { std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) @@ -2995,12 +3002,21 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, bool parse_siblings, bool parse_children) { size_t types_added = 0; DWARFDIE die = orig_die; + while (die) { + const dw_tag_t tag = die.Tag(); bool type_is_new = false; - if (ParseType(sc, die, &type_is_new).get()) { - if (type_is_new) - ++types_added; - } + + Tag dwarf_tag = static_cast<Tag>(tag); + + // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...) + // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or + // not. + if (isType(dwarf_tag) && tag != DW_TAG_subrange_type) + ParseType(sc, die, &type_is_new); + + if (type_is_new) + ++types_added; if (parse_children && die.HasChildren()) { if (die.Tag() == DW_TAG_subprogram) { @@ -3020,7 +3036,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, } size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); lldbassert(comp_unit); @@ -3040,7 +3056,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t types_added = 0; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { @@ -3056,7 +3072,7 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (sc.comp_unit != nullptr) { DWARFDebugInfo *info = DebugInfo(); if (info == nullptr) @@ -3193,15 +3209,18 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, debug_info_data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, block_offset, block_length), + die.GetCU()); } else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, data_offset, *data_length), + die.GetCU()); else { const uint8_t *data_pointer = form_value.BlockData(); if (data_pointer) { @@ -3217,17 +3236,21 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (form_value.Form() == DW_FORM_strp) { uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + data_offset, + *data_length), + die.GetCU()); } else { const char *str = form_value.AsCString(); uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); uint32_t string_length = strlen(str) + 1; - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - string_offset, string_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + string_offset, + string_length), + die.GetCU()); } } } @@ -3241,17 +3264,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), + die.GetCU()); } else { - const DWARFDataExtractor &debug_loc_data = DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - die.GetCU(), debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - location = DWARFExpression(module, debug_loc_data, die.GetCU(), - debug_loc_offset, loc_list_length); + DataExtractor data = DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + location = DWARFExpression(module, data, die.GetCU()); assert(func_low_pc != LLDB_INVALID_ADDRESS); location.SetLocationListSlide( func_low_pc - @@ -3522,6 +3543,8 @@ SymbolFileDWARF::FindBlockContainingSpecification( spec_block_die_offset) return die; } break; + default: + break; } // Give the concrete function die specified by "func_die_offset", find the @@ -3577,8 +3600,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, } else { GetObjectFile()->GetModule()->ReportError( "parent 0x%8.8" PRIx64 " %s with no valid compile unit in " - "symbol context for 0x%8.8" PRIx64 - " %s.\n", + "symbol context for 0x%8.8" PRIx64 " %s.\n", sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), orig_die.GetID(), orig_die.GetTagAsCString()); } @@ -3654,9 +3676,57 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, return vars_added; } +/// Collect call site parameters in a DW_TAG_call_site DIE. +static CallSiteParameterArray +CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { + CallSiteParameterArray parameters; + for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); + child = child.GetSibling()) { + if (child.Tag() != DW_TAG_call_site_parameter) + continue; + + llvm::Optional<DWARFExpression> LocationInCallee = {}; + llvm::Optional<DWARFExpression> LocationInCaller = {}; + + DWARFAttributes attributes; + const size_t num_attributes = child.GetAttributes(attributes); + + // Parse the location at index \p attr_index within this call site parameter + // DIE, or return None on failure. + auto parse_simple_location = + [&](int attr_index) -> llvm::Optional<DWARFExpression> { + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) + return {}; + if (!DWARFFormValue::IsBlockForm(form_value.Form())) + return {}; + auto data = child.GetData(); + uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + return DWARFExpression(module, + DataExtractor(data, block_offset, block_length), + child.GetCU()); + }; + + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attr == DW_AT_location) + LocationInCallee = parse_simple_location(i); + if (attr == DW_AT_call_value) + LocationInCaller = parse_simple_location(i); + } + + if (LocationInCallee && LocationInCaller) { + CallSiteParameter param = {*LocationInCallee, *LocationInCaller}; + parameters.push_back(param); + } + } + return parameters; +} + /// Collect call graph edges present in a function DIE. static std::vector<lldb_private::CallEdge> -CollectCallEdges(DWARFDIE function_die) { +CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // Check if the function has a supported call site-related attribute. // TODO: In the future it may be worthwhile to support call_all_source_calls. uint64_t has_call_edges = @@ -3693,9 +3763,28 @@ CollectCallEdges(DWARFDIE function_die) { addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc, LLDB_INVALID_ADDRESS); + // Extract call site parameters. + CallSiteParameterArray parameters = + CollectCallSiteParameters(module, child); + LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", call_origin.GetPubname(), return_pc); - call_edges.emplace_back(call_origin.GetMangledName(), return_pc); + if (log && parameters.size()) { + for (const CallSiteParameter ¶m : parameters) { + StreamString callee_loc_desc, caller_loc_desc; + param.LocationInCallee.GetDescription(&callee_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + param.LocationInCaller.GetDescription(&caller_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}", + callee_loc_desc.GetString(), caller_loc_desc.GetString()); + } + } + + call_edges.emplace_back(call_origin.GetMangledName(), return_pc, + std::move(parameters)); } return call_edges; } @@ -3704,7 +3793,7 @@ std::vector<lldb_private::CallEdge> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) - return CollectCallEdges(func_die); + return CollectCallEdges(GetObjectFile()->GetModule(), func_die); return {}; } @@ -3713,11 +3802,17 @@ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); } uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; } -void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } +void SymbolFileDWARF::Dump(lldb_private::Stream &s) { + SymbolFile::Dump(s); + m_index->Dump(s); +} void SymbolFileDWARF::DumpClangAST(Stream &s) { - TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); - ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(ts); + auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!ts_or_err) + return; + ClangASTContext *clang = + llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get()); if (!clang) return; clang->Dump(s); @@ -3727,10 +3822,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (sym_vendor) - m_debug_map_symfile = - (SymbolFileDWARFDebugMap *)sym_vendor->GetSymbolFile(); + m_debug_map_symfile = + (SymbolFileDWARFDebugMap *)module_sp->GetSymbolFile(); } } return m_debug_map_symfile; @@ -3746,9 +3839,9 @@ SymbolFileDWARF::GetLocationListFormat() const { SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { ModuleSpec module_spec; - module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); + module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); module_spec.GetSymbolFileSpec() = - FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp"); + FileSpec(m_objfile_sp->GetFileSpec().GetPath() + ".dwp"); FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 018af47305f46..04cb11d426be5 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -46,7 +46,8 @@ class DWARFDebugAranges; class DWARFDebugInfo; class DWARFDebugInfoEntry; class DWARFDebugLine; -class DWARFDebugRangesBase; +class DWARFDebugRanges; +class DWARFDebugRngLists; class DWARFDeclContext; class DWARFFormValue; class DWARFTypeUnit; @@ -78,13 +79,13 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); static lldb_private::FileSpecList GetSymlinkPaths(); // Constructors and Destructors - SymbolFileDWARF(lldb_private::ObjectFile *ofile, + SymbolFileDWARF(lldb::ObjectFileSP objfile_sp, lldb_private::SectionList *dwo_section_list); ~SymbolFileDWARF() override; @@ -95,10 +96,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -108,6 +105,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -156,47 +157,46 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; void GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) override; - uint32_t + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context, - bool append, lldb_private::TypeMap &types) override; + void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, + lldb_private::LanguageSet languages, + lldb_private::TypeMap &types) override; - lldb_private::TypeList *GetTypeList() override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; - - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -223,8 +223,8 @@ public: const DWARFDebugInfo *DebugInfo() const; - DWARFDebugRangesBase *GetDebugRanges(); - DWARFDebugRangesBase *GetDebugRngLists(); + DWARFDebugRanges *GetDebugRanges(); + DWARFDebugRngLists *GetDebugRngLists(); const lldb_private::DWARFDataExtractor &DebugLocData(); @@ -331,6 +331,12 @@ protected: bool DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx); + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + + lldb_private::TypeList &GetTypeList() override; + virtual DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); @@ -477,8 +483,8 @@ protected: typedef std::set<lldb::user_id_t> DIERefSet; typedef llvm::StringMap<DIERefSet> NameToOffsetMap; NameToOffsetMap m_function_scope_qualified_name_map; - std::unique_ptr<DWARFDebugRangesBase> m_ranges; - std::unique_ptr<DWARFDebugRangesBase> m_rnglists; + std::unique_ptr<DWARFDebugRanges> m_ranges; + std::unique_ptr<DWARFDebugRngLists> m_rnglists; UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 8ec64dbaf7641..a50d4e460bae5 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -41,7 +41,7 @@ using namespace lldb_private; // Subclass lldb_private::Module so we can intercept the // "Module::GetObjectFile()" (so we can fixup the object file sections) and -// also for "Module::GetSymbolVendor()" (so we can fixup the symbol file id. +// also for "Module::GetSymbolFile()" (so we can fixup the symbol file id. const SymbolFileDWARFDebugMap::FileRangeMap & SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( @@ -60,11 +60,11 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( return file_range_map; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) - log->Printf( - "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", - static_cast<void *>(this), - oso_module->GetSpecificationDescription().c_str()); + LLDB_LOGF( + log, + "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", + static_cast<void *>(this), + oso_module->GetSpecificationDescription().c_str()); std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) { @@ -173,12 +173,12 @@ public: ~DebugMapModule() override = default; - SymbolVendor * - GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = nullptr) override { + SymbolFile * + GetSymbolFile(bool can_create = true, + lldb_private::Stream *feedback_strm = nullptr) override { // Scope for locker if (m_symfile_up.get() || !can_create) - return m_symfile_up.get(); + return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; ModuleSP exe_module_sp(m_exe_module_wp.lock()); if (exe_module_sp) { @@ -186,30 +186,28 @@ public: ObjectFile *oso_objfile = GetObjectFile(); if (oso_objfile) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - SymbolVendor *symbol_vendor = - Module::GetSymbolVendor(can_create, feedback_strm); - if (symbol_vendor) { + if (SymbolFile *symfile = + Module::GetSymbolFile(can_create, feedback_strm)) { // Set a pointer to this class to set our OSO DWARF file know that // the DWARF is being used along with a debug map and that it will // have the remapped sections that we do below. SymbolFileDWARF *oso_symfile = - SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF( - symbol_vendor->GetSymbolFile()); + SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile); if (!oso_symfile) return nullptr; ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); - SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); + SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile(); - if (exe_objfile && exe_sym_vendor) { + if (exe_objfile && exe_symfile) { oso_symfile->SetDebugMapModule(exe_module_sp); // Set the ID of the symbol file DWARF to the index of the OSO // shifted left by 32 bits to provide a unique prefix for any // UserID's that get created in the symbol file. oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull); } - return symbol_vendor; + return symfile; } } } @@ -239,13 +237,13 @@ const char *SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader (debug map)."; } -SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARFDebugMap(obj_file); +SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARFDebugMap(std::move(objfile_sp)); } -SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFile *ofile) - : SymbolFile(ofile), m_flags(), m_compile_unit_infos(), m_func_indexes(), - m_glob_indexes(), +SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(), + m_func_indexes(), m_glob_indexes(), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {} @@ -260,12 +258,12 @@ void SymbolFileDWARFDebugMap::InitOSO() { // If the object file has been stripped, there is no sense in looking further // as all of the debug symbols for the debug map will not be available - if (m_obj_file->IsStripped()) + if (m_objfile_sp->IsStripped()) return; // Also make sure the file type is some sort of executable. Core files, debug // info files (dSYM), object files (.o files), and stub libraries all can - switch (m_obj_file->GetType()) { + switch (m_objfile_sp->GetType()) { case ObjectFile::eTypeInvalid: case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeDebugInfo: @@ -286,7 +284,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // these files exist and also contain valid DWARF. If we get any of that then // we return the abilities of the first N_OSO's DWARF. - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); @@ -352,7 +350,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // The sibling index can't be less that or equal to the current index // "i" if (sibling_idx == UINT32_MAX) { - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO in symbol with UID %u has invalid sibling in debug map, " "please file a bug and attach the binary listed in this error", so_symbol->GetID()); @@ -363,28 +361,27 @@ void SymbolFileDWARFDebugMap::InitOSO() { m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID(); m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID(); - if (log) - log->Printf("Initialized OSO 0x%8.8x: file=%s", i, - oso_symbol->GetName().GetCString()); + LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i, + oso_symbol->GetName().GetCString()); } } else { if (oso_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO symbol[%u] can't be found, please file a bug and attach " "the binary listed in this error", oso_idx); else if (so_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO not found for N_OSO symbol[%u], please file a bug and " "attach the binary listed in this error", oso_idx); else if (so_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", so_symbol->GetType(), oso_idx); else if (oso_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", oso_symbol->GetType(), oso_idx); @@ -421,7 +418,11 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // than the one from the CU. auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>( FileSystem::Instance().GetModificationTime(oso_file)); - if (oso_mod_time != comp_unit_info->oso_mod_time) { + // A timestamp of 0 means that the linker was in deterministic mode. In + // that case, we should skip the check against the filesystem last + // modification timestamp, since it will never match. + if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() && + oso_mod_time != comp_unit_info->oso_mod_time) { obj_file->GetModule()->ReportError( "debug map object file '%s' has changed (actual time is " "%s, debug map time is %s" @@ -448,7 +449,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // since .o files for "i386-apple-ios" will historically show up as "i386 // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or // LC_VERSION_MIN_IPHONEOS load command... - oso_arch.SetTriple(m_obj_file->GetModule() + oso_arch.SetTriple(m_objfile_sp->GetModule() ->GetArchitecture() .GetTriple() .getArchName() @@ -534,12 +535,8 @@ SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) { SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( CompileUnitInfo *comp_unit_info) { - Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); - if (oso_module) { - SymbolVendor *sym_vendor = oso_module->GetSymbolVendor(); - if (sym_vendor) - return GetSymbolFileAsSymbolFileDWARF(sym_vendor->GetSymbolFile()); - } + if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info)) + return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile()); return nullptr; } @@ -562,7 +559,7 @@ uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() { return 0; } -uint32_t SymbolFileDWARFDebugMap::GetNumCompileUnits() { +uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() { InitOSO(); return m_compile_unit_infos.size(); } @@ -581,13 +578,12 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { lldb::user_id_t cu_id = 0; m_compile_unit_infos[cu_idx].compile_unit_sp = std::make_shared<CompileUnit>( - m_obj_file->GetModule(), nullptr, so_file_spec, cu_id, + m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id, eLanguageTypeUnknown, eLazyBoolCalculate); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { - // Let our symbol vendor know about this compile unit - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp); + SetCompileUnitAtIndex(cu_idx, + m_compile_unit_infos[cu_idx].compile_unit_sp); } } } @@ -625,6 +621,7 @@ size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule( lldb::LanguageType SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLanguage(comp_unit); @@ -632,6 +629,7 @@ SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseFunctions(comp_unit); @@ -639,6 +637,7 @@ size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLineTable(comp_unit); @@ -646,14 +645,24 @@ bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseDebugMacros(comp_unit); return false; } +void SymbolFileDWARFDebugMap::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); + if (oso_dwarf) + oso_dwarf->ForEachExternalModule(comp_unit, f); +} + bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseSupportFiles(comp_unit, support_files); @@ -661,6 +670,7 @@ bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, } bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseIsOptimized(comp_unit); @@ -669,6 +679,7 @@ bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARFDebugMap::ParseImportedModules( const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseImportedModules(sc, imported_modules); @@ -676,6 +687,7 @@ bool SymbolFileDWARFDebugMap::ParseImportedModules( } size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); if (!comp_unit) return 0; @@ -687,6 +699,7 @@ size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseTypes(comp_unit); @@ -695,6 +708,7 @@ size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseVariablesForContext(sc); @@ -702,6 +716,7 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { } Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) @@ -738,8 +753,9 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { const addr_t exe_file_addr = exe_so_addr.GetFileAddress(); @@ -766,7 +782,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, Address oso_so_addr; if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) { resolved_flags |= - oso_module->GetSymbolVendor()->ResolveSymbolContext( + oso_module->GetSymbolFile()->ResolveSymbolContext( oso_so_addr, resolve_scope, sc); } } @@ -780,6 +796,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( const FileSpec &file_spec, uint32_t line, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t initial = sc_list.GetSize(); const uint32_t cu_count = GetNumCompileUnits(); @@ -807,12 +824,11 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( return sc_list.GetSize() - initial; } -uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( +void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name" uint32_t max_matches, VariableList &variables) { - const uint32_t original_size = variables.GetSize(); const size_t match_count = indexes.size(); for (size_t i = 0; i < match_count; ++i) { uint32_t oso_idx; @@ -821,28 +837,26 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( if (comp_unit_info) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) { - if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, - variables)) - if (variables.GetSize() > max_matches) - break; + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + if (variables.GetSize() > max_matches) + break; } } } - return variables.GetSize() - original_size; } -uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( +void SymbolFileDWARFDebugMap::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { - - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = oso_dwarf->FindGlobalVariables( - name, parent_decl_ctx, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -861,22 +875,18 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } -uint32_t -SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - +void SymbolFileDWARFDebugMap::FindGlobalVariables( + const RegularExpression ®ex, uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = - oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -895,9 +905,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex( @@ -993,71 +1000,58 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp, } } -uint32_t SymbolFileDWARFDebugMap::FindFunctions( +void SymbolFileDWARFDebugMap::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (name = %s)", name.GetCString()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, + include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -uint32_t SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, - bool include_inlines, - bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(regex, include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(regex, include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - TypeList &type_list) { +void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + TypeList &type_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)", type_mask); - uint32_t initial_size = type_list.GetSize(); SymbolFileDWARF *oso_dwarf = nullptr; if (sc_scope) { SymbolContext sc; @@ -1075,7 +1069,6 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, return false; }); } - return type_list.GetSize() - initial_size; } std::vector<lldb_private::CallEdge> @@ -1124,7 +1117,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( // N_SO. SymbolFileDWARF *oso_dwarf = nullptr; TypeSP type_sp; - ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); + ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile(); if (module_objfile) { Symtab *symtab = module_objfile->GetSymtab(); if (symtab) { @@ -1177,23 +1170,17 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( return TypeSP(); } -uint32_t SymbolFileDWARFDebugMap::FindTypes( +void SymbolFileDWARFDebugMap::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); - - const uint32_t initial_types_size = types.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(name, parent_decl_ctx, append, max_matches, + oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches, searched_symbol_files, types); return types.GetSize() >= max_matches; }); - - return types.GetSize() - initial_types_size; } // @@ -1212,6 +1199,7 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( lldb_private::ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompilerDeclContext matching_namespace; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { @@ -1284,8 +1272,7 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, cu_sp.get()); } else { m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp; - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, cu_sp); + SetCompileUnitAtIndex(cu_idx, cu_sp); } } } @@ -1388,8 +1375,8 @@ bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) { if (addr_module == exe_module) return true; // Address is already in terms of the main executable module - CompileUnitInfo *cu_info = GetCompileUnitInfo(GetSymbolFileAsSymbolFileDWARF( - addr_module->GetSymbolVendor()->GetSymbolFile())); + CompileUnitInfo *cu_info = GetCompileUnitInfo( + GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile())); if (cu_info) { const lldb::addr_t oso_file_addr = addr.GetFileAddress(); const FileRangeMap::Entry *oso_range_entry = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index afc6142e8231c..7adee1b356ce0 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -34,19 +34,16 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileDWARFDebugMap(lldb_private::ObjectFile *ofile); + SymbolFileDWARFDebugMap(lldb::ObjectFileSP objfile_sp); ~SymbolFileDWARFDebugMap() override; uint32_t CalculateAbilities() override; void InitializeObject() override; // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -56,6 +53,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -91,34 +92,34 @@ public: bool check_inlines, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; std::vector<lldb_private::CallEdge> ParseCallEdgesInFunction(lldb_private::UserID func_id) override; @@ -174,6 +175,9 @@ protected: // Protected Member Functions void InitOSO(); + uint32_t CalculateNumCompileUnits() override; + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { return (uint32_t)((uid >> 32ull) - 1ull); } @@ -232,7 +236,7 @@ protected: static int SymbolContainsSymbolWithID(lldb::user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info); - uint32_t PrivateFindGlobalVariables( + void PrivateFindGlobalVariables( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c5b54b65ea29c..b0f7e813d4f8b 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -23,21 +23,21 @@ using namespace lldb_private; SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu) - : SymbolFileDWARF(objfile.get(), objfile->GetSectionList( - /*update_module_section_list*/ false)), - m_obj_file_sp(objfile), m_base_dwarf_cu(dwarf_cu) { + : SymbolFileDWARF(objfile, objfile->GetSectionList( + /*update_module_section_list*/ false)), + m_base_dwarf_cu(dwarf_cu) { SetID(((lldb::user_id_t)dwarf_cu.GetID()) << 32); } void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { const SectionList *section_list = - m_obj_file->GetSectionList(false /* update_module_section_list */); + m_objfile_sp->GetSectionList(false /* update_module_section_list */); if (section_list) { SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); if (section_sp) { - if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) + if (m_objfile_sp->ReadSectionData(section_sp.get(), data) != 0) return; data.Clear(); @@ -140,7 +140,7 @@ SymbolFileDWARFDwo::GetLocationListFormat() const { return DWARFExpression::SplitDwarfLocationList; } -TypeSystem * +llvm::Expected<TypeSystem &> SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile().GetTypeSystemForLanguage(language); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 9b2f3bb84c4f3..ad290cdcf65e8 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -30,7 +30,7 @@ public: size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets) override; - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; DWARFDIE @@ -71,7 +71,6 @@ protected: DWARFCompileUnit *ComputeCompileUnit(); - lldb::ObjectFileSP m_obj_file_sp; DWARFCompileUnit &m_base_dwarf_cu; DWARFCompileUnit *m_cu = nullptr; }; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td new file mode 100644 index 0000000000000..ef6ae34985882 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "symbolfiledwarf" in { + def SymLinkPaths: Property<"comp-dir-symlink-paths", "FileSpecList">, + Global, + DefaultStringValue<"">, + Desc<"If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time.">; + def IgnoreIndexes: Property<"ignore-file-indexes", "Boolean">, + Global, + DefaultFalse, + Desc<"Ignore indexes present in the object files and always index DWARF manually.">; +} diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 8da7e22262664..4862fea8d0798 100644 --- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -55,6 +55,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_partial_unit: done = true; break; + default: + break; } } parent_arg_die = parent_arg_die.GetParent(); |