summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2024-07-08 19:19:54 +0700
committerKoakuma <koachan@protonmail.com>2024-07-08 19:19:54 +0700
commit5c4fdc2fd5898ebd9e89999a4f4b8aa289ca637f (patch)
treef3b92a07f3dfc6e70f36d1000605f36a3c15af46 /lldb/source/Plugins/SymbolFile
parentdbda8e2f2cd8764e0badd983915d62a2c3377f4d (diff)
parente9b8cd0c806db00f0981fb36717077c941426302 (diff)
Created using spr 1.3.5 [skip ci]
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp844
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h55
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp98
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp73
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h9
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp18
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h18
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp98
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h30
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp349
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h16
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp11
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h5
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,