diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 241 |
1 files changed, 209 insertions, 32 deletions
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; } |