diff options
Diffstat (limited to 'lldb/source/Plugins')
7 files changed, 491 insertions, 68 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 2fb360440f6..ab20844bfcf 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -33,6 +33,18 @@ public: const DWARFDIE &die) = 0; virtual bool + CanCompleteType (const lldb_private::CompilerType &compiler_type) + { + return false; + } + + virtual bool + CompleteType (const lldb_private::CompilerType &compiler_type) + { + return false; + } + + virtual bool CompleteTypeFromDWARF (const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &compiler_type) = 0; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index caa8c63f8ad..68a0285b69d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -24,11 +24,14 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" #include "lldb/Host/Host.h" +#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Target/Language.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" @@ -114,6 +117,78 @@ struct BitfieldInfo } }; + +ClangASTImporter & +DWARFASTParserClang::GetClangASTImporter() +{ + if (!m_clang_ast_importer_ap) + { + m_clang_ast_importer_ap.reset (new ClangASTImporter); + } + return *m_clang_ast_importer_ap; +} + + +TypeSP +DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log) +{ + ModuleSP dwo_module_sp = die.GetContainingDWOModule(); + if (dwo_module_sp) + { + // This type comes from an external DWO module + std::vector<CompilerContext> dwo_context; + die.GetDWOContext(dwo_context); + TypeMap dwo_types; + if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types)) + { + const size_t num_dwo_types = dwo_types.GetSize(); + if (num_dwo_types == 1) + { + // 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 + TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0); + if (dwo_type_sp) + { + lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType(); + + lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type); + + //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString()); + if (type) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + TypeSP type_sp (new Type (die.GetID(), + dwarf, + dwo_type_sp->GetName(), + dwo_type_sp->GetByteSize(), + NULL, + LLDB_INVALID_UID, + Type::eEncodingInvalid, + &dwo_type_sp->GetDeclaration(), + type, + Type::eResolveStateForward)); + + dwarf->GetTypeList()->Insert(type_sp); + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); + if (tag_decl) + LinkDeclContextToDIE(tag_decl, die); + else + { + clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + } + return type_sp; + } + } + } + } + } + return TypeSP(); +} + TypeSP DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, const DWARFDIE &die, @@ -487,15 +562,15 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) - { - type_sp = unique_ast_entry_ap->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; + type_sp = unique_ast_entry_ap->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); @@ -600,6 +675,11 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, type_name_cstr); } + // 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); @@ -833,7 +913,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, case DW_AT_type: encoding_form = form_value; break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break; + case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break; case DW_AT_allocated: case DW_AT_associated: case DW_AT_bit_stride: @@ -850,6 +930,54 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, } } + if (is_forward_declaration) + { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + 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), + type_name_cstr, + 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->DebugInfo()->GetDIE(DIERef(type_sp->GetID()))); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + + } DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); CompilerType enumerator_clang_type; @@ -1130,7 +1258,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (class_type) { bool alternate_defn = false; - if (class_type->GetID() != decl_ctx_die.GetID()) + if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE()) { alternate_defn = true; @@ -1798,6 +1926,33 @@ DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die, } bool +DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type) +{ + if (m_clang_ast_importer_ap) + return ClangASTContext::CanImport(compiler_type, GetClangASTImporter()); + else + return false; +} + +bool +DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type) +{ + if (CanCompleteType(compiler_type)) + { + if (ClangASTContext::Import(compiler_type, GetClangASTImporter())) + { + ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); + return true; + } + else + { + ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false); + } + } + return false; +} + +bool DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, lldb_private::Type *type, CompilerType &clang_type) @@ -1868,25 +2023,17 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, DWARFDIECollection member_function_dies; DelayedPropertyList delayed_properties; - if (!ParseChildMembers (sc, - die, - clang_type, - class_language, - base_classes, - member_accessibilities, - member_function_dies, - delayed_properties, - default_accessibility, - is_a_class, - layout_info)) - { - auto module = dwarf->GetObjectFile()->GetModule(); - module->ReportError (":: Class %s has members with incomplete type.", die.GetName()); - if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) - module->ReportError(":: Try compiling the source file with -fno-limit-debug-info."); - - return false; - } + ParseChildMembers (sc, + die, + clang_type, + class_language, + base_classes, + member_accessibilities, + member_function_dies, + delayed_properties, + default_accessibility, + is_a_class, + layout_info); // Now parse any methods if there were any... size_t num_functions = member_function_dies.Size(); @@ -1977,7 +2124,14 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) module->ReportError (":: Try compiling the source file with -fno-limit-debug-info."); - return false; + // We have no choice other than to pretend that the base class + // is complete. If we don't do this, clang will crash when we + // call setBases() inside of "clang_type.SetBaseClassesForClassType()" + // below. Since we provide layout assistance, all ivars in this + // class and other classes will be fine, this is the best we can do + // short of crashing. + ClangASTContext::StartTagDeclarationDefinition (base_class_type); + ClangASTContext::CompleteTagDeclarationDefinition (base_class_type); } } } @@ -2420,7 +2574,6 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, if (!parent_die) return 0; - uint32_t incomplete_member_info_count = 0; uint32_t member_idx = 0; BitfieldInfo last_field_info; @@ -2754,8 +2907,8 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, } CompilerType member_clang_type = member_type->GetLayoutCompilerType (); - if (!member_clang_type.IsCompleteType() && !member_clang_type.GetCompleteType()) - incomplete_member_info_count += 1; + if (!member_clang_type.IsCompleteType()) + member_clang_type.GetCompleteType(); { // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>). @@ -2789,6 +2942,30 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, } } + if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false) + { + if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) + module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info", + parent_die.GetOffset(), + parent_die.GetName(), + die.GetOffset(), + name); + else + module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", + parent_die.GetOffset(), + parent_die.GetName(), + die.GetOffset(), + name, + sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); + // We have no choice other than to pretend that the member class + // is complete. If we don't do this, clang will crash when trying + // to layout the class. Since we provide layout assistance, all + // ivars in this class and other classes will be fine, this is + // the best we can do short of crashing. + ClangASTContext::StartTagDeclarationDefinition(member_clang_type); + ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type); + } + field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type, name, member_clang_type, @@ -2978,7 +3155,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, } } - return incomplete_member_info_count == 0; + return true; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index e46972e261b..3814758fdd2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -47,6 +47,12 @@ public: const DWARFDIE &die) override; bool + CanCompleteType (const lldb_private::CompilerType &compiler_type) override; + + bool + CompleteType (const lldb_private::CompilerType &compiler_type) override; + + bool CompleteTypeFromDWARF (const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &compiler_type) override; @@ -175,6 +181,19 @@ protected: void LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); + lldb_private::ClangASTImporter & + GetClangASTImporter(); + + 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; @@ -188,6 +207,7 @@ protected: DIEToDeclContextMap m_die_to_decl_ctx; DeclContextToDIEMap m_decl_ctx_to_die; RecordDeclToLayoutMap m_record_decl_to_layout_map; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap; }; #endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 2ca4394b28e..708b88a1fe9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -22,8 +22,11 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeSystem.h" +using namespace lldb_private; + DIERef DWARFDIE::GetDIERef() const { @@ -307,6 +310,51 @@ DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const } } +void +DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const +{ + const dw_tag_t tag = Tag(); + if (tag == DW_TAG_compile_unit) + return; + DWARFDIE parent = GetParent(); + if (parent) + parent.GetDWOContext(context); + switch (tag) + { + case DW_TAG_module: + context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + break; + case DW_TAG_namespace: + context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName()))); + break; + case DW_TAG_structure_type: + context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName()))); + break; + case DW_TAG_union_type: + context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + break; + case DW_TAG_class_type: + context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + break; + case DW_TAG_enumeration_type: + context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName()))); + break; + case DW_TAG_subprogram: + context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname()))); + break; + case DW_TAG_variable: + context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname()))); + break; + case DW_TAG_typedef: + context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + break; + default: + assert(!"remove this prior to checkin"); + break; + } +} + + DWARFDIE DWARFDIE::GetParentDeclContextDIE () const @@ -371,6 +419,45 @@ DWARFDIE::IsStructOrClass () const return tag == DW_TAG_class_type || tag == DW_TAG_structure_type; } + +DWARFDIE +DWARFDIE::GetContainingDWOModuleDIE () const +{ + if (IsValid()) + { + DWARFDIE top_module_die; + // Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so + for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent()) + { + const dw_tag_t tag = parent.Tag(); + if (tag == DW_TAG_module) + top_module_die = parent; + else if (tag == DW_TAG_compile_unit) + break; + } + + return top_module_die; + } + return DWARFDIE(); +} + +lldb::ModuleSP +DWARFDIE::GetContainingDWOModule () const +{ + if (IsValid()) + { + DWARFDIE dwo_module_die = GetContainingDWOModuleDIE(); + + if (dwo_module_die) + { + const char *module_name = dwo_module_die.GetName(); + if (module_name) + return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name)); + } + } + return lldb::ModuleSP(); +} + bool DWARFDIE::HasChildren () const { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index f3e72d74d19..db37a45ad01 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -126,6 +126,12 @@ public: m_die = nullptr; } + lldb::ModuleSP + GetContainingDWOModule () const; + + DWARFDIE + GetContainingDWOModuleDIE () const; + //---------------------------------------------------------------------- // Accessing information about a DIE //---------------------------------------------------------------------- @@ -217,6 +223,9 @@ public: void GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const; + void + GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const; + //---------------------------------------------------------------------- // Getting attribute values from the DIE. // diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 70293384e7f..fd254ad9c29 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1077,9 +1077,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage())) { UpdateExternalModuleListIfNeeded(); - for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules) + for (const auto &pair : m_external_type_modules) { - imported_modules.push_back(external_type_module.second.m_name); + imported_modules.push_back(pair.first); } } } @@ -1515,13 +1515,32 @@ bool SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type) { CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); - return GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()); + if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType())) + { + return true; + } + TypeSystem *type_system = compiler_type.GetTypeSystem(); + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->CanCompleteType(compiler_type); + } + return false; } bool SymbolFileDWARF::CompleteType (CompilerType &compiler_type) { + TypeSystem *type_system = compiler_type.GetTypeSystem(); + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type)) + return dwarf_ast->CompleteType(compiler_type); + } + // We have a struct/union/class/enum that needs to be fully resolved. CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType()); @@ -1641,6 +1660,17 @@ SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc) return false; } +lldb::ModuleSP +SymbolFileDWARF::GetDWOModule (ConstString name) +{ + UpdateExternalModuleListIfNeeded(); + const auto &pos = m_external_type_modules.find(name); + if (pos != m_external_type_modules.end()) + return pos->second; + else + return lldb::ModuleSP(); +} + void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1658,37 +1688,24 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded() const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly(); if (die && die.HasChildren() == false) { - const uint64_t name_strp = die.GetAttributeValueAsUnsigned (DW_AT_name, UINT64_MAX); - const uint64_t dwo_path_strp = die.GetAttributeValueAsUnsigned (DW_AT_GNU_dwo_name, UINT64_MAX); - - if (name_strp != UINT64_MAX) + const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr); + + if (name) { - if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end()) + ConstString const_name(name); + if (m_external_type_modules.find(const_name) == m_external_type_modules.end()) { - const char *name = get_debug_str_data().PeekCStr(name_strp); - const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp); - if (name || dwo_path) + ModuleSP module_sp; + const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); + if (dwo_path) { - ModuleSP module_sp; - if (dwo_path) - { - ModuleSpec dwo_module_spec; - dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); - dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); - //printf ("Loading dwo = '%s'\n", dwo_path); - Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL); - } - - if (dwo_path_strp != LLDB_INVALID_UID) - { - m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp }; - } - else - { - // This hack should be removed promptly once clang emits both. - m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp }; - } + ModuleSpec dwo_module_spec; + dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); + dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); + //printf ("Loading dwo = '%s'\n", dwo_path); + Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL); } + m_external_type_modules[const_name] = module_sp; } } } @@ -2970,6 +2987,104 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, } return num_matches; } + else + { + 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 (sc, + name, + parent_decl_ctx, + append, + max_matches, + types); + if (num_external_matches) + return num_external_matches; + } + } + } + } + + return 0; +} + + +size_t +SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context, + bool append, + TypeMap& types) +{ + if (!append) + types.Clear(); + + if (context.empty()) + return 0; + + DIEArray die_offsets; + + ConstString name = context.back().name; + + if (m_using_apple_tables) + { + if (m_apple_types_ap.get()) + { + const char *name_cstr = name.GetCString(); + m_apple_types_ap->FindByName (name_cstr, die_offsets); + } + } + else + { + if (!m_indexed) + Index (); + + m_type_index.Find (name, die_offsets); + } + + const size_t num_die_matches = die_offsets.size(); + + if (num_die_matches) + { + size_t num_matches = 0; + DWARFDebugInfo* debug_info = DebugInfo(); + for (size_t i=0; i<num_die_matches; ++i) + { + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); + + if (die) + { + std::vector<CompilerContext> die_context; + die.GetDWOContext(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 + { + if (m_using_apple_tables) + { + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", + die_ref.die_offset, name.GetCString()); + } + } + + } + return num_matches; + } return 0; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 818ce68eabb..2bdbc37c51f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -211,6 +211,11 @@ public: uint32_t max_matches, lldb_private::TypeMap& types) override; + size_t + FindTypes (const std::vector<lldb_private::CompilerContext> &context, + bool append, + lldb_private::TypeMap& types) override; + lldb_private::TypeList * GetTypeList () override; @@ -306,6 +311,9 @@ public: virtual lldb_private::DWARFExpression::LocationListFormat GetLocationListFormat() const; + lldb::ModuleSP + GetDWOModule (lldb_private::ConstString name); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; @@ -483,12 +491,7 @@ protected: typedef std::set<lldb_private::Type *> TypeSet; - typedef struct { - lldb_private::ConstString m_name; - lldb::ModuleSP m_module_sp; - } ClangModuleInfo; - - typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap; + typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap; void GetTypes (const DWARFDIE &die, |

