diff options
| author | Koakuma <koachan@protonmail.com> | 2024-07-08 19:19:54 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2024-07-08 19:19:54 +0700 |
| commit | 5c4fdc2fd5898ebd9e89999a4f4b8aa289ca637f (patch) | |
| tree | f3b92a07f3dfc6e70f36d1000605f36a3c15af46 /lldb/source/Plugins/SymbolFile | |
| parent | dbda8e2f2cd8764e0badd983915d62a2c3377f4d (diff) | |
| parent | e9b8cd0c806db00f0981fb36717077c941426302 (diff) | |
[𝘀𝗽𝗿] changes introduced through rebaseusers/koachan/spr/main.sparcias-enable-parseforallfeatures-in-matchoperandparserimpl
Created using spr 1.3.5
[skip ci]
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
23 files changed, 868 insertions, 801 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 66db396279e0..abaeb2502cbb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -58,7 +58,7 @@ public: virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( CompilerDeclContext decl_context) = 0; - virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0; + virtual std::string GetDIEClassTemplateParams(const DWARFDIE &die) = 0; static std::optional<SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 579a538af363..f36e2af9589b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -23,6 +23,7 @@ #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/Module.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Value.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/CompileUnit.h" @@ -38,10 +39,12 @@ #include "lldb/Utility/StreamString.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Type.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Demangle/Demangle.h" #include <map> @@ -222,7 +225,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward, TypePayloadClang(GetOwningClangModule(die))); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type); if (tag_decl) { LinkDeclContextToDIE(tag_decl, die); @@ -457,90 +459,78 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, DW_TAG_value_to_name(die.Tag()), die.Tag(), die.GetName()); } - Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); - if (type_ptr == DIE_IS_BEING_PARSED) - return nullptr; - if (type_ptr) - return type_ptr->shared_from_this(); // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + if (auto [it, inserted] = + dwarf->GetDIEToType().try_emplace(die.GetDIE(), DIE_IS_BEING_PARSED); + !inserted) { + if (it->getSecond() == nullptr || it->getSecond() == DIE_IS_BEING_PARSED) + return nullptr; + return it->getSecond()->shared_from_this(); + } ParsedDWARFTypeAttributes attrs(die); + TypeSP type_sp; if (DWARFDIE signature_die = attrs.signature.Reference()) { - if (TypeSP type_sp = - ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + type_sp = ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr); + if (type_sp) { if (clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(signature_die)) LinkDeclContextToDIE(decl_ctx, die); - return type_sp; } - return nullptr; - } - - if (type_is_new_ptr) - *type_is_new_ptr = true; - - const dw_tag_t tag = die.Tag(); - - TypeSP type_sp; - - switch (tag) { - case DW_TAG_typedef: - case DW_TAG_base_type: - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - case DW_TAG_const_type: - case DW_TAG_restrict_type: - case DW_TAG_volatile_type: - case DW_TAG_LLVM_ptrauth_type: - case DW_TAG_atomic_type: - case DW_TAG_unspecified_type: { - type_sp = ParseTypeModifier(sc, die, attrs); - break; - } - - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: { - type_sp = ParseStructureLikeDIE(sc, die, attrs); - break; - } + } else { + if (type_is_new_ptr) + *type_is_new_ptr = true; - case DW_TAG_enumeration_type: { - type_sp = ParseEnum(sc, die, attrs); - break; - } + const dw_tag_t tag = die.Tag(); - case DW_TAG_inlined_subroutine: - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: { - type_sp = ParseSubroutine(die, attrs); - break; - } - case DW_TAG_array_type: { - type_sp = ParseArrayType(die, attrs); - break; - } - case DW_TAG_ptr_to_member_type: { - type_sp = ParsePointerToMemberType(die, attrs); - break; + switch (tag) { + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_const_type: + case DW_TAG_restrict_type: + case DW_TAG_volatile_type: + case DW_TAG_LLVM_ptrauth_type: + case DW_TAG_atomic_type: + case DW_TAG_unspecified_type: + type_sp = ParseTypeModifier(sc, die, attrs); + break; + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + type_sp = ParseStructureLikeDIE(sc, die, attrs); + break; + case DW_TAG_enumeration_type: + type_sp = ParseEnum(sc, die, attrs); + break; + case DW_TAG_inlined_subroutine: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + type_sp = ParseSubroutine(die, attrs); + break; + case DW_TAG_array_type: + type_sp = ParseArrayType(die, attrs); + break; + case DW_TAG_ptr_to_member_type: + type_sp = ParsePointerToMemberType(die, attrs); + break; + default: + dwarf->GetObjectFile()->GetModule()->ReportError( + "[{0:x16}]: unhandled type tag {1:x4} ({2}), " + "please file a bug and " + "attach the file at the start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } + UpdateSymbolContextScopeForType(sc, die, type_sp); } - default: - dwarf->GetObjectFile()->GetModule()->ReportError( - "[{0:x16}]: unhandled type tag {1:x4} ({2}), " - "please file a bug and " - "attach the file at the start of this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - break; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); } - - // TODO: We should consider making the switch above exhaustive to simplify - // control flow in ParseTypeFromDWARF. Then, we could simply replace this - // return statement with a call to llvm_unreachable. - return UpdateSymbolContextScopeForType(sc, die, type_sp); + return type_sp; } static std::optional<uint32_t> @@ -829,78 +819,68 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, } } - type_sp = dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr, - attrs.type.Reference().GetID(), encoding_data_type, - &attrs.decl, clang_type, resolve_state, payload); - - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; + return dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr, + attrs.type.Reference().GetID(), encoding_data_type, + &attrs.decl, clang_type, resolve_state, payload); } -ConstString +std::string DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) { if (llvm::StringRef(die.GetName()).contains("<")) - return ConstString(); + return {}; TypeSystemClang::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - return ConstString(m_ast.PrintTemplateParams(template_param_infos)); - } - return ConstString(); + if (ParseTemplateParameterInfos(die, template_param_infos)) + return m_ast.PrintTemplateParams(template_param_infos); + + return {}; } TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, - const DWARFDIE &die, + const DWARFDIE &decl_die, ParsedDWARFTypeAttributes &attrs) { Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); - SymbolFileDWARF *dwarf = die.GetDWARF(); - const dw_tag_t tag = die.Tag(); - TypeSP type_sp; + SymbolFileDWARF *dwarf = decl_die.GetDWARF(); + const dw_tag_t tag = decl_die.Tag(); + DWARFDIE def_die; if (attrs.is_forward_declaration) { - type_sp = ParseTypeFromClangModule(sc, die, log); - if (type_sp) + if (TypeSP type_sp = ParseTypeFromClangModule(sc, decl_die, log)) return type_sp; - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); + def_die = dwarf->FindDefinitionDIE(decl_die); - if (!type_sp) { + if (!def_die) { 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); + def_die = debug_map_symfile->FindDefinitionDIE(decl_die); } } - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}}: {2} ({3}) type \"{4}\" is a " - "forward declaration, complete type is {5:x8}", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), 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; + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}}: {2} ({3}) type \"{4}\" is a " + "forward declaration, complete DIE is {5}", + static_cast<void *>(this), decl_die.GetID(), DW_TAG_value_to_name(tag), + tag, attrs.name.GetCString(), + def_die ? llvm::utohexstr(def_die.GetID()) : "not found"); } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + if (def_die) { + attrs = ParsedDWARFTypeAttributes(def_die); + } else { + // No definition found. Proceed with the declaration die. We can use it to + // create a forward-declared type. + def_die = decl_die; + } CompilerType enumerator_clang_type; if (attrs.type.IsValid()) { - Type *enumerator_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); + Type *enumerator_type = + dwarf->ResolveTypeUID(attrs.type.Reference(), true); if (enumerator_type) enumerator_clang_type = enumerator_type->GetFullCompilerType(); } @@ -915,24 +895,31 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, } CompilerType clang_type = m_ast.CreateEnumerationType( - attrs.name.GetStringRef(), GetClangDeclContextContainingDIE(die, nullptr), - GetOwningClangModule(die), attrs.decl, enumerator_clang_type, + attrs.name.GetStringRef(), GetClangDeclContextContainingDIE(def_die, nullptr), + GetOwningClangModule(def_die), attrs.decl, enumerator_clang_type, attrs.is_scoped_enum); - - LinkDeclContextToDIE(TypeSystemClang::GetDeclContextForType(clang_type), die); - - type_sp = - dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr, + TypeSP type_sp = + dwarf->MakeType(def_die.GetID(), attrs.name, attrs.byte_size, nullptr, attrs.type.Reference().GetID(), Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward, - TypePayloadClang(GetOwningClangModule(die))); + TypePayloadClang(GetOwningClangModule(def_die))); + + clang::DeclContext *type_decl_ctx = + TypeSystemClang::GetDeclContextForType(clang_type); + LinkDeclContextToDIE(type_decl_ctx, decl_die); + if (decl_die != def_die) { + LinkDeclContextToDIE(type_decl_ctx, def_die); + dwarf->GetDIEToType()[def_die.GetDIE()] = type_sp.get(); + // Declaration DIE is inserted into the type map in ParseTypeFromDWARF + } + if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) { - if (die.HasChildren()) { + if (def_die.HasChildren()) { bool is_signed = false; enumerator_clang_type.IsIntegerType(is_signed); ParseChildEnumerators(clang_type, is_signed, - type_sp->GetByteSize(nullptr).value_or(0), die); + type_sp->GetByteSize(nullptr).value_or(0), def_die); } TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); } else { @@ -940,7 +927,7 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, "DWARF DIE at {0:x16} named \"{1}\" was not able to start its " "definition.\nPlease file a bug and attach the file at the " "start of this error message", - die.GetOffset(), attrs.name.GetCString()); + def_die.GetOffset(), attrs.name.GetCString()); } return type_sp; } @@ -975,6 +962,216 @@ ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) { return clang::CC_C; } +bool DWARFASTParserClang::ParseObjCMethod( + const ObjCLanguage::MethodName &objc_method, const DWARFDIE &die, + CompilerType clang_type, const ParsedDWARFTypeAttributes &attrs, + bool is_variadic) { + SymbolFileDWARF *dwarf = die.GetDWARF(); + assert(dwarf); + + const auto tag = die.Tag(); + ConstString class_name(objc_method.GetClassName()); + if (!class_name) + return false; + + TypeSP complete_objc_class_type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), class_name, + false); + + if (!complete_objc_class_type_sp) + return false; + + CompilerType type_clang_forward_type = + complete_objc_class_type_sp->GetForwardCompilerType(); + + if (!type_clang_forward_type) + return false; + + if (!TypeSystemClang::IsObjCObjectOrInterfaceType(type_clang_forward_type)) + return false; + + clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType( + type_clang_forward_type, attrs.name.GetCString(), clang_type, + attrs.is_artificial, is_variadic, attrs.is_objc_direct_call); + + if (!objc_method_decl) { + dwarf->GetObjectFile()->GetModule()->ReportError( + "[{0:x16}]: invalid Objective-C method {1:x4} ({2}), " + "please file a bug and attach the file at the start of " + "this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + return false; + } + + LinkDeclContextToDIE(objc_method_decl, die); + m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); + + return true; +} + +std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod( + const DWARFDIE &die, CompilerType clang_type, + const ParsedDWARFTypeAttributes &attrs, const DWARFDIE &decl_ctx_die, + bool is_static, bool &ignore_containing_context) { + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + SymbolFileDWARF *dwarf = die.GetDWARF(); + assert(dwarf); + + Type *class_type = dwarf->ResolveType(decl_ctx_die); + if (!class_type) + return {}; + + 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"... + if (DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID())) { + std::vector<DWARFDIE> 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().lookup(die.GetDIE()); + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) + return {true, 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 + // completed so that the m_die_to_decl_ctx for the method in + // the specification has a valid clang decl context. + class_type->GetForwardCompilerType(); + // If we have a specification, then the function type should + // have been made with the specification and not with this + // die. + DWARFDIE spec_die = attrs.specification.Reference(); + clang::DeclContext *spec_clang_decl_ctx = + GetClangDeclContextForDIE(spec_die); + if (spec_clang_decl_ctx) + LinkDeclContextToDIE(spec_clang_decl_ctx, die); + else + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "{0:x8}: DW_AT_specification({1:x16}" + ") has no decl\n", + die.GetID(), spec_die.GetOffset()); + + return {true, nullptr}; + } + + if (attrs.abstract_origin.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the abstract origin has a valid clang decl context. + class_type->GetForwardCompilerType(); + + DWARFDIE abs_die = attrs.abstract_origin.Reference(); + clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE(abs_die); + if (abs_clang_decl_ctx) + LinkDeclContextToDIE(abs_clang_decl_ctx, die); + else + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "{0:x8}: DW_AT_abstract_origin({1:x16}" + ") has no decl\n", + die.GetID(), abs_die.GetOffset()); + + return {true, nullptr}; + } + + CompilerType class_opaque_type = class_type->GetForwardCompilerType(); + if (!TypeSystemClang::IsCXXClassType(class_opaque_type)) + return {}; + + if (class_opaque_type.IsBeingDefined()) { + // We have a C++ member function with no children (this + // pointer!) and clang will get mad if we try and make + // a function that isn't well formed in the DWARF, so + // we will just skip it... + if (!is_static && !die.HasChildren()) + return {true, nullptr}; + + const bool is_attr_used = false; + // Neither GCC 4.2 nor clang++ currently set a valid + // accessibility in the DWARF for C++ methods... + // Default to public for now... + const auto accessibility = attrs.accessibility == eAccessNone + ? eAccessPublic + : attrs.accessibility; + + clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( + class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), + attrs.mangled_name, clang_type, accessibility, attrs.is_virtual, + is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, + attrs.is_artificial); + + if (cxx_method_decl) { + LinkDeclContextToDIE(cxx_method_decl, die); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + char const *object_pointer_name = + attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr; + if (object_pointer_name) { + metadata.SetObjectPtrName(object_pointer_name); + LLDB_LOGF(log, + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name, static_cast<void *>(cxx_method_decl)); + } + m_ast.SetMetadata(cxx_method_decl, metadata); + } else { + ignore_containing_context = true; + } + + // Artificial methods are always handled even when we + // don't create a new declaration for them. + const bool type_handled = cxx_method_decl != nullptr || attrs.is_artificial; + + return {type_handled, nullptr}; + } + + // We were asked to parse the type for a method in a + // class, yet the class hasn't been asked to complete + // itself through the clang::ExternalASTSource protocol, + // so we need to just have the class complete itself and + // do things the right way, then our + // DIE should then have an entry in the + // dwarf->GetDIEToType() map. First + // we need to modify the dwarf->GetDIEToType() so it + // doesn't think we are trying to parse this DIE + // anymore... + dwarf->GetDIEToType().erase(die.GetDIE()); + + // Now we get the full type to force our class type to + // complete itself using the clang::ExternalASTSource + // protocol which will parse all base classes and all + // methods (including the method for this DIE). + class_type->GetFullCompilerType(); + + // The type for this DIE should have been filled in the + // function call above. + Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) + return {true, type_ptr->shared_from_this()}; + + // The previous comment isn't actually true if the class wasn't + // resolved using the current method's parent DIE as source + // data. We need to ensure that we look up the method correctly + // in the class and then link the method's DIE to the unique + // CXXMethodDecl appropriately. + return {true, nullptr}; +} + TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs) { @@ -989,13 +1186,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, unsigned type_quals = 0; - std::string object_pointer_name; - if (attrs.object_pointer) { - const char *object_pointer_name_cstr = attrs.object_pointer.GetName(); - if (object_pointer_name_cstr) - object_pointer_name = object_pointer_name_cstr; - } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); @@ -1066,208 +1256,19 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, if (attrs.name) { bool type_handled = false; if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { - std::optional<const ObjCLanguage::MethodName> objc_method = - ObjCLanguage::MethodName::Create(attrs.name.GetStringRef(), true); - if (objc_method) { - CompilerType class_opaque_type; - ConstString class_name(objc_method->GetClassName()); - if (class_name) { - TypeSP complete_objc_class_type_sp( - dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), - class_name, false)); - - if (complete_objc_class_type_sp) { - CompilerType type_clang_forward_type = - complete_objc_class_type_sp->GetForwardCompilerType(); - if (TypeSystemClang::IsObjCObjectOrInterfaceType( - type_clang_forward_type)) - class_opaque_type = type_clang_forward_type; - } - } - - if (class_opaque_type) { - clang::ObjCMethodDecl *objc_method_decl = - m_ast.AddMethodToObjCObjectType( - class_opaque_type, attrs.name.GetCString(), clang_type, - attrs.is_artificial, is_variadic, attrs.is_objc_direct_call); - type_handled = objc_method_decl != nullptr; - if (type_handled) { - LinkDeclContextToDIE(objc_method_decl, die); - m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "[{0:x16}]: invalid Objective-C method {1:x4} ({2}), " - "please file a bug and attach the file at the start of " - "this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - } - } + if (std::optional<const ObjCLanguage::MethodName> objc_method = + ObjCLanguage::MethodName::Create(attrs.name.GetStringRef(), + true)) { + type_handled = + ParseObjCMethod(*objc_method, die, clang_type, attrs, is_variadic); } else if (is_cxx_method) { - // Look at the parent of this DIE and see if it is a class or - // 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<DWARFDIE> 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(); - } - } - } + auto [handled, type_sp] = + ParseCXXMethod(die, clang_type, attrs, decl_ctx_die, is_static, + ignore_containing_context); + if (type_sp) + return type_sp; - 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 - // completed so that the m_die_to_decl_ctx for the method in - // the specification has a valid clang decl context. - class_type->GetForwardCompilerType(); - // If we have a specification, then the function type should - // have been made with the specification and not with this - // die. - DWARFDIE spec_die = attrs.specification.Reference(); - clang::DeclContext *spec_clang_decl_ctx = - GetClangDeclContextForDIE(spec_die); - if (spec_clang_decl_ctx) { - LinkDeclContextToDIE(spec_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "{0:x8}: DW_AT_specification({1:x16}" - ") has no decl\n", - die.GetID(), spec_die.GetOffset()); - } - type_handled = true; - } else if (attrs.abstract_origin.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the abstract origin has a valid clang decl context. - class_type->GetForwardCompilerType(); - - DWARFDIE abs_die = attrs.abstract_origin.Reference(); - clang::DeclContext *abs_clang_decl_ctx = - GetClangDeclContextForDIE(abs_die); - if (abs_clang_decl_ctx) { - LinkDeclContextToDIE(abs_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "{0:x8}: DW_AT_abstract_origin({1:x16}" - ") has no decl\n", - die.GetID(), abs_die.GetOffset()); - } - type_handled = true; - } else { - CompilerType class_opaque_type = - class_type->GetForwardCompilerType(); - if (TypeSystemClang::IsCXXClassType(class_opaque_type)) { - if (class_opaque_type.IsBeingDefined()) { - if (!is_static && !die.HasChildren()) { - // We have a C++ member function with no children (this - // pointer!) and clang will get mad if we try and make - // a function that isn't well formed in the DWARF, so - // we will just skip it... - type_handled = true; - } else { - llvm::PrettyStackTraceFormat stack_trace( - "SymbolFileDWARF::ParseType() is adding a method " - "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", - attrs.name.GetCString(), - class_type->GetName().GetCString(), die.GetID(), - dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str()); - - const bool is_attr_used = false; - // Neither GCC 4.2 nor clang++ currently set a valid - // accessibility in the DWARF for C++ methods... - // Default to public for now... - const auto accessibility = attrs.accessibility == eAccessNone - ? eAccessPublic - : attrs.accessibility; - - clang::CXXMethodDecl *cxx_method_decl = - m_ast.AddMethodToCXXRecordType( - class_opaque_type.GetOpaqueQualType(), - attrs.name.GetCString(), attrs.mangled_name, - clang_type, accessibility, attrs.is_virtual, - is_static, attrs.is_inline, attrs.is_explicit, - is_attr_used, attrs.is_artificial); - - type_handled = cxx_method_decl != nullptr; - // Artificial methods are always handled even when we - // don't create a new declaration for them. - type_handled |= attrs.is_artificial; - - if (cxx_method_decl) { - LinkDeclContextToDIE(cxx_method_decl, die); - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - LLDB_LOGF(log, - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast<void *>(cxx_method_decl)); - } - m_ast.SetMetadata(cxx_method_decl, metadata); - } else { - ignore_containing_context = true; - } - } - } else { - // We were asked to parse the type for a method in a - // class, yet the class hasn't been asked to complete - // itself through the clang::ExternalASTSource protocol, - // so we need to just have the class complete itself and - // do things the right way, then our - // DIE should then have an entry in the - // dwarf->GetDIEToType() map. First - // we need to modify the dwarf->GetDIEToType() so it - // doesn't think we are trying to parse this DIE - // anymore... - dwarf->GetDIEToType()[die.GetDIE()] = NULL; - - // Now we get the full type to force our class type to - // complete itself using the clang::ExternalASTSource - // protocol which will parse all base classes and all - // methods (including the method for this DIE). - class_type->GetFullCompilerType(); - - // The type for this DIE should have been filled in the - // function call above. - Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - return type_ptr->shared_from_this(); - } - - // The previous comment isn't actually true if the class wasn't - // resolved using the current method's parent DIE as source - // data. We need to ensure that we look up the method correctly - // in the class and then link the method's DIE to the unique - // CXXMethodDecl appropriately. - type_handled = true; - } - } - } - } + type_handled = handled; } } @@ -1356,13 +1357,14 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ClangASTMetadata metadata; metadata.SetUserID(die.GetID()); - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName(object_pointer_name.c_str()); + char const *object_pointer_name = + attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr; + if (object_pointer_name) { + metadata.SetObjectPtrName(object_pointer_name); LLDB_LOGF(log, "Setting object pointer name: %s on function " "object %p.", - object_pointer_name.c_str(), - static_cast<void *>(function_decl)); + object_pointer_name, static_cast<void *>(function_decl)); } m_ast.SetMetadata(function_decl, metadata); } @@ -1560,7 +1562,6 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( if (!type_sp) return type_sp; - SymbolFileDWARF *dwarf = die.GetDWARF(); DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); dw_tag_t sc_parent_tag = sc_parent_die.Tag(); @@ -1579,8 +1580,6 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( if (symbol_context_scope != nullptr) type_sp->SetSymbolContextScope(symbol_context_scope); - - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); return type_sp; } @@ -1616,7 +1615,7 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { case DW_TAG_union_type: { if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) { qualified_name.insert( - 0, GetDIEClassTemplateParams(parent_decl_ctx_die).AsCString("")); + 0, GetDIEClassTemplateParams(parent_decl_ctx_die)); qualified_name.insert(0, "::"); qualified_name.insert(0, class_union_struct_name); } @@ -1634,20 +1633,19 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { qualified_name.append("::"); qualified_name.append(name); - qualified_name.append(GetDIEClassTemplateParams(die).AsCString("")); + qualified_name.append(GetDIEClassTemplateParams(die)); return qualified_name; } TypeSP DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, - const DWARFDIE &die, + const DWARFDIE &decl_die, ParsedDWARFTypeAttributes &attrs) { - TypeSP type_sp; CompilerType clang_type; - const dw_tag_t tag = die.Tag(); - SymbolFileDWARF *dwarf = die.GetDWARF(); - LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU()); + const dw_tag_t tag = decl_die.Tag(); + SymbolFileDWARF *dwarf = decl_die.GetDWARF(); + LanguageType cu_language = SymbolFileDWARF::GetLanguage(*decl_die.GetCU()); Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); // UniqueDWARFASTType is large, so don't create a local variables on the @@ -1664,20 +1662,19 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // For C++, we rely solely upon the one definition rule that says // only one thing can exist at a given decl context. We ignore the // file and line that things are declared on. - std::string qualified_name = GetCPlusPlusQualifiedName(die); + std::string qualified_name = GetCPlusPlusQualifiedName(decl_die); if (!qualified_name.empty()) unique_typename = ConstString(qualified_name); unique_decl.Clear(); } if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, attrs.byte_size.value_or(-1), - *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + unique_typename, decl_die, unique_decl, + attrs.byte_size.value_or(-1), *unique_ast_entry_up)) { + if (TypeSP type_sp = unique_ast_entry_up->m_type_sp) { LinkDeclContextToDIE( - GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); + GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), + decl_die); return type_sp; } } @@ -1700,7 +1697,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, } if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC) { + !decl_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] @@ -1717,14 +1714,14 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, 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()) { + decl_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); + TypeSP type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(decl_die, attrs.name, true); if (!type_sp) { SymbolFileDWARFDebugMap *debug_map_symfile = @@ -1733,7 +1730,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // 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); + decl_die, attrs.name, true); } } @@ -1743,21 +1740,22 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an " "incomplete objc type, complete type is {5:x8}", - static_cast<void *>(this), die.GetOffset(), + static_cast<void *>(this), decl_die.GetOffset(), DW_TAG_value_to_name(tag), 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; } } } + DWARFDIE def_die; if (attrs.is_forward_declaration) { + Progress progress(llvm::formatv( + "Parsing type in {0}: '{1}'", + dwarf->GetObjectFile()->GetFileSpec().GetFilename().GetString(), + attrs.name.GetString())); + // 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 @@ -1768,83 +1766,80 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a " "forward declaration, trying to find complete type", - static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), - tag, attrs.name.GetCString()); + static_cast<void *>(this), decl_die.GetID(), + DW_TAG_value_to_name(tag), 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) + if (TypeSP type_sp = ParseTypeFromClangModule(sc, decl_die, log)) return type_sp; - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); + def_die = dwarf->FindDefinitionDIE(decl_die); - if (!type_sp) { + if (!def_die) { 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); + def_die = debug_map_symfile->FindDefinitionDIE(decl_die); } } - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a " - "forward declaration, complete type is {5:x8}", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), 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; + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a " + "forward declaration, complete type is {5}", + static_cast<void *>(this), def_die.GetID(), DW_TAG_value_to_name(tag), + tag, attrs.name.GetCString(), + def_die ? llvm::utohexstr(def_die.GetID()) : "not found"); } } + + if (def_die) { + attrs = ParsedDWARFTypeAttributes(def_die); + } else { + // No definition found. Proceed with the declaration die. We can use it to + // create a forward-declared type. + def_die = decl_die; + } 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); + clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(def_die, nullptr); - PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die, + PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), + containing_decl_ctx, def_die, attrs.name.GetCString()); - if (attrs.accessibility == eAccessNone && decl_ctx) { + if (attrs.accessibility == eAccessNone && containing_decl_ctx) { // Check the decl context that contains this class/struct/union. If // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + const clang::Decl::Kind containing_decl_kind = + containing_decl_ctx->getDeclKind(); if (DeclKindIsCXXClass(containing_decl_kind)) attrs.accessibility = default_accessibility; } ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + metadata.SetUserID(def_die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(def_die)); TypeSystemClang::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { + if (ParseTemplateParameterInfos(def_die, template_param_infos)) { clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, template_param_infos); + containing_decl_ctx, GetOwningClangModule(def_die), + attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, + template_param_infos); if (!class_template_decl) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" " "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), + static_cast<void *>(this), def_die.GetID(), DW_TAG_value_to_name(tag), tag, attrs.name.GetCString()); } return TypeSP(); @@ -1852,8 +1847,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, GetOwningClangModule(die), class_template_decl, - tag_decl_kind, template_param_infos); + containing_decl_ctx, GetOwningClangModule(def_die), + class_template_decl, tag_decl_kind, template_param_infos); clang_type = m_ast.CreateClassTemplateSpecializationType(class_specialization_decl); clang_type_was_created = true; @@ -1865,26 +1860,34 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (!clang_type_was_created) { clang_type_was_created = true; clang_type = m_ast.CreateRecordType( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, + containing_decl_ctx, GetOwningClangModule(def_die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, attrs.exports_symbols); } - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = dwarf->MakeType( - die.GetID(), attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, + TypeSP type_sp = dwarf->MakeType( + def_die.GetID(), attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward, TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); + // 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. + clang::DeclContext *type_decl_ctx = + TypeSystemClang::GetDeclContextForType(clang_type); + LinkDeclContextToDIE(type_decl_ctx, decl_die); + if (decl_die != def_die) { + LinkDeclContextToDIE(type_decl_ctx, def_die); + dwarf->GetDIEToType()[def_die.GetDIE()] = type_sp.get(); + // Declaration DIE is inserted into the type map in ParseTypeFromDWARF + } + // Add our type to the unique type map so we don't end up creating many // copies of the same type over and over in the ASTContext for our // module unique_ast_entry_up->m_type_sp = type_sp; - unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_die = def_die; unique_ast_entry_up->m_declaration = unique_decl; unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0); dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, @@ -1895,18 +1898,17 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // has child classes or types that require the class to be created // for use as their decl contexts the class will be ready to accept // these child definitions. - if (!die.HasChildren()) { + if (!def_die.HasChildren()) { // No children for this struct/union/class, lets finish it if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) { TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); } else { dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at {0:x16} named \"{1}\" was not able to start " - "its " + "DWARF DIE {0:x16} named \"{1}\" was not able to start its " "definition.\nPlease file a bug and attach the file at the " "start of this error message", - die.GetOffset(), attrs.name.GetCString()); + def_die.GetID(), attrs.name.GetCString()); } // Setting authority byte size and alignment for empty structures. @@ -1954,7 +1956,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // binaries. dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), - *die.GetDIERef()); + *def_die.GetDIERef()); m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); } } @@ -2440,7 +2442,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) { std::vector<clang::ParmVarDecl *> param_decls; StreamString sstr; - DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); + DWARFDeclContext decl_ctx = die.GetDWARFDeclContext(); sstr << decl_ctx.GetQualifiedName(); clang::DeclContext *containing_decl_ctx = @@ -3788,7 +3790,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (dst_decl_ctx) src_dwarf_ast_parser->LinkDeclContextToDIE(dst_decl_ctx, src); - if (Type *src_child_type = die_to_type[src.GetDIE()]) + if (Type *src_child_type = die_to_type.lookup(src.GetDIE())) die_to_type[dst.GetDIE()] = src_child_type; }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 8d4af203bb28..7b5ddbaa2a6b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -23,6 +23,7 @@ #include "lldb/Core/PluginInterface.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include <optional> @@ -103,9 +104,9 @@ public: /// /// \param die The struct/class DWARFDIE containing template parameters. /// \return A string, including surrounding '<>', of the template parameters. - /// If the DIE's name already has '<>', returns an empty ConstString because + /// If the DIE's name already has '<>', returns an empty string because /// it's assumed that the caller is using the DIE name anyway. - lldb_private::ConstString GetDIEClassTemplateParams( + std::string GetDIEClassTemplateParams( const lldb_private::plugin::dwarf::DWARFDIE &die) override; protected: @@ -370,6 +371,56 @@ private: ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); + + /// Helper function called by \ref ParseSubroutine when parsing ObjC-methods. + /// + /// \param[in] objc_method Name of the ObjC method being parsed. + /// + /// \param[in] die The DIE that represents the ObjC method being parsed. + /// + /// \param[in] clang_type The CompilerType representing the function prototype + /// of the ObjC method being parsed. + /// + /// \param[in] attrs DWARF attributes for \ref die. + /// + /// \param[in] is_variadic Is true iff we're parsing a variadic method. + /// + /// \returns true on success + bool + ParseObjCMethod(const lldb_private::ObjCLanguage::MethodName &objc_method, + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::CompilerType clang_type, + const ParsedDWARFTypeAttributes &attrs, bool is_variadic); + + /// Helper function called by \ref ParseSubroutine when parsing C++ methods. + /// + /// \param[in] die The DIE that represents the C++ method being parsed. + /// + /// \param[in] clang_type The CompilerType representing the function prototype + /// of the C++ method being parsed. + /// + /// \param[in] attrs DWARF attributes for \ref die. + /// + /// \param[in] decl_ctx_die The DIE representing the DeclContext of the C++ + /// method being parsed. + /// + /// \param[in] is_static Is true iff we're parsing a static method. + /// + /// \param[out] ignore_containing_context Will get set to true if the caller + /// should treat this C++ method as-if it was not a C++ method. + /// Currently used as a hack to work around templated C++ methods + /// causing class definitions to mismatch between CUs. + /// + /// \returns A pair of <bool, TypeSP>. The first element is 'true' on success. + /// The second element is non-null if we have previously parsed this + /// method (a null TypeSP does not indicate failure). + std::pair<bool, lldb::TypeSP> + ParseCXXMethod(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::CompilerType clang_type, + const ParsedDWARFTypeAttributes &attrs, + const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die, + bool is_static, bool &ignore_containing_context); + lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); lldb::TypeSP diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 7cf92adc6ef5..fb32e2adeb3f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -367,20 +367,6 @@ lldb_private::Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const { return nullptr; } -std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const { - if (!IsValid()) - return {}; - - std::vector<DWARFDIE> result; - DWARFDIE parent = GetParentDeclContextDIE(); - while (parent.IsValid() && parent.GetDIE() != GetDIE()) { - result.push_back(std::move(parent)); - parent = parent.GetParentDeclContextDIE(); - } - - return result; -} - static void GetDeclContextImpl(DWARFDIE die, llvm::SmallSet<lldb::user_id_t, 4> &seen, std::vector<CompilerContext> &context) { @@ -408,15 +394,13 @@ static void GetDeclContextImpl(DWARFDIE die, case DW_TAG_namespace: push_ctx(CompilerContextKind::Namespace, die.GetName()); break; + case DW_TAG_class_type: case DW_TAG_structure_type: - push_ctx(CompilerContextKind::Struct, die.GetName()); + push_ctx(CompilerContextKind::ClassOrStruct, die.GetName()); break; case DW_TAG_union_type: push_ctx(CompilerContextKind::Union, die.GetName()); break; - case DW_TAG_class_type: - push_ctx(CompilerContextKind::Class, die.GetName()); - break; case DW_TAG_enumeration_type: push_ctx(CompilerContextKind::Enum, die.GetName()); break; @@ -470,15 +454,13 @@ static void GetTypeLookupContextImpl(DWARFDIE die, case DW_TAG_namespace: push_ctx(CompilerContextKind::Namespace, die.GetName()); break; + case DW_TAG_class_type: case DW_TAG_structure_type: - push_ctx(CompilerContextKind::Struct, die.GetName()); + push_ctx(CompilerContextKind::ClassOrStruct, die.GetName()); break; case DW_TAG_union_type: push_ctx(CompilerContextKind::Union, die.GetName()); break; - case DW_TAG_class_type: - push_ctx(CompilerContextKind::Class, die.GetName()); - break; case DW_TAG_enumeration_type: push_ctx(CompilerContextKind::Enum, die.GetName()); break; @@ -491,6 +473,18 @@ static void GetTypeLookupContextImpl(DWARFDIE die, case DW_TAG_base_type: push_ctx(CompilerContextKind::Builtin, name); break; + // If any of the tags below appear in the parent chain, stop the decl + // context and return. Prior to these being in here, if a type existed in a + // namespace "a" like "a::my_struct", but we also have a function in that + // same namespace "a" which contained a type named "my_struct", both would + // return "a::my_struct" as the declaration context since the + // DW_TAG_subprogram would be skipped and its parent would be found. + case DW_TAG_compile_unit: + case DW_TAG_type_unit: + case DW_TAG_subprogram: + case DW_TAG_lexical_block: + case DW_TAG_inlined_subroutine: + return; default: break; } @@ -507,12 +501,64 @@ std::vector<CompilerContext> DWARFDIE::GetTypeLookupContext() const { return context; } +static DWARFDeclContext GetDWARFDeclContextImpl(DWARFDIE die) { + DWARFDeclContext dwarf_decl_ctx; + while (die) { + const dw_tag_t tag = die.Tag(); + if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) + break; + dwarf_decl_ctx.AppendDeclContext(tag, die.GetName()); + DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE(); + if (parent_decl_ctx_die == die) + break; + die = parent_decl_ctx_die; + } + return dwarf_decl_ctx; +} + +DWARFDeclContext DWARFDIE::GetDWARFDeclContext() const { + return GetDWARFDeclContextImpl(*this); +} + +static DWARFDIE GetParentDeclContextDIEImpl(DWARFDIE die) { + DWARFDIE orig_die = die; + while (die) { + // If this is the original DIE that we are searching for a declaration for, + // then don't look in the cache as we don't want our own decl context to be + // our decl context... + if (die != orig_die) { + switch (die.Tag()) { + case DW_TAG_compile_unit: + case DW_TAG_partial_unit: + case DW_TAG_namespace: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + return die; + + default: + break; + } + } + + if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) { + if (DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE()) + return decl_ctx_die; + } + + if (DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin)) { + if (DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE()) + return decl_ctx_die; + } + + die = die.GetParent(); + } + return DWARFDIE(); +} + DWARFDIE DWARFDIE::GetParentDeclContextDIE() const { - if (IsValid()) - return m_die->GetParentDeclContextDIE(m_cu); - else - return DWARFDIE(); + return GetParentDeclContextDIEImpl(*this); } bool DWARFDIE::IsStructUnionOrClass() const { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 511ca62d0197..e1318953a384 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -69,9 +69,6 @@ public: DWARFDIE GetParentDeclContextDIE() const; - // DeclContext related functions - std::vector<DWARFDIE> GetDeclContextDIEs() const; - /// Return this DIE's decl context as it is needed to look up types /// in Clang modules. This context will include any modules or functions that /// the type is declared in so an exact module match can be efficiently made. @@ -89,6 +86,8 @@ public: /// using a full or partial CompilerContext array. std::vector<CompilerContext> GetTypeLookupContext() const; + DWARFDeclContext GetDWARFDeclContext() const; + // Getting attribute values from the DIE. // // GetAttributeValueAsXXX() functions should only be used if you are diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index da73891f6665..f383261e8a5f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -89,8 +89,7 @@ void DWARFDebugAranges::AppendRange(dw_offset_t offset, dw_addr_t low_pc, } void DWARFDebugAranges::Sort(bool minimize) { - LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION, - static_cast<void *>(this)); + LLDB_SCOPED_TIMER(); m_aranges.Sort(); m_aranges.CombineConsecutiveEntriesWithEqualData(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index c37cc91e08ed..f7df38d24019 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -232,6 +232,10 @@ DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, return result; } +const std::shared_ptr<SymbolFileDWARFDwo> &DWARFDebugInfo::GetDwpSymbolFile() { + return m_dwarf.GetDwpSymbolFile(); +} + DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { auto pos = llvm::lower_bound(m_type_hash_to_unit_index, std::make_pair(hash, 0u), llvm::less_first()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index 4706b55d38ea..598739bf3cb9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -52,6 +52,8 @@ public: const DWARFDebugAranges &GetCompileUnitAranges(); + const std::shared_ptr<SymbolFileDWARFDwo> &GetDwpSymbolFile(); + protected: typedef std::vector<DWARFUnitSP> UnitColl; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 688a287a0650..e2660735ea7d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -610,79 +610,6 @@ void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( } } -DWARFDeclContext -DWARFDebugInfoEntry::GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, - DWARFUnit *cu) { - DWARFDeclContext dwarf_decl_ctx; - for (;;) { - const dw_tag_t tag = die->Tag(); - if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) - return dwarf_decl_ctx; - dwarf_decl_ctx.AppendDeclContext(tag, die->GetName(cu)); - DWARFDIE parent_decl_ctx_die = die->GetParentDeclContextDIE(cu); - if (!parent_decl_ctx_die || parent_decl_ctx_die.GetDIE() == die) - return dwarf_decl_ctx; - if (parent_decl_ctx_die.Tag() == DW_TAG_compile_unit || - parent_decl_ctx_die.Tag() == DW_TAG_partial_unit) - return dwarf_decl_ctx; - die = parent_decl_ctx_die.GetDIE(); - cu = parent_decl_ctx_die.GetCU(); - } -} - -DWARFDeclContext DWARFDebugInfoEntry::GetDWARFDeclContext(DWARFUnit *cu) const { - return GetDWARFDeclContextStatic(this, cu); -} - -DWARFDIE -DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const { - DWARFAttributes attributes = GetAttributes(cu, Recurse::yes); - return GetParentDeclContextDIE(cu, attributes); -} - -DWARFDIE -DWARFDebugInfoEntry::GetParentDeclContextDIE( - DWARFUnit *cu, const DWARFAttributes &attributes) const { - DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); - - while (die) { - // If this is the original DIE that we are searching for a declaration for, - // then don't look in the cache as we don't want our own decl context to be - // our decl context... - if (die.GetDIE() != this) { - switch (die.Tag()) { - case DW_TAG_compile_unit: - case DW_TAG_partial_unit: - case DW_TAG_namespace: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: - return die; - - default: - break; - } - } - - DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification); - if (spec_die) { - DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); - if (decl_ctx_die) - return decl_ctx_die; - } - - DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin); - if (abs_die) { - DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); - if (decl_ctx_die) - return decl_ctx_die; - } - - die = die.GetParent(); - } - return DWARFDIE(); -} - lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { return GetOffset() + llvm::getULEB128Size(m_abbr_idx); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 6773b00e8206..3816c6500717 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -157,12 +157,6 @@ public: return HasChildren() ? this + 1 : nullptr; } - DWARFDeclContext GetDWARFDeclContext(DWARFUnit *cu) const; - - DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu) const; - DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu, - const DWARFAttributes &attributes) const; - void SetSiblingIndex(uint32_t idx) { m_sibling_idx = idx; } void SetParentIndex(uint32_t idx) { m_parent_idx = idx; } @@ -172,9 +166,6 @@ public: bool IsGlobalOrStaticScopeVariable() const; protected: - static DWARFDeclContext - GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu); - // Up to 2TB offset within the .debug_info/.debug_types dw_offset_t m_offset : DW_DIE_OFFSET_MAX_BITSIZE; // How many to subtract from "this" to get the parent. If zero this die has no diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp index 44421c0eda3e..f759cb8fae61 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp @@ -12,18 +12,16 @@ using namespace lldb_private::dwarf; using namespace lldb_private::plugin::dwarf; -/// Returns the name of `entry` if it has one, or the appropriate "anonymous -/// {namespace, class, struct, union}". -static const char *GetName(DWARFDeclContext::Entry entry) { - if (entry.name != nullptr) - return entry.name; - if (entry.tag == DW_TAG_namespace) +const char *DWARFDeclContext::Entry::GetName() const { + if (name != nullptr) + return name; + if (tag == DW_TAG_namespace) return "(anonymous namespace)"; - if (entry.tag == DW_TAG_class_type) + if (tag == DW_TAG_class_type) return "(anonymous class)"; - if (entry.tag == DW_TAG_structure_type) + if (tag == DW_TAG_structure_type) return "(anonymous struct)"; - if (entry.tag == DW_TAG_union_type) + if (tag == DW_TAG_union_type) return "(anonymous union)"; return "(anonymous)"; } @@ -46,7 +44,7 @@ const char *DWARFDeclContext::GetQualifiedName() const { llvm::raw_string_ostream string_stream(m_qualified_name); llvm::interleave( llvm::reverse(m_entries), string_stream, - [&](auto entry) { string_stream << GetName(entry); }, "::"); + [&](auto entry) { string_stream << entry.GetName(); }, "::"); } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 7e6c5f51f4be..b563d1c4417b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -9,8 +9,9 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H -#include "lldb/Utility/ConstString.h" #include "DWARFDefines.h" +#include "lldb/Utility/ConstString.h" +#include "llvm/ADT/StringExtras.h" #include <cassert> #include <string> @@ -38,6 +39,10 @@ public: return false; } + /// Returns the name of this entry if it has one, or the appropriate + /// "anonymous {namespace, class, struct, union}". + const char *GetName() const; + // Test operator explicit operator bool() const { return tag != 0; } @@ -83,6 +88,17 @@ public: m_qualified_name.clear(); } + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const DWARFDeclContext &ctx) { + OS << "DWARFDeclContext{"; + llvm::ListSeparator LS; + for (const Entry &e : ctx.m_entries) { + OS << LS << "{" << DW_TAG_value_to_name(e.tag) << ", " << e.GetName() + << "}"; + } + return OS << "}"; + } + protected: typedef std::vector<Entry> collection; collection m_entries; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 30fb5d5ebdb0..eafddbad03f5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -121,8 +121,7 @@ void DWARFIndex::GetFullyQualifiedType( bool DWARFIndex::GetFullyQualifiedTypeImpl( const DWARFDeclContext &context, DWARFDIE die, llvm::function_ref<bool(DWARFDIE die)> callback) { - DWARFDeclContext dwarf_decl_ctx = - die.GetDIE()->GetDWARFDeclContext(die.GetCU()); + DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext(); if (dwarf_decl_ctx == context) return callback(die); return true; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index 90e42be7202d..7e66b3dccf97 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -10,6 +10,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" #include "lldb/Core/Module.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" @@ -34,6 +35,17 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, module, std::move(index_up), debug_names, debug_str, dwarf)); } +llvm::DenseSet<uint64_t> +DebugNamesDWARFIndex::GetTypeUnitSignatures(const DebugNames &debug_names) { + llvm::DenseSet<uint64_t> result; + for (const DebugNames::NameIndex &ni : debug_names) { + const uint32_t num_tus = ni.getForeignTUCount(); + for (uint32_t tu = 0; tu < num_tus; ++tu) + result.insert(ni.getForeignTUSignature(tu)); + } + return result; +} + llvm::DenseSet<dw_offset_t> DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { llvm::DenseSet<dw_offset_t> result; @@ -48,20 +60,80 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { return result; } +std::optional<DWARFTypeUnit *> +DebugNamesDWARFIndex::GetForeignTypeUnit(const DebugNames::Entry &entry) const { + std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature(); + if (!type_sig.has_value()) + return std::nullopt; + + // Ask the entry for the skeleton compile unit offset and fetch the .dwo + // file from it and get the type unit by signature from there. If we find + // the type unit in the .dwo file, we don't need to check that the + // DW_AT_dwo_name matches because each .dwo file can have its own type unit. + std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset(); + if (!cu_offset) + return nullptr; // Return NULL, this is a type unit, but couldn't find it. + + DWARFUnit *cu = + m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); + if (!cu) + return nullptr; // Return NULL, this is a type unit, but couldn't find it. + + auto dwp_sp = m_debug_info.GetDwpSymbolFile(); + if (!dwp_sp) { + // No .dwp file, we need to load the .dwo file. + DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit(); + // We don't need the check if the type unit matches the .dwo file if we have + // a .dwo file (not a .dwp), so we can just return the value here. + if (!dwo_cu.IsDWOUnit()) + return nullptr; // We weren't able to load the .dwo file. + return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash( + *type_sig); + } + // We have a .dwp file, just get the type unit from there. We need to verify + // that the type unit that ended up in the final .dwp file is the right type + // unit. Type units have signatures which are the same across multiple .dwo + // files, but only one of those type units will end up in the .dwp file. The + // contents of type units for the same type can be different in different .dwo + // files, which means the DIE offsets might not be the same between two + // different type units. So we need to determine if this accelerator table + // matches the type unit that ended up in the .dwp file. If it doesn't match, + // then we need to ignore this accelerator table entry as the type unit that + // is in the .dwp file will have its own index. In order to determine if the + // type unit that ended up in a .dwp file matches this DebugNames::Entry, we + // need to find the skeleton compile unit for this entry. + DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig); + if (!foreign_tu) + return nullptr; // Return NULL, this is a type unit, but couldn't find it. + + DWARFBaseDIE cu_die = cu->GetUnitDIEOnly(); + DWARFBaseDIE tu_die = foreign_tu->GetUnitDIEOnly(); + llvm::StringRef cu_dwo_name = + cu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr); + llvm::StringRef tu_dwo_name = + tu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr); + if (cu_dwo_name == tu_dwo_name) + return foreign_tu; // We found a match! + return nullptr; // Return NULL, this is a type unit, but couldn't find it. +} + DWARFUnit * DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const { + + if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry)) + return foreign_tu.value(); + // Look for a DWARF unit offset (CU offset or local TU offset) as they are // both offsets into the .debug_info section. std::optional<uint64_t> unit_offset = entry.getCUOffset(); - if (!unit_offset) { + if (!unit_offset) unit_offset = entry.getLocalTUOffset(); - if (!unit_offset) - return nullptr; + if (unit_offset) { + if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, + *unit_offset)) + return &cu->GetNonSkeletonUnit(); } - - DWARFUnit *cu = - m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *unit_offset); - return cu ? &cu->GetNonSkeletonUnit() : nullptr; + return nullptr; } DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const { @@ -85,6 +157,11 @@ bool DebugNamesDWARFIndex::ProcessEntry( DWARFDIE die = GetDIE(entry); if (!die) return true; + // Clang used to erroneously emit index entries for declaration DIEs in case + // when the definition is in a type unit (llvm.org/pr77696). + if (die.IsStructUnionOrClass() && + die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0)) + return true; return callback(die); } @@ -269,6 +346,13 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType( if (!isType(entry.tag())) continue; + // If we get a NULL foreign_tu back, the entry doesn't match the type unit + // in the .dwp file, or we were not able to load the .dwo file or the DWO ID + // didn't match. + std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry); + if (foreign_tu && foreign_tu.value() == nullptr) + continue; + // Grab at most one extra parent, subsequent parents are not necessary to // test equality. std::optional<llvm::SmallVector<Entry, 4>> parent_chain = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index a27a414ecdd1..cb15c1d4f994 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -70,7 +70,8 @@ private: : DWARFIndex(module), m_debug_info(dwarf.DebugInfo()), m_debug_names_data(debug_names_data), m_debug_str_data(debug_str_data), m_debug_names_up(std::move(debug_names_up)), - m_fallback(module, dwarf, GetUnits(*m_debug_names_up)) {} + m_fallback(module, dwarf, GetUnits(*m_debug_names_up), + GetTypeUnitSignatures(*m_debug_names_up)) {} DWARFDebugInfo &m_debug_info; @@ -85,6 +86,31 @@ private: DWARFUnit *GetNonSkeletonUnit(const DebugNames::Entry &entry) const; DWARFDIE GetDIE(const DebugNames::Entry &entry) const; + + /// Checks if an entry is a foreign TU and fetch the type unit. + /// + /// This function checks if the DebugNames::Entry refers to a foreign TU and + /// returns an optional with a value of the \a entry is a foreign type unit + /// entry. A valid pointer will be returned if this entry is from a .dwo file + /// or if it is from a .dwp file and it matches the type unit's originating + /// .dwo file by verifying that the DW_TAG_type_unit DIE has a DW_AT_dwo_name + /// that matches the DWO name from the originating skeleton compile unit. + /// + /// \param[in] entry + /// The accelerator table entry to check. + /// + /// \returns + /// A std::optional that has a value if this entry represents a foreign type + /// unit. If the pointer is valid, then we were able to find and match the + /// entry to the type unit in the .dwo or .dwp file. The returned value can + /// have a valid, yet contain NULL in the following cases: + /// - we were not able to load the .dwo file (missing or DWO ID mismatch) + /// - we were able to load the .dwp file, but the type units DWO name + /// doesn't match the originating skeleton compile unit's entry + /// Returns std::nullopt if this entry is not a foreign type unit entry. + std::optional<DWARFTypeUnit *> + GetForeignTypeUnit(const DebugNames::Entry &entry) const; + bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref<bool(DWARFDIE die)> callback); @@ -97,6 +123,8 @@ private: llvm::StringRef name); static llvm::DenseSet<dw_offset_t> GetUnits(const DebugNames &debug_names); + static llvm::DenseSet<uint64_t> + GetTypeUnitSignatures(const DebugNames &debug_names); }; } // namespace dwarf diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index 92275600f99c..d581d3773ab2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -60,8 +60,11 @@ void ManualDWARFIndex::Index() { } if (dwp_info && dwp_info->ContainsTypeUnits()) { for (size_t U = 0; U < dwp_info->GetNumUnits(); ++U) { - if (auto *tu = llvm::dyn_cast<DWARFTypeUnit>(dwp_info->GetUnitAtIndex(U))) - units_to_index.push_back(tu); + if (auto *tu = + llvm::dyn_cast<DWARFTypeUnit>(dwp_info->GetUnitAtIndex(U))) { + if (!m_type_sigs_to_avoid.contains(tu->GetTypeHash())) + units_to_index.push_back(tu); + } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 0126e587e52d..d8c4a22ab21f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -21,9 +21,11 @@ class SymbolFileDWARFDwo; class ManualDWARFIndex : public DWARFIndex { public: ManualDWARFIndex(Module &module, SymbolFileDWARF &dwarf, - llvm::DenseSet<dw_offset_t> units_to_avoid = {}) + llvm::DenseSet<dw_offset_t> units_to_avoid = {}, + llvm::DenseSet<uint64_t> type_sigs_to_avoid = {}) : DWARFIndex(module), m_dwarf(&dwarf), - m_units_to_avoid(std::move(units_to_avoid)) {} + m_units_to_avoid(std::move(units_to_avoid)), + m_type_sigs_to_avoid(std::move(type_sigs_to_avoid)) {} void Preload() override { Index(); } @@ -170,6 +172,7 @@ private: SymbolFileDWARF *m_dwarf; /// Which dwarf units should we skip while building the index. llvm::DenseSet<dw_offset_t> m_units_to_avoid; + llvm::DenseSet<uint64_t> m_type_sigs_to_avoid; IndexSet m_set; bool m_indexed = false; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index a52a7d676737..f2ff3a8b259f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -710,8 +710,8 @@ llvm::DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { DWARFDebugInfo &SymbolFileDWARF::DebugInfo() { llvm::call_once(m_info_once_flag, [&] { - LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION, - static_cast<void *>(this)); + LLDB_SCOPED_TIMER(); + m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); }); return *m_info; @@ -732,8 +732,7 @@ DWARFCompileUnit *SymbolFileDWARF::GetDWARFCompileUnit(CompileUnit *comp_unit) { DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { if (!m_ranges) { - LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION, - static_cast<void *>(this)); + LLDB_SCOPED_TIMER(); if (m_context.getOrLoadRangesData().GetByteSize() > 0) m_ranges = std::make_unique<DWARFDebugRanges>(); @@ -1728,14 +1727,7 @@ lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) { return pos->second; } -DWARFDIE -SymbolFileDWARF::GetDIE(const DIERef &die_ref) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - - SymbolFileDWARF *symbol_file = nullptr; - +SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) { // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we // must make sure we use the correct DWARF file when resolving things. On // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple @@ -1743,30 +1735,44 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { // references to other DWARF objects and we must be ready to receive a // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF // instance. + std::optional<uint32_t> file_index = die_ref.file_index(); - if (file_index) { - if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) { - symbol_file = debug_map->GetSymbolFileByOSOIndex(*file_index); // OSO case - if (symbol_file) - return symbol_file->DebugInfo().GetDIE(die_ref.section(), - die_ref.die_offset()); - return DWARFDIE(); - } + // If the file index matches, then we have the right SymbolFileDWARF already. + // This will work for both .dwo file and DWARF in .o files for mac. Also if + // both the file indexes are invalid, then we have a match. + if (GetFileIndex() == file_index) + return this; + + if (file_index) { + // We have a SymbolFileDWARFDebugMap, so let it find the right file + if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) + return debug_map->GetSymbolFileByOSOIndex(*file_index); + + // Handle the .dwp file case correctly if (*file_index == DIERef::k_file_index_mask) - symbol_file = GetDwpSymbolFile().get(); // DWP case - else - symbol_file = this->DebugInfo() - .GetUnitAtIndex(*die_ref.file_index()) - ->GetDwoSymbolFile(); // DWO case - } else if (die_ref.die_offset() == DW_INVALID_OFFSET) { - return DWARFDIE(); + return GetDwpSymbolFile().get(); // DWP case + + // Handle the .dwo file case correctly + return DebugInfo().GetUnitAtIndex(*die_ref.file_index()) + ->GetDwoSymbolFile(); // DWO case } + return this; +} - if (symbol_file) - return symbol_file->GetDIE(die_ref); +DWARFDIE +SymbolFileDWARF::GetDIE(const DIERef &die_ref) { + if (die_ref.die_offset() == DW_INVALID_OFFSET) + return DWARFDIE(); - return DebugInfo().GetDIE(die_ref.section(), die_ref.die_offset()); + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + SymbolFileDWARF *symbol_file = GetDIERefSymbolFile(die_ref); + if (symbol_file) + return symbol_file->DebugInfo().GetDIE(die_ref.section(), + die_ref.die_offset()); + return DWARFDIE(); } /// Return the DW_AT_(GNU_)dwo_id. @@ -3039,205 +3045,113 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( return type_sp; } -// This function helps to ensure that the declaration contexts match for two -// different DIEs. Often times debug information will refer to a forward -// declaration of a type (the equivalent of "struct my_struct;". There will -// often be a declaration of that type elsewhere that has the full definition. -// When we go looking for the full type "my_struct", we will find one or more -// matches in the accelerator tables and we will then need to make sure the -// type was in the same declaration context as the original DIE. This function -// can efficiently compare two DIEs and will return true when the declaration -// context matches, and false when they don't. -bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, - const DWARFDIE &die2) { - if (die1 == die2) - return true; +DWARFDIE +SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { + if (!die.GetName()) + return {}; - std::vector<DWARFDIE> decl_ctx_1; - std::vector<DWARFDIE> decl_ctx_2; - // The declaration DIE stack is a stack of the declaration context DIEs all - // the way back to the compile unit. If a type "T" is declared inside a class - // "B", and class "B" is declared inside a class "A" and class "A" is in a - // namespace "lldb", and the namespace is in a compile unit, there will be a - // stack of DIEs: - // - // [0] DW_TAG_class_type for "B" - // [1] DW_TAG_class_type for "A" - // [2] DW_TAG_namespace for "lldb" - // [3] DW_TAG_compile_unit or DW_TAG_partial_unit for the source file. - // - // We grab both contexts and make sure that everything matches all the way - // back to the compiler unit. - - // First lets grab the decl contexts for both DIEs - decl_ctx_1 = die1.GetDeclContextDIEs(); - decl_ctx_2 = die2.GetDeclContextDIEs(); - // Make sure the context arrays have the same size, otherwise we are done - const size_t count1 = decl_ctx_1.size(); - const size_t count2 = decl_ctx_2.size(); - if (count1 != count2) - return false; + const dw_tag_t tag = die.Tag(); - // Make sure the DW_TAG values match all the way back up the compile unit. If - // they don't, then we are done. - DWARFDIE decl_ctx_die1; - DWARFDIE decl_ctx_die2; - size_t i; - for (i = 0; i < count1; i++) { - decl_ctx_die1 = decl_ctx_1[i]; - decl_ctx_die2 = decl_ctx_2[i]; - if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag()) - return false; + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindDefinitionDIE(tag={0} " + "({1}), name='{2}')", + DW_TAG_value_to_name(tag), tag, die.GetName()); } -#ifndef NDEBUG - - // Make sure the top item in the decl context die array is always - // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then - // something went wrong in the DWARFDIE::GetDeclContextDIEs() - // function. - dw_tag_t cu_tag = decl_ctx_1[count1 - 1].Tag(); - UNUSED_IF_ASSERT_DISABLED(cu_tag); - assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit); - -#endif - // Always skip the compile unit when comparing by only iterating up to "count - // - 1". Here we compare the names as we go. - for (i = 0; i < count1 - 1; i++) { - decl_ctx_die1 = decl_ctx_1[i]; - decl_ctx_die2 = decl_ctx_2[i]; - const char *name1 = decl_ctx_die1.GetName(); - const char *name2 = decl_ctx_die2.GetName(); - // If the string was from a DW_FORM_strp, then the pointer will often be - // the same! - if (name1 == name2) - continue; - // Name pointers are not equal, so only compare the strings if both are not - // NULL. - if (name1 && name2) { - // If the strings don't compare, we are done... - if (strcmp(name1, name2) != 0) - return false; + // Get the type system that we are looking to find a type for. We will + // use this to ensure any matches we find are in a language that this + // type system supports + const LanguageType language = GetLanguage(*die.GetCU()); + TypeSystemSP type_system = nullptr; + if (language != eLanguageTypeUnknown) { + auto type_system_or_err = GetTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), + "Cannot get TypeSystem for language {1}: {0}", + Language::GetNameForLanguageType(language)); } else { - // One name was NULL while the other wasn't - return false; + type_system = *type_system_or_err; } } - // We made it through all of the checks and the declaration contexts are - // equal. - return true; -} - -TypeSP -SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { - TypeSP type_sp; - if (die.GetName()) { - const dw_tag_t tag = die.Tag(); - - Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag={0} " - "({1}), name='{2}')", - DW_TAG_value_to_name(tag), tag, die.GetName()); - } - - // Get the type system that we are looking to find a type for. We will - // use this to ensure any matches we find are in a language that this - // type system supports - const LanguageType language = GetLanguage(*die.GetCU()); - TypeSystemSP type_system = nullptr; - if (language != eLanguageTypeUnknown) { - auto type_system_or_err = GetTypeSystemForLanguage(language); - if (auto err = type_system_or_err.takeError()) { - LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), - "Cannot get TypeSystem for language {1}: {0}", - Language::GetNameForLanguageType(language)); - } else { - type_system = *type_system_or_err; + // See comments below about -gsimple-template-names for why we attempt to + // compute missing template parameter names. + std::vector<std::string> template_params; + DWARFDeclContext die_dwarf_decl_ctx; + DWARFASTParser *dwarf_ast = + type_system ? type_system->GetDWARFParser() : nullptr; + for (DWARFDIE ctx_die = die; ctx_die && !isUnitType(ctx_die.Tag()); + ctx_die = ctx_die.GetParentDeclContextDIE()) { + die_dwarf_decl_ctx.AppendDeclContext(ctx_die.Tag(), ctx_die.GetName()); + template_params.push_back( + (ctx_die.IsStructUnionOrClass() && dwarf_ast) + ? dwarf_ast->GetDIEClassTemplateParams(ctx_die) + : ""); + } + const bool any_template_params = llvm::any_of( + template_params, [](llvm::StringRef p) { return !p.empty(); }); + + auto die_matches = [&](DWARFDIE type_die) { + // Resolve the type if both have the same tag or {class, struct} tags. + const bool tag_matches = + type_die.Tag() == tag || + (IsStructOrClassTag(type_die.Tag()) && IsStructOrClassTag(tag)); + if (!tag_matches) + return false; + if (any_template_params) { + size_t pos = 0; + for (DWARFDIE ctx_die = type_die; ctx_die && !isUnitType(ctx_die.Tag()) && + pos < template_params.size(); + ctx_die = ctx_die.GetParentDeclContextDIE(), ++pos) { + if (template_params[pos].empty()) + continue; + if (template_params[pos] != + dwarf_ast->GetDIEClassTemplateParams(ctx_die)) + return false; } + if (pos != template_params.size()) + return false; } + return true; + }; + DWARFDIE result; + m_index->GetFullyQualifiedType(die_dwarf_decl_ctx, [&](DWARFDIE type_die) { + // Make sure type_die's language matches the type system we are + // looking for. We don't want to find a "Foo" type from Java if we + // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. + if (type_system && + !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) + return true; - // See comments below about -gsimple-template-names for why we attempt to - // compute missing template parameter names. - ConstString template_params; - if (type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast) - template_params = dwarf_ast->GetDIEClassTemplateParams(die); - } - - const DWARFDeclContext die_dwarf_decl_ctx = GetDWARFDeclContext(die); - m_index->GetFullyQualifiedType(die_dwarf_decl_ctx, [&](DWARFDIE type_die) { - // Make sure type_die's language matches the type system we are - // looking for. We don't want to find a "Foo" type from Java if we - // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. - if (type_system && - !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) - return true; - - const dw_tag_t type_tag = type_die.Tag(); - // Resolve the type if both have the same tag or {class, struct} tags. - const bool try_resolving_type = - type_tag == tag || - (IsStructOrClassTag(type_tag) && IsStructOrClassTag(tag)); - - if (!try_resolving_type) { - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag={0} ({1}), " - "name='{2}') ignoring die={3:x16} ({4})", - DW_TAG_value_to_name(tag), tag, die.GetName(), - type_die.GetOffset(), type_die.GetName()); - } - return true; - } - + if (!die_matches(type_die)) { if (log) { - DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die); GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag={0} ({1}), name='{2}') " - "trying die={3:x16} ({4})", + "SymbolFileDWARF::FindDefinitionDIE(tag={0} ({1}), " + "name='{2}') ignoring die={3:x16} ({4})", DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(), - type_dwarf_decl_ctx.GetQualifiedName()); + type_die.GetName()); } + return true; + } - Type *resolved_type = ResolveType(type_die, false); - if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) - return true; - - // With -gsimple-template-names, the DIE name may not contain the template - // parameters. If the declaration has template parameters but doesn't - // contain '<', check that the child template parameters match. - if (template_params) { - llvm::StringRef test_base_name = - GetTypeForDIE(type_die)->GetBaseName().GetStringRef(); - auto i = test_base_name.find('<'); - - // Full name from clang AST doesn't contain '<' so this type_die isn't - // a template parameter, but we're expecting template parameters, so - // bail. - if (i == llvm::StringRef::npos) - return true; - - llvm::StringRef test_template_params = - test_base_name.slice(i, test_base_name.size()); - // Bail if template parameters don't match. - if (test_template_params != template_params.GetStringRef()) - return true; - } + if (log) { + DWARFDeclContext type_dwarf_decl_ctx = type_die.GetDWARFDeclContext(); + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindDefinitionTypeDIE(tag={0} ({1}), name='{2}') " + "trying die={3:x16} ({4})", + DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(), + type_dwarf_decl_ctx.GetQualifiedName()); + } - type_sp = resolved_type->shared_from_this(); - return false; - }); - } - return type_sp; + result = type_die; + return false; + }); + return result; } TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, @@ -3624,8 +3538,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if ((parent_tag == DW_TAG_compile_unit || parent_tag == DW_TAG_partial_unit) && Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU()))) - mangled = - GetDWARFDeclContext(die).GetQualifiedNameAsConstString().GetCString(); + mangled = die.GetDWARFDeclContext() + .GetQualifiedNameAsConstString() + .GetCString(); } if (tag == DW_TAG_formal_parameter) @@ -4450,14 +4365,6 @@ SymbolFileDWARF::GetContainingDeclContext(const DWARFDIE &die) { return CompilerDeclContext(); } -DWARFDeclContext SymbolFileDWARF::GetDWARFDeclContext(const DWARFDIE &die) { - if (!die.IsValid()) - return {}; - DWARFDeclContext dwarf_decl_ctx = - die.GetDIE()->GetDWARFDeclContext(die.GetCU()); - return dwarf_decl_ctx; -} - LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) { // Note: user languages between lo_user and hi_user must be handled // explicitly here. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 7282c08c6857..8469248872a4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -241,6 +241,15 @@ public: return m_external_type_modules; } + /// Given a DIERef, find the correct SymbolFileDWARF. + /// + /// A DIERef contains a file index that can uniquely identify a N_OSO file for + /// DWARF in .o files on mac, or a .dwo or .dwp file index for split DWARF. + /// Calling this function will find the correct symbol file to use so that + /// further lookups can be done on the correct symbol file so that the DIE + /// offset makes sense in the DIERef. + virtual SymbolFileDWARF *GetDIERefSymbolFile(const DIERef &die_ref); + virtual DWARFDIE GetDIE(const DIERef &die_ref); DWARFDIE GetDIE(lldb::user_id_t uid); @@ -296,8 +305,6 @@ public: static CompilerDeclContext GetContainingDeclContext(const DWARFDIE &die); - static DWARFDeclContext GetDWARFDeclContext(const DWARFDIE &die); - static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val); static lldb::LanguageType GetLanguage(DWARFUnit &unit); @@ -353,8 +360,7 @@ public: SymbolFileDWARFDebugMap *GetDebugMapSymfile(); - virtual lldb::TypeSP - FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); + virtual DWARFDIE FindDefinitionDIE(const DWARFDIE &die); virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( const DWARFDIE &die, ConstString type_name, bool must_be_implementation); @@ -461,8 +467,6 @@ protected: FindBlockContainingSpecification(const DWARFDIE &die, dw_offset_t spec_block_die_offset); - bool DIEDeclContextsMatch(const DWARFDIE &die1, const DWARFDIE &die2); - bool ClassContainsSelector(const DWARFDIE &class_die, ConstString selector); /// Parse call site entries (DW_TAG_call_site), including any nested call site diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index f066f13d51c5..64cde16433ef 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1147,14 +1147,13 @@ SymbolFileDWARFDebugMap::ParseCallEdgesInFunction( return {}; } -TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext( - const DWARFDIE &die) { - TypeSP type_sp; +DWARFDIE SymbolFileDWARFDebugMap::FindDefinitionDIE(const DWARFDIE &die) { + DWARFDIE result; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) { - type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die); - return type_sp ? IterationAction::Stop : IterationAction::Continue; + result = oso_dwarf->FindDefinitionDIE(die); + return result ? IterationAction::Stop : IterationAction::Continue; }); - return type_sp; + return result; } bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index de22dd676eef..7d5516b92737 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -277,7 +277,7 @@ protected: CompileUnitInfo *GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf); - lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); + DWARFDIE FindDefinitionDIE(const DWARFDIE &die); bool Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF *skip_dwarf_oso); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 71c9997e4c82..4a8c532a0d2a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -125,9 +125,8 @@ UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { return GetBaseSymbolFile().GetUniqueDWARFASTTypeMap(); } -lldb::TypeSP -SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { - return GetBaseSymbolFile().FindDefinitionTypeForDWARFDeclContext(die); +DWARFDIE SymbolFileDWARFDwo::FindDefinitionDIE(const DWARFDIE &die) { + return GetBaseSymbolFile().FindDefinitionDIE(die); } lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( @@ -174,3 +173,8 @@ bool SymbolFileDWARFDwo::GetDebugInfoHadFrameVariableErrors() const { void SymbolFileDWARFDwo::SetDebugInfoHadFrameVariableErrors() { return GetBaseSymbolFile().SetDebugInfoHadFrameVariableErrors(); } + +SymbolFileDWARF * +SymbolFileDWARFDwo::GetDIERefSymbolFile(const DIERef &die_ref) { + return GetBaseSymbolFile().GetDIERefSymbolFile(die_ref); +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 1500540424b5..3bd0a2d25a5a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -67,6 +67,8 @@ public: bool GetDebugInfoHadFrameVariableErrors() const override; void SetDebugInfoHadFrameVariableErrors() override; + SymbolFileDWARF *GetDIERefSymbolFile(const DIERef &die_ref) override; + protected: DIEToTypePtr &GetDIEToType() override; @@ -76,8 +78,7 @@ protected: UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; - lldb::TypeSP - FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) override; + DWARFDIE FindDefinitionDIE(const DWARFDIE &die) override; lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE &die, |
