From 4e800003099b593e66f12dc21be5fbac5279e03e Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 30 Apr 2024 16:23:11 -0400 Subject: [PATCH 01/10] [lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 270 +++++++----------- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 105 ++++++- .../SymbolFile/DWARF/SymbolFileDWARF.h | 14 + .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 5 + .../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 2 + .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 95 +++--- .../SymbolFile/DWARF/UniqueDWARFASTType.h | 21 +- 7 files changed, 296 insertions(+), 216 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index bea11e0e3840af..7ad661c9a9d49b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -252,7 +252,8 @@ static void ForcefullyCompleteType(CompilerType type) { static void PrepareContextToReceiveMembers(TypeSystemClang &ast, ClangASTImporter &ast_importer, clang::DeclContext *decl_ctx, - DWARFDIE die, + const DWARFDIE &decl_ctx_die, + const DWARFDIE &die, const char *type_name_cstr) { auto *tag_decl_ctx = clang::dyn_cast(decl_ctx); if (!tag_decl_ctx) @@ -279,6 +280,13 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast, type_name_cstr ? type_name_cstr : "", die.GetOffset()); } + // By searching for the definition DIE of the decl_ctx type, we will either: + // 1. Found the the definition DIE and start its definition with + // TypeSystemClang::StartTagDeclarationDefinition. + // 2. Unable to find it, then need to forcefully complete it. + die.GetDWARF()->FindDefinitionDIE(decl_ctx_die); + if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined()) + return; // We don't have a type definition and/or the import failed. We must // forcefully complete the type to avoid crashes. ForcefullyCompleteType(type); @@ -620,10 +628,11 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (tag == DW_TAG_typedef) { // DeclContext will be populated when the clang type is materialized in // Type::ResolveCompilerType. - PrepareContextToReceiveMembers( - m_ast, GetClangASTImporter(), - GetClangDeclContextContainingDIE(die, nullptr), die, - attrs.name.GetCString()); + DWARFDIE decl_ctx_die; + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, &decl_ctx_die); + PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, + decl_ctx_die, die, attrs.name.GetCString()); if (attrs.type.IsValid()) { // Try to parse a typedef from the (DWARF embedded in the) Clang @@ -1100,32 +1109,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, // struct and see if this is actually a C++ method Type *class_type = dwarf->ResolveType(decl_ctx_die); if (class_type) { - if (class_type->GetID() != decl_ctx_die.GetID() || - IsClangModuleFwdDecl(decl_ctx_die)) { - - // We uniqued the parent class of this function to another - // class so we now need to associate all dies under - // "decl_ctx_die" to DIEs in the DIE for "class_type"... - DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); - - if (class_type_die) { - std::vector failures; - - CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, - class_type, failures); - - // FIXME do something with these failures that's - // smarter than just dropping them on the ground. - // Unfortunately classes don't like having stuff added - // to them after their definitions are complete... - - Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - return type_ptr->shared_from_this(); - } - } - } - if (attrs.specification.IsValid()) { // We have a specification which we are going to base our // function prototype off of, so we need this type to be @@ -1260,6 +1243,39 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } } } + // By here, we should have already completed the c++ class_type + // because if either specification or abstract_origin is present, we + // call GetClangDeclContextForDIE to resolve the DW_TAG_subprogram + // refered by this one until we reached the DW_TAG_subprogram without + // specification or abstract_origin (the else branch above). Then the + // above GetFullCompilerType() will complete the class_type if it's + // not completed yet. After that, we will have the mapping from DIEs + // in class_type_die to DeclContexts in m_die_to_decl_ctx. + if (class_type->GetID() != decl_ctx_die.GetID() || + IsClangModuleFwdDecl(decl_ctx_die)) { + + // We uniqued the parent class of this function to another + // class so we now need to associate all dies under + // "decl_ctx_die" to DIEs in the DIE for "class_type"... + DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); + + if (class_type_die) { + std::vector failures; + + CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, + class_type, failures); + + // FIXME do something with these failures that's + // smarter than just dropping them on the ground. + // Unfortunately classes don't like having stuff added + // to them after their definitions are complete... + + Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + return type_ptr->shared_from_this(); + } + } + } } } } @@ -1651,6 +1667,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, ConstString unique_typename(attrs.name); Declaration unique_decl(attrs.decl); + uint64_t byte_size = attrs.byte_size.value_or(0); if (attrs.name) { if (Language::LanguageIsCPlusPlus(cu_language)) { @@ -1664,13 +1681,34 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, } if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, attrs.byte_size.value_or(-1), - *unique_ast_entry_up)) { + unique_typename, die, unique_decl, byte_size, + attrs.is_forward_declaration, *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); + if (!attrs.is_forward_declaration) { + dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace( + unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef()); + // If the parameter DIE is definition and the entry in the map is + // declaration, then we need to update the entry to point to the + // definition DIE. + if (unique_ast_entry_up->m_is_forward_declaration) { + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_byte_size = byte_size; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_is_forward_declaration = false; + // Need to update Type ID to refer to the definition DIE. because + // it's used in ParseSubroutine to determine if we need to copy cxx + // method types from a declaration DIE to this definition DIE. + type_sp->SetID(die.GetID()); + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + TypeSystemClang::StartTagDeclarationDefinition( + type_sp->GetForwardCompilerType()); + } + } return type_sp; } } @@ -1707,112 +1745,22 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, 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({0:p}) - {1:x16}: {2} type " - "\"{3}\" is an " - "incomplete objc type, complete type is {4:x8}", - static_cast(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({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, trying to find complete type", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString()); - } - // See if the type comes from a Clang module and if so, track down // that type. type_sp = ParseTypeFromClangModule(sc, die, log); if (type_sp) return type_sp; - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); - - 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); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, complete type is {4:x8}", - static_cast(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); UNUSED_IF_ASSERT_DISABLED(tag_decl_kind); - bool clang_type_was_created = false; - clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); + DWARFDIE decl_ctx_die; + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die, - attrs.name.GetCString()); + PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, + decl_ctx_die, die, attrs.name.GetCString()); if (attrs.accessibility == eAccessNone && decl_ctx) { // Check the decl context that contains this class/struct/union. If @@ -1850,20 +1798,20 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, 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; + if (!clang_type) { clang_type = m_ast.CreateRecordType( decl_ctx, GetOwningClangModule(die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, attrs.exports_symbols); } - + if (!attrs.is_forward_declaration) + dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(), + *die.GetDIERef()); // 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. @@ -1880,7 +1828,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, 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.value_or(0); + unique_ast_entry_up->m_byte_size = byte_size; + unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration; dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, *unique_ast_entry_up); @@ -1921,38 +1870,33 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, GetClangASTImporter().SetRecordLayout(record_decl, layout); } } - } 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) - TypeSystemClang::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->GetForwardDeclCompilerTypeToDIE().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->GetForwardDeclCompilerTypeToDIE().try_emplace( - ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), - *die.GetDIERef()); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); } + // 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) + TypeSystemClang::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->GetForwardDeclCompilerTypeToDIE().count( + ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( + ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), + *die.GetDIERef()); + 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 diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 49f13d2c89e380..5a317db7e74028 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1631,13 +1631,19 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { return true; } - DWARFDIE dwarf_die = GetDIE(die_it->getSecond()); + DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond())); if (dwarf_die) { // Once we start resolving this type, remove it from the forward // declaration map in case anyone child members or other types require this // type to get resolved. The type will get resolved when all of the calls // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done. - GetForwardDeclCompilerTypeToDIE().erase(die_it); + // Need to get a new iterator because FindDefinitionDIE might add new + // entries into the map and invalidate previous iterator. + auto die_it = GetForwardDeclCompilerTypeToDIE().find( + compiler_type_no_qualifiers.GetOpaqueQualType()); + if (die_it != GetForwardDeclCompilerTypeToDIE().end()) { + GetForwardDeclCompilerTypeToDIE().erase(die_it); + } Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); @@ -1654,6 +1660,101 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { return false; } +DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { + auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE()); + if (def_die_it != GetDeclarationDIEToDefinitionDIE().end()) + return GetDIE(def_die_it->getSecond()); + + ParsedDWARFTypeAttributes attrs(die); + const dw_tag_t tag = die.Tag(); + TypeSP type_sp; + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration DIE, trying to find definition DIE", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + // We haven't parse definition die for this type, starting to search for it. + // After we found the definition die, the GetDeclarationDIEToDefinitionDIE() + // map will have the new mapping from this declaration die to definition die. + 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 = + FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + 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 && log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type " + "\"{3}\" is an " + "incomplete objc type, complete type is {4:x8}", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + } + } + bool is_forward_declaration = + attrs.is_forward_declaration || + (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && + SymbolFileDWARF::GetLanguage(*die.GetCU()) == eLanguageTypeObjC); + if (is_forward_declaration) { + type_sp = FindDefinitionTypeForDWARFDeclContext(die); + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = 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); + } + if (type_sp && log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration, complete type is {4:x8}", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + } + } + def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE()); + if (def_die_it != GetDeclarationDIEToDefinitionDIE().end()) + return GetDIE(def_die_it->getSecond()); + + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration, unable to find definition DIE for it", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + return DWARFDIE(); +} + Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 7282c08c6857c9..86d5a3d4f6c46d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -182,6 +182,8 @@ class SymbolFileDWARF : public SymbolFileCommon { void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; + DWARFDIE FindDefinitionDIE(const DWARFDIE &die); + void GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector &mangled_names) override; @@ -342,6 +344,11 @@ class SymbolFileDWARF : public SymbolFileCommon { return m_forward_decl_compiler_type_to_die; } + typedef llvm::DenseMap DIEToDIE; + virtual DIEToDIE &GetDeclarationDIEToDefinitionDIE() { + return m_die_to_def_die; + } + typedef llvm::DenseMap DIEToVariableSP; @@ -533,9 +540,16 @@ class SymbolFileDWARF : public SymbolFileCommon { NameToOffsetMap m_function_scope_qualified_name_map; std::unique_ptr m_ranges; UniqueDWARFASTTypeMap m_unique_ast_type_map; + // A map from DIE to lldb_private::Type. For record type, the key might be + // either declaration DIE or definition DIE. DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; + // A map from CompilerType to the struct/class/union/enum DIE (might be a + // declaration or a definition) that is used to construct it. CompilerTypeToDIE m_forward_decl_compiler_type_to_die; + // A map from a struct/class/union/enum DIE (might be a declaration or a + // definition) to its definition DIE. + DIEToDIE m_die_to_def_die; llvm::DenseMap> m_type_unit_support_files; std::vector m_lldb_cu_to_dwarf_unit; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 85e1afd0d89761..cb5ec4ae026b3d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -110,6 +110,11 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { return GetBaseSymbolFile().GetDIEToVariable(); } +SymbolFileDWARF::DIEToDIE & +SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() { + return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE(); +} + SymbolFileDWARF::CompilerTypeToDIE & SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 1500540424b524..3e8cfb885aaee9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -74,6 +74,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF { CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override; + DIEToDIE &GetDeclarationDIEToDefinitionDIE() override; + UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; lldb::TypeSP diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 223518f0ae8241..cc23bb86f6805a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -16,60 +16,65 @@ using namespace lldb_private::plugin::dwarf; bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, const lldb_private::Declaration &decl, const int32_t byte_size, + bool is_forward_declaration, UniqueDWARFASTType &entry) const { for (const UniqueDWARFASTType &udt : m_collection) { // Make sure the tags match if (udt.m_die.Tag() == die.Tag()) { - // Validate byte sizes of both types only if both are valid. - if (udt.m_byte_size < 0 || byte_size < 0 || - udt.m_byte_size == byte_size) { - // Make sure the file and line match - if (udt.m_declaration == decl) { - // The type has the same name, and was defined on the same file and - // line. Now verify all of the parent DIEs match. - DWARFDIE parent_arg_die = die.GetParent(); - DWARFDIE parent_pos_die = udt.m_die.GetParent(); - bool match = true; - bool done = false; - while (!done && match && parent_arg_die && parent_pos_die) { - const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); - const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); - if (parent_arg_tag == parent_pos_tag) { - switch (parent_arg_tag) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_namespace: { - const char *parent_arg_die_name = parent_arg_die.GetName(); - if (parent_arg_die_name == - nullptr) // Anonymous (i.e. no-name) struct - { + // If they are not both definition DIEs or both declaration DIEs, then + // don't check for byte size and declaration location, because declaration + // DIEs usually don't have those info. + bool matching_size_declaration = + udt.m_is_forward_declaration != is_forward_declaration + ? true + : (udt.m_byte_size < 0 || byte_size < 0 || + udt.m_byte_size == byte_size) && + udt.m_declaration == decl; + if (matching_size_declaration) { + // The type has the same name, and was defined on the same file and + // line. Now verify all of the parent DIEs match. + DWARFDIE parent_arg_die = die.GetParent(); + DWARFDIE parent_pos_die = udt.m_die.GetParent(); + bool match = true; + bool done = false; + while (!done && match && parent_arg_die && parent_pos_die) { + const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); + const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); + if (parent_arg_tag == parent_pos_tag) { + switch (parent_arg_tag) { + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_namespace: { + const char *parent_arg_die_name = parent_arg_die.GetName(); + if (parent_arg_die_name == + nullptr) // Anonymous (i.e. no-name) struct + { + match = false; + } else { + const char *parent_pos_die_name = parent_pos_die.GetName(); + if (parent_pos_die_name == nullptr || + ((parent_arg_die_name != parent_pos_die_name) && + strcmp(parent_arg_die_name, parent_pos_die_name))) match = false; - } else { - const char *parent_pos_die_name = parent_pos_die.GetName(); - if (parent_pos_die_name == nullptr || - ((parent_arg_die_name != parent_pos_die_name) && - strcmp(parent_arg_die_name, parent_pos_die_name))) - match = false; - } - } break; - - case DW_TAG_compile_unit: - case DW_TAG_partial_unit: - done = true; - break; - default: - break; } + } break; + + case DW_TAG_compile_unit: + case DW_TAG_partial_unit: + done = true; + break; + default: + break; } - parent_arg_die = parent_arg_die.GetParent(); - parent_pos_die = parent_pos_die.GetParent(); } + parent_arg_die = parent_arg_die.GetParent(); + parent_pos_die = parent_pos_die.GetParent(); + } - if (match) { - entry = udt; - return true; - } + if (match) { + entry = udt; + return true; } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index bf3cbae55e5c7b..94619953d07ac5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -24,13 +24,16 @@ class UniqueDWARFASTType { UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {} UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die, - const Declaration &decl, int32_t byte_size) + const Declaration &decl, int32_t byte_size, + bool is_forward_declaration) : m_type_sp(type_sp), m_die(die), m_declaration(decl), - m_byte_size(byte_size) {} + m_byte_size(byte_size), + m_is_forward_declaration(is_forward_declaration) {} UniqueDWARFASTType(const UniqueDWARFASTType &rhs) : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die), - m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {} + m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size), + m_is_forward_declaration(rhs.m_is_forward_declaration) {} ~UniqueDWARFASTType() = default; @@ -40,6 +43,7 @@ class UniqueDWARFASTType { m_die = rhs.m_die; m_declaration = rhs.m_declaration; m_byte_size = rhs.m_byte_size; + m_is_forward_declaration = rhs.m_is_forward_declaration; } return *this; } @@ -48,6 +52,8 @@ class UniqueDWARFASTType { DWARFDIE m_die; Declaration m_declaration; int32_t m_byte_size = -1; + // True if the m_die is a forward declaration DIE. + bool m_is_forward_declaration = true; }; class UniqueDWARFASTTypeList { @@ -63,7 +69,8 @@ class UniqueDWARFASTTypeList { } bool Find(const DWARFDIE &die, const Declaration &decl, - const int32_t byte_size, UniqueDWARFASTType &entry) const; + const int32_t byte_size, bool is_forward_declaration, + UniqueDWARFASTType &entry) const; protected: typedef std::vector collection; @@ -81,11 +88,13 @@ class UniqueDWARFASTTypeMap { } bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl, - const int32_t byte_size, UniqueDWARFASTType &entry) const { + const int32_t byte_size, bool is_forward_declaration, + UniqueDWARFASTType &entry) const { const char *unique_name_cstr = name.GetCString(); collection::const_iterator pos = m_collection.find(unique_name_cstr); if (pos != m_collection.end()) { - return pos->second.Find(die, decl, byte_size, entry); + return pos->second.Find(die, decl, byte_size, is_forward_declaration, + entry); } return false; } From 751a58d24ec9e32234d2bfa672f51d255bfd78fa Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Wed, 1 May 2024 10:25:28 -0400 Subject: [PATCH 02/10] fix format --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 5a317db7e74028..c7069550ccf702 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1689,12 +1689,10 @@ DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { // 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 = - FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + type_sp = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - GetDebugMapSymfile(); + SymbolFileDWARFDebugMap *debug_map_symfile = 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... From c0a539ec9b3b468e5568cd6f569f51663fdafcac Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Thu, 2 May 2024 14:08:11 -0400 Subject: [PATCH 03/10] address comments --- .../Plugins/SymbolFile/DWARF/DWARFASTParser.h | 6 + .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 166 ++++++++++++++---- .../SymbolFile/DWARF/DWARFASTParserClang.h | 10 ++ .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 146 ++++----------- .../SymbolFile/DWARF/SymbolFileDWARF.h | 10 -- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 5 - .../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 2 - 7 files changed, 179 insertions(+), 166 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 66db396279e063..14b9cba05d3215 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -60,6 +60,12 @@ class DWARFASTParser { virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0; + // Return true if we found the definition DIE for it. is_forward_declaration + // is set to true if the parameter die is a declaration. + virtual bool + FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, + bool &is_forward_declaration) = 0; + static std::optional ParseChildArrayInfo(const DWARFDIE &parent_die, const ExecutionContext *exe_ctx = nullptr); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 7ad661c9a9d49b..8a8c303e1a8b2d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -154,6 +154,27 @@ static bool TagIsRecordType(dw_tag_t tag) { } } +static bool +IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs, + LanguageType cu_language) { + 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. + return true; + } + return attrs.is_forward_declaration; +} + TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -249,12 +270,10 @@ static void ForcefullyCompleteType(CompilerType type) { /// This function serves a similar purpose as RequireCompleteType above, but it /// avoids completing the type if it is not immediately necessary. It only /// ensures we _can_ complete the type later. -static void PrepareContextToReceiveMembers(TypeSystemClang &ast, - ClangASTImporter &ast_importer, - clang::DeclContext *decl_ctx, - const DWARFDIE &decl_ctx_die, - const DWARFDIE &die, - const char *type_name_cstr) { +void DWARFASTParserClang::PrepareContextToReceiveMembers( + TypeSystemClang &ast, clang::DeclContext *decl_ctx, + const DWARFDIE &decl_ctx_die, const DWARFDIE &die, + const char *type_name_cstr) { auto *tag_decl_ctx = clang::dyn_cast(decl_ctx); if (!tag_decl_ctx) return; // Non-tag context are always ready. @@ -270,6 +289,7 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast, // If this type was not imported from an external AST, there's nothing to do. CompilerType type = ast.GetTypeForDecl(tag_decl_ctx); + ClangASTImporter &ast_importer = GetClangASTImporter(); if (type && ast_importer.CanImport(type)) { auto qual_type = ClangUtil::GetQualType(type); if (ast_importer.RequireCompleteType(qual_type)) @@ -284,7 +304,8 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast, // 1. Found the the definition DIE and start its definition with // TypeSystemClang::StartTagDeclarationDefinition. // 2. Unable to find it, then need to forcefully complete it. - die.GetDWARF()->FindDefinitionDIE(decl_ctx_die); + bool is_forward_declaration = false; + FindDefinitionDIE(decl_ctx_die, is_forward_declaration); if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined()) return; // We don't have a type definition and/or the import failed. We must @@ -631,8 +652,8 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, DWARFDIE decl_ctx_die; clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, - decl_ctx_die, die, attrs.name.GetCString()); + PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die, + attrs.name.GetCString()); if (attrs.type.IsValid()) { // Try to parse a typedef from the (DWARF embedded in the) Clang @@ -1648,6 +1669,96 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { return qualified_name; } +bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die, + bool &is_forward_declaration) { + ParsedDWARFTypeAttributes attrs(die); + is_forward_declaration = IsForwardDeclaration( + die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU())); + if (!is_forward_declaration) + return true; + + const dw_tag_t tag = die.Tag(); + TypeSP type_sp; + SymbolFileDWARF *dwarf = die.GetDWARF(); + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration DIE, trying to find definition DIE", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + // We haven't parse definition die for this type, starting to search for it. + // After we found the definition die, the GetDeclarationDIEToDefinitionDIE() + // map will have the new mapping from this declaration die to definition die. + 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 && log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type " + "\"{3}\" is an " + "incomplete objc type, complete type is {4:x8}", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + } + } + + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); + 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); + } + if (type_sp && log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration, complete type is {4:x8}", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString(), type_sp->GetID()); + } + } + if (type_sp) + return true; + + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration, unable to find definition DIE for it", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + return false; +} + TypeSP DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, const DWARFDIE &die, @@ -1668,6 +1779,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, ConstString unique_typename(attrs.name); Declaration unique_decl(attrs.decl); uint64_t byte_size = attrs.byte_size.value_or(0); + attrs.is_forward_declaration = IsForwardDeclaration(die, attrs, cu_language); if (attrs.name) { if (Language::LanguageIsCPlusPlus(cu_language)) { @@ -1689,8 +1801,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, LinkDeclContextToDIE( GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); if (!attrs.is_forward_declaration) { - dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace( - unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef()); // If the parameter DIE is definition and the entry in the map is // declaration, then we need to update the entry to point to the // definition DIE. @@ -1703,10 +1813,18 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // it's used in ParseSubroutine to determine if we need to copy cxx // method types from a declaration DIE to this definition DIE. type_sp->SetID(die.GetID()); + clang_type = type_sp->GetForwardCompilerType(); if (attrs.class_language != eLanguageTypeObjC && attrs.class_language != eLanguageTypeObjC_plus_plus) - TypeSystemClang::StartTagDeclarationDefinition( - type_sp->GetForwardCompilerType()); + TypeSystemClang::StartTagDeclarationDefinition(clang_type); + + CompilerType compiler_type_no_qualifiers = + ClangUtil::RemoveFastQualifiers(clang_type); + auto result = dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( + compiler_type_no_qualifiers.GetOpaqueQualType(), + *die.GetDIERef()); + if (!result.second) + result.first->second = *die.GetDIERef(); } } return type_sp; @@ -1730,21 +1848,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, 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.is_forward_declaration) { // See if the type comes from a Clang module and if so, track down // that type. @@ -1759,8 +1862,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, - decl_ctx_die, die, attrs.name.GetCString()); + PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die, + attrs.name.GetCString()); if (attrs.accessibility == eAccessNone && decl_ctx) { // Check the decl context that contains this class/struct/union. If @@ -1809,9 +1912,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, attrs.exports_symbols); } - if (!attrs.is_forward_declaration) - dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(), - *die.GetDIERef()); // 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. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 8d4af203bb2871..b884d6869add84 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -108,6 +108,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { lldb_private::ConstString GetDIEClassTemplateParams( const lldb_private::plugin::dwarf::DWARFDIE &die) override; + bool FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, + bool &is_forward_declaration) override; + protected: /// Protected typedefs and members. /// @{ @@ -246,6 +249,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { lldb::ModuleSP GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die); + void PrepareContextToReceiveMembers( + lldb_private::TypeSystemClang &ast, + clang::DeclContext *decl_ctx, + const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die, + const lldb_private::plugin::dwarf::DWARFDIE &die, + const char *type_name_cstr); + static bool classof(const DWARFASTParser *Parser) { return Parser->GetKind() == Kind::DWARFASTParserClang; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index c7069550ccf702..d2f66b00c17941 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1631,126 +1631,40 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { return true; } - DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond())); - if (dwarf_die) { - // Once we start resolving this type, remove it from the forward - // declaration map in case anyone child members or other types require this - // type to get resolved. The type will get resolved when all of the calls - // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done. - // Need to get a new iterator because FindDefinitionDIE might add new - // entries into the map and invalidate previous iterator. - auto die_it = GetForwardDeclCompilerTypeToDIE().find( - compiler_type_no_qualifiers.GetOpaqueQualType()); - if (die_it != GetForwardDeclCompilerTypeToDIE().end()) { - GetForwardDeclCompilerTypeToDIE().erase(die_it); - } - - Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); + // Once we start resolving this type, remove it from the forward + // declaration map in case anyone child members or other types require this + // type to get resolved. + DWARFDIE dwarf_die = GetDIE(die_it->second); + GetForwardDeclCompilerTypeToDIE().erase(die_it); + // The DWARFASTParser might determine if this is a declaration or not with + // information other than DW_AT_declaration depending on the language. + bool is_forward_declaration = false; + bool found_def_die = false; + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) + found_def_die = + dwarf_ast->FindDefinitionDIE(dwarf_die, is_forward_declaration); + if (!found_def_die) + return false; - Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); - if (log) - GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, "{0:x8}: {1} '{2}' resolving forward declaration...", - dwarf_die.GetID(), dwarf_die.GetTagAsCString(), - type->GetName().AsCString()); - assert(compiler_type); - if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) - return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type); + die_it = GetForwardDeclCompilerTypeToDIE().find( + compiler_type_no_qualifiers.GetOpaqueQualType()); + if (die_it != GetForwardDeclCompilerTypeToDIE().end()) { + dwarf_die = GetDIE(die_it->getSecond()); + GetForwardDeclCompilerTypeToDIE().erase(die_it); } - return false; -} -DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { - auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE()); - if (def_die_it != GetDeclarationDIEToDefinitionDIE().end()) - return GetDIE(def_die_it->getSecond()); + Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); - ParsedDWARFTypeAttributes attrs(die); - const dw_tag_t tag = die.Tag(); - TypeSP type_sp; - Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration DIE, trying to find definition DIE", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString()); - } - // We haven't parse definition die for this type, starting to search for it. - // After we found the definition die, the GetDeclarationDIEToDefinitionDIE() - // map will have the new mapping from this declaration die to definition die. - 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 = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = 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 && log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type " - "\"{3}\" is an " - "incomplete objc type, complete type is {4:x8}", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - } - } - bool is_forward_declaration = - attrs.is_forward_declaration || - (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && - SymbolFileDWARF::GetLanguage(*die.GetCU()) == eLanguageTypeObjC); - if (is_forward_declaration) { - type_sp = FindDefinitionTypeForDWARFDeclContext(die); - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = 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); - } - if (type_sp && log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, complete type is {4:x8}", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - } - } - def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE()); - if (def_die_it != GetDeclarationDIEToDefinitionDIE().end()) - return GetDIE(def_die_it->getSecond()); - - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, unable to find definition DIE for it", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString()); - } - return DWARFDIE(); + Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); + if (log) + GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( + log, "{0:x8}: {1} '{2}' resolving forward declaration...", + dwarf_die.GetID(), dwarf_die.GetTagAsCString(), + type->GetName().AsCString()); + assert(compiler_type); + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) + return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type); + return true; } Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 86d5a3d4f6c46d..94aa810680c52c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -182,8 +182,6 @@ class SymbolFileDWARF : public SymbolFileCommon { void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; - DWARFDIE FindDefinitionDIE(const DWARFDIE &die); - void GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector &mangled_names) override; @@ -344,11 +342,6 @@ class SymbolFileDWARF : public SymbolFileCommon { return m_forward_decl_compiler_type_to_die; } - typedef llvm::DenseMap DIEToDIE; - virtual DIEToDIE &GetDeclarationDIEToDefinitionDIE() { - return m_die_to_def_die; - } - typedef llvm::DenseMap DIEToVariableSP; @@ -547,9 +540,6 @@ class SymbolFileDWARF : public SymbolFileCommon { // A map from CompilerType to the struct/class/union/enum DIE (might be a // declaration or a definition) that is used to construct it. CompilerTypeToDIE m_forward_decl_compiler_type_to_die; - // A map from a struct/class/union/enum DIE (might be a declaration or a - // definition) to its definition DIE. - DIEToDIE m_die_to_def_die; llvm::DenseMap> m_type_unit_support_files; std::vector m_lldb_cu_to_dwarf_unit; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index cb5ec4ae026b3d..85e1afd0d89761 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -110,11 +110,6 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { return GetBaseSymbolFile().GetDIEToVariable(); } -SymbolFileDWARF::DIEToDIE & -SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() { - return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE(); -} - SymbolFileDWARF::CompilerTypeToDIE & SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 3e8cfb885aaee9..1500540424b524 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -74,8 +74,6 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF { CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override; - DIEToDIE &GetDeclarationDIEToDefinitionDIE() override; - UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; lldb::TypeSP From 515c85d30fbacb523d51b024010056a61956e93b Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Fri, 3 May 2024 10:39:07 -0400 Subject: [PATCH 04/10] Address comments --- .../Plugins/SymbolFile/DWARF/DWARFASTParser.h | 6 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 68 +++--- .../SymbolFile/DWARF/DWARFASTParserClang.h | 203 ++++++++---------- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 12 +- .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 82 +++---- 5 files changed, 163 insertions(+), 208 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 14b9cba05d3215..e144cf0f9bd94e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -60,11 +60,7 @@ class DWARFASTParser { virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0; - // Return true if we found the definition DIE for it. is_forward_declaration - // is set to true if the parameter die is a declaration. - virtual bool - FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, - bool &is_forward_declaration) = 0; + virtual lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) = 0; static std::optional ParseChildArrayInfo(const DWARFDIE &parent_die, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 8a8c303e1a8b2d..0db2e7984d13e6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -271,9 +271,8 @@ static void ForcefullyCompleteType(CompilerType type) { /// avoids completing the type if it is not immediately necessary. It only /// ensures we _can_ complete the type later. void DWARFASTParserClang::PrepareContextToReceiveMembers( - TypeSystemClang &ast, clang::DeclContext *decl_ctx, - const DWARFDIE &decl_ctx_die, const DWARFDIE &die, - const char *type_name_cstr) { + clang::DeclContext *decl_ctx, const DWARFDIE &decl_ctx_die, + const DWARFDIE &die, const char *type_name_cstr) { auto *tag_decl_ctx = clang::dyn_cast(decl_ctx); if (!tag_decl_ctx) return; // Non-tag context are always ready. @@ -288,7 +287,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers( // gmodules case), we can complete the type by doing a full import. // If this type was not imported from an external AST, there's nothing to do. - CompilerType type = ast.GetTypeForDecl(tag_decl_ctx); + CompilerType type = m_ast.GetTypeForDecl(tag_decl_ctx); ClangASTImporter &ast_importer = GetClangASTImporter(); if (type && ast_importer.CanImport(type)) { auto qual_type = ClangUtil::GetQualType(type); @@ -304,8 +303,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers( // 1. Found the the definition DIE and start its definition with // TypeSystemClang::StartTagDeclarationDefinition. // 2. Unable to find it, then need to forcefully complete it. - bool is_forward_declaration = false; - FindDefinitionDIE(decl_ctx_die, is_forward_declaration); + FindDefinitionTypeForDIE(decl_ctx_die); if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined()) return; // We don't have a type definition and/or the import failed. We must @@ -652,7 +650,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, DWARFDIE decl_ctx_die; clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die, + PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die, attrs.name.GetCString()); if (attrs.type.IsValid()) { @@ -1669,17 +1667,17 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { return qualified_name; } -bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die, - bool &is_forward_declaration) { +lldb_private::Type * +DWARFASTParserClang::FindDefinitionTypeForDIE(const DWARFDIE &die) { + SymbolFileDWARF *dwarf = die.GetDWARF(); ParsedDWARFTypeAttributes attrs(die); - is_forward_declaration = IsForwardDeclaration( + bool is_forward_declaration = IsForwardDeclaration( die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU())); if (!is_forward_declaration) - return true; + return dwarf->GetDIEToType()[die.GetDIE()]; const dw_tag_t tag = die.Tag(); TypeSP type_sp; - SymbolFileDWARF *dwarf = die.GetDWARF(); Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( @@ -1745,10 +1743,8 @@ bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die, attrs.name.GetCString(), type_sp->GetID()); } } - if (type_sp) - return true; - if (log) { + if (!type_sp && log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " @@ -1756,7 +1752,7 @@ bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die, static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), attrs.name.GetCString()); } - return false; + return type_sp.get(); } TypeSP @@ -1801,9 +1797,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, LinkDeclContextToDIE( GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); if (!attrs.is_forward_declaration) { - // If the parameter DIE is definition and the entry in the map is - // declaration, then we need to update the entry to point to the - // definition DIE. + // If the DIE being parsed in this function is a definition and the + // entry in the map is a declaration, then we need to update the entry + // to point to the definition DIE. if (unique_ast_entry_up->m_is_forward_declaration) { unique_ast_entry_up->m_die = die; unique_ast_entry_up->m_byte_size = byte_size; @@ -1862,7 +1858,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die, + PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die, attrs.name.GetCString()); if (attrs.accessibility == eAccessNone && decl_ctx) { @@ -1970,25 +1966,25 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, GetClangASTImporter().SetRecordLayout(record_decl, layout); } } - } - // 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.. + } else { + // 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) - TypeSystemClang::StartTagDeclarationDefinition(clang_type); + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + TypeSystemClang::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. + // If this is a declaration DIE, 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->GetForwardDeclCompilerTypeToDIE().count( ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) && "Type already in the forward declaration map!"); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index b884d6869add84..853b8ccc30369f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -42,40 +42,40 @@ struct ParsedDWARFTypeAttributes; class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { public: + typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE; + DWARFASTParserClang(lldb_private::TypeSystemClang &ast); ~DWARFASTParserClang() override; // DWARFASTParser interface. - lldb::TypeSP - ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const lldb_private::plugin::dwarf::DWARFDIE &die, - bool *type_is_new_ptr) override; + lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, + bool *type_is_new_ptr) override; - lldb_private::ConstString ConstructDemangledNameFromDWARF( - const lldb_private::plugin::dwarf::DWARFDIE &die) override; + lldb_private::ConstString + ConstructDemangledNameFromDWARF(const DWARFDIE &die) override; lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, - const lldb_private::plugin::dwarf::DWARFDIE &die, + const DWARFDIE &die, const lldb_private::AddressRange &func_range) override; bool - CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::Type *type, + CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &compiler_type) override; - lldb_private::CompilerDecl GetDeclForUIDFromDWARF( - const lldb_private::plugin::dwarf::DWARFDIE &die) override; + lldb_private::CompilerDecl + GetDeclForUIDFromDWARF(const DWARFDIE &die) override; void EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) override; - lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF( - const lldb_private::plugin::dwarf::DWARFDIE &die) override; + lldb_private::CompilerDeclContext + GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; - lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF( - const lldb_private::plugin::dwarf::DWARFDIE &die) override; + lldb_private::CompilerDeclContext + GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override; lldb_private::ClangASTImporter &GetClangASTImporter(); @@ -105,11 +105,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// \return A string, including surrounding '<>', of the template parameters. /// If the DIE's name already has '<>', returns an empty ConstString because /// it's assumed that the caller is using the DIE name anyway. - lldb_private::ConstString GetDIEClassTemplateParams( - const lldb_private::plugin::dwarf::DWARFDIE &die) override; + lldb_private::ConstString + GetDIEClassTemplateParams(const DWARFDIE &die) override; - bool FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, - bool &is_forward_declaration) override; + // Searching for definition DIE for the given DIE and return the type + // associated with the definition DIE, or nullptr if definition DIE is not + // found. + lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) override; protected: /// Protected typedefs and members. @@ -121,8 +123,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; - typedef std::multimap + typedef std::multimap DeclContextToDIEMap; typedef llvm::DenseMap< const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, @@ -140,14 +141,11 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { std::unique_ptr m_clang_ast_importer_up; /// @} - clang::DeclContext * - GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); - clang::BlockDecl * - ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); - clang::NamespaceDecl * - ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die); /// Returns the namespace decl that a DW_TAG_imported_declaration imports. /// @@ -158,103 +156,86 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// 'die' imports. If the imported entity is not a namespace /// or another import declaration, returns nullptr. If an error /// occurs, returns nullptr. - clang::NamespaceDecl *ResolveImportedDeclarationDIE( - const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die); - bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, + bool ParseTemplateDIE(const DWARFDIE &die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); bool ParseTemplateParameterInfos( - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + const DWARFDIE &parent_die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); - std::string - GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die); + std::string GetCPlusPlusQualifiedName(const DWARFDIE &die); bool ParseChildMembers( - const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::CompilerType &class_compiler_type, + const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, std::vector> &base_classes, - std::vector &member_function_dies, - std::vector &contained_type_dies, + std::vector &member_function_dies, + std::vector &contained_type_dies, DelayedPropertyList &delayed_properties, const lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t ParseChildParameters(clang::DeclContext *containing_decl_ctx, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, - bool skip_artificial, bool &is_static, bool &is_variadic, + const DWARFDIE &parent_die, bool skip_artificial, + bool &is_static, bool &is_variadic, bool &has_template_params, std::vector &function_args, std::vector &function_param_decls, unsigned &type_quals); - size_t ParseChildEnumerators( - lldb_private::CompilerType &compiler_type, bool is_signed, - uint32_t enumerator_byte_size, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die); + size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, + bool is_signed, uint32_t enumerator_byte_size, + const DWARFDIE &parent_die); /// Parse a structure, class, or union type DIE. - lldb::TypeSP - ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, - const lldb_private::plugin::dwarf::DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); - clang::Decl * - GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); - clang::DeclContext * - GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die); - clang::DeclContext *GetClangDeclContextContainingDIE( - const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die); - lldb_private::OptionalClangModuleID - GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die, + DWARFDIE *decl_ctx_die); + lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die); - bool CopyUniqueClassMethodTypes( - const lldb_private::plugin::dwarf::DWARFDIE &src_class_die, - const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die, - lldb_private::Type *class_type, - std::vector &failures); + bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, + const DWARFDIE &dst_class_die, + lldb_private::Type *class_type, + std::vector &failures); - clang::DeclContext *GetCachedClangDeclContextForDIE( - const lldb_private::plugin::dwarf::DWARFDIE &die); + clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die); - void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, - const lldb_private::plugin::dwarf::DWARFDIE &die); + void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die); - void LinkDeclToDIE(clang::Decl *decl, - const lldb_private::plugin::dwarf::DWARFDIE &die); + 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 lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP + UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, lldb::TypeSP type_sp); /// Follow Clang Module Skeleton CU references to find a type definition. - lldb::TypeSP - ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, - const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::Log *log); + lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, + 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 lldb_private::plugin::dwarf::DWARFDIE &die); + lldb::ModuleSP GetModuleForType(const DWARFDIE &die); - void PrepareContextToReceiveMembers( - lldb_private::TypeSystemClang &ast, - clang::DeclContext *decl_ctx, - const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die, - const lldb_private::plugin::dwarf::DWARFDIE &die, - const char *type_name_cstr); + void PrepareContextToReceiveMembers(clang::DeclContext *decl_ctx, + const DWARFDIE &decl_ctx_die, + const DWARFDIE &die, + const char *type_name_cstr); static bool classof(const DWARFASTParser *Parser) { return Parser->GetKind() == Kind::DWARFASTParserClang; @@ -284,10 +265,8 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// Parsed form of all attributes that are relevant for parsing type members. struct MemberAttributes { - explicit MemberAttributes( - const lldb_private::plugin::dwarf::DWARFDIE &die, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, - lldb::ModuleSP module_sp); + explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die, + lldb::ModuleSP module_sp); const char *name = nullptr; /// Indicates how many bits into the word (according to the host endianness) /// the low-order bit of the field starts. Can be negative. @@ -334,15 +313,12 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// created property. /// \param delayed_properties The list of delayed properties that the result /// will be appended to. - void - ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, - const lldb_private::CompilerType &class_clang_type, - DelayedPropertyList &delayed_properties); + void ParseObjCProperty(const DWARFDIE &die, const DWARFDIE &parent_die, + const lldb_private::CompilerType &class_clang_type, + DelayedPropertyList &delayed_properties); void - ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info, @@ -360,31 +336,25 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// \param[in] class_clang_type The parent RecordType of the static /// member this function will create. void CreateStaticMemberVariable( - const lldb_private::plugin::dwarf::DWARFDIE &die, - const MemberAttributes &attrs, + const DWARFDIE &die, const MemberAttributes &attrs, const lldb_private::CompilerType &class_clang_type); - bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::Type *type, + bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &clang_type); - bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die, - lldb_private::Type *type, + bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &clang_type); - lldb::TypeSP - ParseTypeModifier(const lldb_private::SymbolContext &sc, - const lldb_private::plugin::dwarf::DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc, - const lldb_private::plugin::dwarf::DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die, + const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseSubroutine(const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb::TypeSP ParseArrayType(const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP - ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die, - const ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs); /// Parses a DW_TAG_inheritance DIE into a base/super class. /// @@ -401,8 +371,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// \param layout_info The layout information that will be updated for C++ /// base classes with the base offset. void ParseInheritance( - const lldb_private::plugin::dwarf::DWARFDIE &die, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType class_clang_type, const lldb::AccessType default_accessibility, const lldb::ModuleSP &module_sp, @@ -419,8 +388,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// \param layout_info The layout information that will be updated for // base classes with the base offset void - ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die, - const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + ParseRustVariantPart(DWARFDIE &die, const DWARFDIE &parent_die, lldb_private::CompilerType &class_clang_type, const lldb::AccessType default_accesibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); @@ -430,8 +398,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { /// 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 lldb_private::plugin::dwarf::DWARFDIE &die); + typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE; + + explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); lldb::AccessType accessibility = lldb::eAccessNone; bool is_artificial = false; @@ -448,7 +417,7 @@ struct ParsedDWARFTypeAttributes { const char *mangled_name = nullptr; lldb_private::ConstString name; lldb_private::Declaration decl; - lldb_private::plugin::dwarf::DWARFDIE object_pointer; + DWARFDIE object_pointer; lldb_private::plugin::dwarf::DWARFFormValue abstract_origin; lldb_private::plugin::dwarf::DWARFFormValue containing_type; lldb_private::plugin::dwarf::DWARFFormValue signature; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index d2f66b00c17941..10b9ae7d5ab4e1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1636,14 +1636,10 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { // type to get resolved. DWARFDIE dwarf_die = GetDIE(die_it->second); GetForwardDeclCompilerTypeToDIE().erase(die_it); - // The DWARFASTParser might determine if this is a declaration or not with - // information other than DW_AT_declaration depending on the language. - bool is_forward_declaration = false; - bool found_def_die = false; + Type *type = nullptr; if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) - found_def_die = - dwarf_ast->FindDefinitionDIE(dwarf_die, is_forward_declaration); - if (!found_def_die) + type = dwarf_ast->FindDefinitionTypeForDIE(dwarf_die); + if (!type) return false; die_it = GetForwardDeclCompilerTypeToDIE().find( @@ -1653,8 +1649,6 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { GetForwardDeclCompilerTypeToDIE().erase(die_it); } - Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); - Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); if (log) GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index cc23bb86f6805a..8b7b413fcf66e0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -30,52 +30,52 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, : (udt.m_byte_size < 0 || byte_size < 0 || udt.m_byte_size == byte_size) && udt.m_declaration == decl; - if (matching_size_declaration) { - // The type has the same name, and was defined on the same file and - // line. Now verify all of the parent DIEs match. - DWARFDIE parent_arg_die = die.GetParent(); - DWARFDIE parent_pos_die = udt.m_die.GetParent(); - bool match = true; - bool done = false; - while (!done && match && parent_arg_die && parent_pos_die) { - const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); - const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); - if (parent_arg_tag == parent_pos_tag) { - switch (parent_arg_tag) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_namespace: { - const char *parent_arg_die_name = parent_arg_die.GetName(); - if (parent_arg_die_name == - nullptr) // Anonymous (i.e. no-name) struct - { + if (!matching_size_declaration) + continue; + // The type has the same name, and was defined on the same file and + // line. Now verify all of the parent DIEs match. + DWARFDIE parent_arg_die = die.GetParent(); + DWARFDIE parent_pos_die = udt.m_die.GetParent(); + bool match = true; + bool done = false; + while (!done && match && parent_arg_die && parent_pos_die) { + const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); + const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); + if (parent_arg_tag == parent_pos_tag) { + switch (parent_arg_tag) { + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_namespace: { + const char *parent_arg_die_name = parent_arg_die.GetName(); + if (parent_arg_die_name == + nullptr) // Anonymous (i.e. no-name) struct + { + match = false; + } else { + const char *parent_pos_die_name = parent_pos_die.GetName(); + if (parent_pos_die_name == nullptr || + ((parent_arg_die_name != parent_pos_die_name) && + strcmp(parent_arg_die_name, parent_pos_die_name))) match = false; - } else { - const char *parent_pos_die_name = parent_pos_die.GetName(); - if (parent_pos_die_name == nullptr || - ((parent_arg_die_name != parent_pos_die_name) && - strcmp(parent_arg_die_name, parent_pos_die_name))) - match = false; - } - } break; - - case DW_TAG_compile_unit: - case DW_TAG_partial_unit: - done = true; - break; - default: - break; } + } break; + + case DW_TAG_compile_unit: + case DW_TAG_partial_unit: + done = true; + break; + default: + break; } - parent_arg_die = parent_arg_die.GetParent(); - parent_pos_die = parent_pos_die.GetParent(); } + parent_arg_die = parent_arg_die.GetParent(); + parent_pos_die = parent_pos_die.GetParent(); + } - if (match) { - entry = udt; - return true; - } + if (match) { + entry = udt; + return true; } } } From 40b87f037911bf738d0e3cb670485dac33d5b079 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Fri, 3 May 2024 16:26:19 -0400 Subject: [PATCH 05/10] address comments --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 28 +++++++++---------- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 0db2e7984d13e6..0f8beaa8363ed9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -158,21 +158,21 @@ static bool IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs, LanguageType cu_language) { - 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. + if (attrs.is_forward_declaration) return true; - } - return attrs.is_forward_declaration; + + // 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. + return attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC; } TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 10b9ae7d5ab4e1..8b3d8b8c8903ab 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1632,7 +1632,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { } // Once we start resolving this type, remove it from the forward - // declaration map in case anyone child members or other types require this + // declaration map in case anyone's child members or other types require this // type to get resolved. DWARFDIE dwarf_die = GetDIE(die_it->second); GetForwardDeclCompilerTypeToDIE().erase(die_it); From 0481675dcda0da45b5a66a5208bbc80f61d04b79 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Mon, 6 May 2024 11:10:20 -0400 Subject: [PATCH 06/10] add a test --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 9 ++--- .../delayed-definition-die-searching.test | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 1908a1bfffa897..7cd1626f553c30 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -154,10 +154,9 @@ static bool TagIsRecordType(dw_tag_t tag) { } } -static bool -IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die, - const ParsedDWARFTypeAttributes &attrs, - LanguageType cu_language) { +static bool IsForwardDeclaration(const DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs, + LanguageType cu_language) { if (attrs.is_forward_declaration) return true; @@ -172,7 +171,7 @@ IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die, // Note that there is no DW_AT_declaration and there are no children, // and the byte size is zero. return attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC; + !die.HasChildren() && cu_language == eLanguageTypeObjC; } TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test new file mode 100644 index 00000000000000..3f5293d04ccce0 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test @@ -0,0 +1,40 @@ +# Test definition DIE searching is delayed until complete type is required. + +# RUN: split-file %s %t +# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -g -gsimple-template-names -o %t.out +# RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s + +# CHECK: (lldb) p v1 +# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' +# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' +# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' +# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... +# CHECK-NEXT: (t2 >) {} +# CHECK-NEXT: (lldb) p v2 +# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' +# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' +# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration... +# CHECK-NEXT: (t1) {} + +#--- lldb.cmd +log enable dwarf comp +p v1 +p v2 + +#--- template.h +template +struct t1 { +}; +template +struct t2 { +}; + +#--- main.cpp +#include "template.h" +t2> v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it. +int main() { +} + +#--- t1_def.cpp +#include "template.h" +t1 v2; // this CU contains definition DIE for t1. From 4f2fbfbad4b8560990266be36b394e65b3373b91 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 7 May 2024 11:21:19 -0400 Subject: [PATCH 07/10] Use CHECK instead of CHECK-NEXT --- .../delayed-definition-die-searching.test | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test index 3f5293d04ccce0..6fe6819f66e3e8 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test +++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test @@ -5,16 +5,16 @@ # RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s # CHECK: (lldb) p v1 -# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' -# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' -# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... -# CHECK-NEXT: (t2 >) {} -# CHECK-NEXT: (lldb) p v2 -# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' -# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration... -# CHECK-NEXT: (t1) {} +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' +# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... +# CHECK: (t2 >) {} +# CHECK: (lldb) p v2 +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' +# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration... +# CHECK: (t1) {} #--- lldb.cmd log enable dwarf comp From c7edf1566a68a0b361f608d84df990f576042007 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 7 May 2024 16:58:00 -0400 Subject: [PATCH 08/10] address comments --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 3 +-- .../source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp | 5 ++--- lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h | 7 ------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index dcb2f62fc4dfda..5a07fd30fbf70d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1650,8 +1650,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { GetForwardDeclCompilerTypeToDIE().erase(die_it); } - Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); - if (log) + if (Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion)) GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...", dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()), diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 8b7b413fcf66e0..a156c13314bbb4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -48,9 +48,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_union_type: case DW_TAG_namespace: { const char *parent_arg_die_name = parent_arg_die.GetName(); - if (parent_arg_die_name == - nullptr) // Anonymous (i.e. no-name) struct - { + if (parent_arg_die_name == nullptr) { + // Anonymous (i.e. no-name) struct match = false; } else { const char *parent_pos_die_name = parent_pos_die.GetName(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index 94619953d07ac5..f2ff42ae83d50d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -23,13 +23,6 @@ class UniqueDWARFASTType { // Constructors and Destructors UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {} - UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die, - const Declaration &decl, int32_t byte_size, - bool is_forward_declaration) - : m_type_sp(type_sp), m_die(die), m_declaration(decl), - m_byte_size(byte_size), - m_is_forward_declaration(is_forward_declaration) {} - UniqueDWARFASTType(const UniqueDWARFASTType &rhs) : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die), m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size), From 3414ce25cbee1fd843c432366e79a70d126a06f5 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 7 May 2024 17:49:32 -0400 Subject: [PATCH 09/10] Update test: remove -gsimple-template-names --- .../delayed-definition-die-searching.test | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test index 6fe6819f66e3e8..a2b36dadedd214 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test +++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test @@ -1,40 +1,34 @@ # Test definition DIE searching is delayed until complete type is required. # RUN: split-file %s %t -# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -g -gsimple-template-names -o %t.out +# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -g -o %t.out # RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s -# CHECK: (lldb) p v1 -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' +# CHECK: (lldb) p v1 +# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' # CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' -# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... -# CHECK: (t2 >) {} +# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... +# CHECK: (t2) {} # CHECK: (lldb) p v2 # CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int' # CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration... -# CHECK: (t1) {} #--- lldb.cmd log enable dwarf comp p v1 p v2 -#--- template.h -template -struct t1 { -}; +#--- main.cpp template struct t2 { }; - -#--- main.cpp -#include "template.h" -t2> v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it. +struct t1; +t2 v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it. int main() { } #--- t1_def.cpp -#include "template.h" -t1 v2; // this CU contains definition DIE for t1. +struct t1 { // this CU contains definition DIE for t1. + int x; +}; +t1 v2; \ No newline at end of file From a8d45fb8d560d889d530479d42832fbce8083ad2 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Thu, 9 May 2024 17:16:54 -0400 Subject: [PATCH 10/10] Fix an oversight that I was updating the UniqueDWARFASTType object which is copied from UniqueDWARFASTTypeList::Find but I was meant to updating the original obejct. Update UniqueDWARFASTTypeList::Find and UniqueDWARFASTTypeMap::Find to return a pointer of UniqueDWARFASTTypeMap pointting to the object so that we update its fields correctly. --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 32 +++++++++---------- .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 15 ++++----- .../SymbolFile/DWARF/UniqueDWARFASTType.h | 30 ++++++----------- 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 7cd1626f553c30..e0b1b430b266f3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1767,12 +1767,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU()); Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::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(); - ConstString unique_typename(attrs.name); Declaration unique_decl(attrs.decl); uint64_t byte_size = attrs.byte_size.value_or(0); @@ -1789,23 +1783,24 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, unique_decl.Clear(); } - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, byte_size, - attrs.is_forward_declaration, *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; + if (UniqueDWARFASTType *unique_ast_entry_type = + dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, byte_size, + attrs.is_forward_declaration)) { + type_sp = unique_ast_entry_type->m_type_sp; if (type_sp) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); LinkDeclContextToDIE( - GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); + GetCachedClangDeclContextForDIE(unique_ast_entry_type->m_die), die); if (!attrs.is_forward_declaration) { // If the DIE being parsed in this function is a definition and the // entry in the map is a declaration, then we need to update the entry // to point to the definition DIE. - if (unique_ast_entry_up->m_is_forward_declaration) { - unique_ast_entry_up->m_die = die; - unique_ast_entry_up->m_byte_size = byte_size; - unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_is_forward_declaration = false; + if (unique_ast_entry_type->m_is_forward_declaration) { + unique_ast_entry_type->m_die = die; + unique_ast_entry_type->m_byte_size = byte_size; + unique_ast_entry_type->m_declaration = unique_decl; + unique_ast_entry_type->m_is_forward_declaration = false; // Need to update Type ID to refer to the definition DIE. because // it's used in ParseSubroutine to determine if we need to copy cxx // method types from a declaration DIE to this definition DIE. @@ -1919,6 +1914,11 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, Type::ResolveState::Forward, TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); + // 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(); // 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 diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index a156c13314bbb4..4762356034cab7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -13,12 +13,10 @@ using namespace lldb_private::dwarf; using namespace lldb_private::plugin::dwarf; -bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, - const lldb_private::Declaration &decl, - const int32_t byte_size, - bool is_forward_declaration, - UniqueDWARFASTType &entry) const { - for (const UniqueDWARFASTType &udt : m_collection) { +UniqueDWARFASTType *UniqueDWARFASTTypeList::Find( + const DWARFDIE &die, const lldb_private::Declaration &decl, + const int32_t byte_size, bool is_forward_declaration) { + for (UniqueDWARFASTType &udt : m_collection) { // Make sure the tags match if (udt.m_die.Tag() == die.Tag()) { // If they are not both definition DIEs or both declaration DIEs, then @@ -73,10 +71,9 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, } if (match) { - entry = udt; - return true; + return &udt; } } } - return false; + return nullptr; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index f2ff42ae83d50d..29e5c02dcbe176 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -30,17 +30,6 @@ class UniqueDWARFASTType { ~UniqueDWARFASTType() = default; - UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) { - if (this != &rhs) { - m_type_sp = rhs.m_type_sp; - m_die = rhs.m_die; - m_declaration = rhs.m_declaration; - m_byte_size = rhs.m_byte_size; - m_is_forward_declaration = rhs.m_is_forward_declaration; - } - return *this; - } - lldb::TypeSP m_type_sp; DWARFDIE m_die; Declaration m_declaration; @@ -61,9 +50,9 @@ class UniqueDWARFASTTypeList { m_collection.push_back(entry); } - bool Find(const DWARFDIE &die, const Declaration &decl, - const int32_t byte_size, bool is_forward_declaration, - UniqueDWARFASTType &entry) const; + UniqueDWARFASTType *Find(const DWARFDIE &die, const Declaration &decl, + const int32_t byte_size, + bool is_forward_declaration); protected: typedef std::vector collection; @@ -80,16 +69,15 @@ class UniqueDWARFASTTypeMap { m_collection[name.GetCString()].Append(entry); } - bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl, - const int32_t byte_size, bool is_forward_declaration, - UniqueDWARFASTType &entry) const { + UniqueDWARFASTType *Find(ConstString name, const DWARFDIE &die, + const Declaration &decl, const int32_t byte_size, + bool is_forward_declaration) { const char *unique_name_cstr = name.GetCString(); - collection::const_iterator pos = m_collection.find(unique_name_cstr); + collection::iterator pos = m_collection.find(unique_name_cstr); if (pos != m_collection.end()) { - return pos->second.Find(die, decl, byte_size, is_forward_declaration, - entry); + return pos->second.Find(die, decl, byte_size, is_forward_declaration); } - return false; + return nullptr; } protected: