[Lldb-commits] [lldb] [lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. (PR #90663)
Zequan Wu via lldb-commits
lldb-commits at lists.llvm.org
Wed May 1 07:25:59 PDT 2024
https://github.com/ZequanWu updated https://github.com/llvm/llvm-project/pull/90663
>From 4e800003099b593e66f12dc21be5fbac5279e03e Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 30 Apr 2024 16:23:11 -0400
Subject: [PATCH 1/2] [lldb][DWARF] Delay struct/class/union definition DIE
searching when parsing declaration DIEs.
---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 270 +++++++-----------
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 105 ++++++-
.../SymbolFile/DWARF/SymbolFileDWARF.h | 14 +
.../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 5 +
.../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 2 +
.../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 95 +++---
.../SymbolFile/DWARF/UniqueDWARFASTType.h | 21 +-
7 files changed, 296 insertions(+), 216 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index bea11e0e3840af..7ad661c9a9d49b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -252,7 +252,8 @@ static void ForcefullyCompleteType(CompilerType type) {
static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
ClangASTImporter &ast_importer,
clang::DeclContext *decl_ctx,
- DWARFDIE die,
+ const DWARFDIE &decl_ctx_die,
+ const DWARFDIE &die,
const char *type_name_cstr) {
auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
if (!tag_decl_ctx)
@@ -279,6 +280,13 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
type_name_cstr ? type_name_cstr : "", die.GetOffset());
}
+ // By searching for the definition DIE of the decl_ctx type, we will either:
+ // 1. Found the the definition DIE and start its definition with
+ // TypeSystemClang::StartTagDeclarationDefinition.
+ // 2. Unable to find it, then need to forcefully complete it.
+ die.GetDWARF()->FindDefinitionDIE(decl_ctx_die);
+ if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
+ return;
// We don't have a type definition and/or the import failed. We must
// forcefully complete the type to avoid crashes.
ForcefullyCompleteType(type);
@@ -620,10 +628,11 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
if (tag == DW_TAG_typedef) {
// DeclContext will be populated when the clang type is materialized in
// Type::ResolveCompilerType.
- PrepareContextToReceiveMembers(
- m_ast, GetClangASTImporter(),
- GetClangDeclContextContainingDIE(die, nullptr), die,
- attrs.name.GetCString());
+ DWARFDIE decl_ctx_die;
+ clang::DeclContext *decl_ctx =
+ GetClangDeclContextContainingDIE(die, &decl_ctx_die);
+ PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
+ decl_ctx_die, die, attrs.name.GetCString());
if (attrs.type.IsValid()) {
// Try to parse a typedef from the (DWARF embedded in the) Clang
@@ -1100,32 +1109,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
// struct and see if this is actually a C++ method
Type *class_type = dwarf->ResolveType(decl_ctx_die);
if (class_type) {
- if (class_type->GetID() != decl_ctx_die.GetID() ||
- IsClangModuleFwdDecl(decl_ctx_die)) {
-
- // We uniqued the parent class of this function to another
- // class so we now need to associate all dies under
- // "decl_ctx_die" to DIEs in the DIE for "class_type"...
- DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
-
- if (class_type_die) {
- std::vector<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();
- }
- }
- }
-
if (attrs.specification.IsValid()) {
// We have a specification which we are going to base our
// function prototype off of, so we need this type to be
@@ -1260,6 +1243,39 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
}
}
}
+ // By here, we should have already completed the c++ class_type
+ // because if either specification or abstract_origin is present, we
+ // call GetClangDeclContextForDIE to resolve the DW_TAG_subprogram
+ // refered by this one until we reached the DW_TAG_subprogram without
+ // specification or abstract_origin (the else branch above). Then the
+ // above GetFullCompilerType() will complete the class_type if it's
+ // not completed yet. After that, we will have the mapping from DIEs
+ // in class_type_die to DeclContexts in m_die_to_decl_ctx.
+ if (class_type->GetID() != decl_ctx_die.GetID() ||
+ IsClangModuleFwdDecl(decl_ctx_die)) {
+
+ // We uniqued the parent class of this function to another
+ // class so we now need to associate all dies under
+ // "decl_ctx_die" to DIEs in the DIE for "class_type"...
+ DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
+
+ if (class_type_die) {
+ std::vector<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();
+ }
+ }
+ }
}
}
}
@@ -1651,6 +1667,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
ConstString unique_typename(attrs.name);
Declaration unique_decl(attrs.decl);
+ uint64_t byte_size = attrs.byte_size.value_or(0);
if (attrs.name) {
if (Language::LanguageIsCPlusPlus(cu_language)) {
@@ -1664,13 +1681,34 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
}
if (dwarf->GetUniqueDWARFASTTypeMap().Find(
- unique_typename, die, unique_decl, attrs.byte_size.value_or(-1),
- *unique_ast_entry_up)) {
+ unique_typename, die, unique_decl, byte_size,
+ attrs.is_forward_declaration, *unique_ast_entry_up)) {
type_sp = unique_ast_entry_up->m_type_sp;
if (type_sp) {
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
LinkDeclContextToDIE(
GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
+ if (!attrs.is_forward_declaration) {
+ dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(
+ unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef());
+ // If the parameter DIE is definition and the entry in the map is
+ // declaration, then we need to update the entry to point to the
+ // definition DIE.
+ if (unique_ast_entry_up->m_is_forward_declaration) {
+ unique_ast_entry_up->m_die = die;
+ unique_ast_entry_up->m_byte_size = byte_size;
+ unique_ast_entry_up->m_declaration = unique_decl;
+ unique_ast_entry_up->m_is_forward_declaration = false;
+ // Need to update Type ID to refer to the definition DIE. because
+ // it's used in ParseSubroutine to determine if we need to copy cxx
+ // method types from a declaration DIE to this definition DIE.
+ type_sp->SetID(die.GetID());
+ if (attrs.class_language != eLanguageTypeObjC &&
+ attrs.class_language != eLanguageTypeObjC_plus_plus)
+ TypeSystemClang::StartTagDeclarationDefinition(
+ type_sp->GetForwardCompilerType());
+ }
+ }
return type_sp;
}
}
@@ -1707,112 +1745,22 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
attrs.is_forward_declaration = true;
}
- if (attrs.class_language == eLanguageTypeObjC ||
- attrs.class_language == eLanguageTypeObjC_plus_plus) {
- if (!attrs.is_complete_objc_class &&
- die.Supports_DW_AT_APPLE_objc_complete_type()) {
- // We have a valid eSymbolTypeObjCClass class symbol whose name
- // matches the current objective C class that we are trying to find
- // and this DIE isn't the complete definition (we checked
- // is_complete_objc_class above and know it is false), so the real
- // definition is in here somewhere
- type_sp =
- dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
-
- if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile =
- dwarf->GetDebugMapSymfile();
- if (debug_map_symfile) {
- // We weren't able to find a full declaration in this DWARF,
- // see if we have a declaration anywhere else...
- type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
- die, attrs.name, true);
- }
- }
-
- if (type_sp) {
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
- "\"{3}\" is an "
- "incomplete objc type, complete type is {4:x8}",
- static_cast<void *>(this), die.GetOffset(),
- DW_TAG_value_to_name(tag), attrs.name.GetCString(),
- type_sp->GetID());
- }
-
- // We found a real definition for this type elsewhere so lets use
- // it and cache the fact that we found a complete type for this
- // die
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- return type_sp;
- }
- }
- }
-
if (attrs.is_forward_declaration) {
- // We have a forward declaration to a type and we need to try and
- // find a full declaration. We look in the current type index just in
- // case we have a forward declaration followed by an actual
- // declarations in the DWARF. If this fails, we need to look
- // elsewhere...
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
- "forward declaration, trying to find complete type",
- static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
- attrs.name.GetCString());
- }
-
// See if the type comes from a Clang module and if so, track down
// that type.
type_sp = ParseTypeFromClangModule(sc, die, log);
if (type_sp)
return type_sp;
-
- // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
- // type_name_const_str);
- type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
-
- if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
- if (debug_map_symfile) {
- // We weren't able to find a full declaration in this DWARF, see
- // if we have a declaration anywhere else...
- type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
- }
- }
-
- if (type_sp) {
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
- "forward declaration, complete type is {4:x8}",
- static_cast<void *>(this), die.GetOffset(),
- DW_TAG_value_to_name(tag), attrs.name.GetCString(),
- type_sp->GetID());
- }
-
- // We found a real definition for this type elsewhere so lets use
- // it and cache the fact that we found a complete type for this die
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- clang::DeclContext *defn_decl_ctx =
- GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
- if (defn_decl_ctx)
- LinkDeclContextToDIE(defn_decl_ctx, die);
- return type_sp;
- }
}
+
assert(tag_decl_kind != -1);
UNUSED_IF_ASSERT_DISABLED(tag_decl_kind);
- bool clang_type_was_created = false;
- clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
+ DWARFDIE decl_ctx_die;
+ clang::DeclContext *decl_ctx =
+ GetClangDeclContextContainingDIE(die, &decl_ctx_die);
- PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die,
- attrs.name.GetCString());
+ PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
+ decl_ctx_die, die, attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
// Check the decl context that contains this class/struct/union. If
@@ -1850,20 +1798,20 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
tag_decl_kind, template_param_infos);
clang_type =
m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
- clang_type_was_created = true;
m_ast.SetMetadata(class_template_decl, metadata);
m_ast.SetMetadata(class_specialization_decl, metadata);
}
- if (!clang_type_was_created) {
- clang_type_was_created = true;
+ if (!clang_type) {
clang_type = m_ast.CreateRecordType(
decl_ctx, GetOwningClangModule(die), attrs.accessibility,
attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,
attrs.exports_symbols);
}
-
+ if (!attrs.is_forward_declaration)
+ dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(),
+ *die.GetDIERef());
// Store a forward declaration to this class type in case any
// parameters in any class methods need it for the clang types for
// function prototypes.
@@ -1880,7 +1828,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
unique_ast_entry_up->m_type_sp = type_sp;
unique_ast_entry_up->m_die = die;
unique_ast_entry_up->m_declaration = unique_decl;
- unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0);
+ unique_ast_entry_up->m_byte_size = byte_size;
+ unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration;
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
*unique_ast_entry_up);
@@ -1921,38 +1870,33 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
GetClangASTImporter().SetRecordLayout(record_decl, layout);
}
}
- } else if (clang_type_was_created) {
- // Start the definition if the class is not objective C since the
- // underlying decls respond to isCompleteDefinition(). Objective
- // C decls don't respond to isCompleteDefinition() so we can't
- // start the declaration definition right away. For C++
- // class/union/structs we want to start the definition in case the
- // class is needed as the declaration context for a contained class
- // or type without the need to complete that type..
-
- if (attrs.class_language != eLanguageTypeObjC &&
- attrs.class_language != eLanguageTypeObjC_plus_plus)
- TypeSystemClang::StartTagDeclarationDefinition(clang_type);
-
- // Leave this as a forward declaration until we need to know the
- // details of the type. lldb_private::Type will automatically call
- // the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)" When the definition
- // needs to be defined.
- assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
- ClangUtil::RemoveFastQualifiers(clang_type)
- .GetOpaqueQualType()) &&
- "Type already in the forward declaration map!");
- // Can't assume m_ast.GetSymbolFile() is actually a
- // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
- // binaries.
- dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
- ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
- *die.GetDIERef());
- m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
}
+ // Start the definition if the class is not objective C since the
+ // underlying decls respond to isCompleteDefinition(). Objective
+ // C decls don't respond to isCompleteDefinition() so we can't
+ // start the declaration definition right away. For C++
+ // class/union/structs we want to start the definition in case the
+ // class is needed as the declaration context for a contained class
+ // or type without the need to complete that type..
+
+ if (attrs.class_language != eLanguageTypeObjC &&
+ attrs.class_language != eLanguageTypeObjC_plus_plus)
+ TypeSystemClang::StartTagDeclarationDefinition(clang_type);
}
+ // Leave this as a forward declaration until we need to know the
+ // details of the type. lldb_private::Type will automatically call
+ // the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+ // needs to be defined.
+ assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
+ ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
+ "Type already in the forward declaration map!");
+ dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
+ ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
+ *die.GetDIERef());
+ m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+
// If we made a clang type, set the trivial abi if applicable: We only
// do this for pass by value - which implies the Trivial ABI. There
// isn't a way to assert that something that would normally be pass by
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 49f13d2c89e380..5a317db7e74028 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1631,13 +1631,19 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
return true;
}
- DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
+ DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond()));
if (dwarf_die) {
// Once we start resolving this type, remove it from the forward
// declaration map in case anyone child members or other types require this
// type to get resolved. The type will get resolved when all of the calls
// to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
- GetForwardDeclCompilerTypeToDIE().erase(die_it);
+ // Need to get a new iterator because FindDefinitionDIE might add new
+ // entries into the map and invalidate previous iterator.
+ auto die_it = GetForwardDeclCompilerTypeToDIE().find(
+ compiler_type_no_qualifiers.GetOpaqueQualType());
+ if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
+ GetForwardDeclCompilerTypeToDIE().erase(die_it);
+ }
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
@@ -1654,6 +1660,101 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
return false;
}
+DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
+ auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
+ if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
+ return GetDIE(def_die_it->getSecond());
+
+ ParsedDWARFTypeAttributes attrs(die);
+ const dw_tag_t tag = die.Tag();
+ TypeSP type_sp;
+ Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+ if (log) {
+ GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration DIE, trying to find definition DIE",
+ static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+ attrs.name.GetCString());
+ }
+ // We haven't parse definition die for this type, starting to search for it.
+ // After we found the definition die, the GetDeclarationDIEToDefinitionDIE()
+ // map will have the new mapping from this declaration die to definition die.
+ if (attrs.class_language == eLanguageTypeObjC ||
+ attrs.class_language == eLanguageTypeObjC_plus_plus) {
+ if (!attrs.is_complete_objc_class &&
+ die.Supports_DW_AT_APPLE_objc_complete_type()) {
+ // We have a valid eSymbolTypeObjCClass class symbol whose name
+ // matches the current objective C class that we are trying to find
+ // and this DIE isn't the complete definition (we checked
+ // is_complete_objc_class above and know it is false), so the real
+ // definition is in here somewhere
+ type_sp =
+ FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile =
+ GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
+ die, attrs.name, true);
+ }
+ }
+
+ if (type_sp && log) {
+ GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
+ "\"{3}\" is an "
+ "incomplete objc type, complete type is {4:x8}",
+ static_cast<void *>(this), die.GetOffset(),
+ DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+ type_sp->GetID());
+ }
+ }
+ }
+ bool is_forward_declaration =
+ attrs.is_forward_declaration ||
+ (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
+ !die.HasChildren() &&
+ SymbolFileDWARF::GetLanguage(*die.GetCU()) == eLanguageTypeObjC);
+ if (is_forward_declaration) {
+ type_sp = FindDefinitionTypeForDWARFDeclContext(die);
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF, see
+ // if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
+ }
+ if (type_sp && log) {
+ GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration, complete type is {4:x8}",
+ static_cast<void *>(this), die.GetOffset(),
+ DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+ type_sp->GetID());
+ }
+ }
+ }
+ def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
+ if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
+ return GetDIE(def_die_it->getSecond());
+
+ if (log) {
+ GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration, unable to find definition DIE for it",
+ static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+ attrs.name.GetCString());
+ }
+ return DWARFDIE();
+}
+
Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
bool assert_not_being_parsed,
bool resolve_function_context) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 7282c08c6857c9..86d5a3d4f6c46d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -182,6 +182,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
void FindFunctions(const RegularExpression ®ex, bool include_inlines,
SymbolContextList &sc_list) override;
+ DWARFDIE FindDefinitionDIE(const DWARFDIE &die);
+
void
GetMangledNamesForFunction(const std::string &scope_qualified_name,
std::vector<ConstString> &mangled_names) override;
@@ -342,6 +344,11 @@ class SymbolFileDWARF : public SymbolFileCommon {
return m_forward_decl_compiler_type_to_die;
}
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, DIERef> DIEToDIE;
+ virtual DIEToDIE &GetDeclarationDIEToDefinitionDIE() {
+ return m_die_to_def_die;
+ }
+
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
DIEToVariableSP;
@@ -533,9 +540,16 @@ class SymbolFileDWARF : public SymbolFileCommon {
NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
+ // A map from DIE to lldb_private::Type. For record type, the key might be
+ // either declaration DIE or definition DIE.
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
+ // A map from CompilerType to the struct/class/union/enum DIE (might be a
+ // declaration or a definition) that is used to construct it.
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
+ // A map from a struct/class/union/enum DIE (might be a declaration or a
+ // definition) to its definition DIE.
+ DIEToDIE m_die_to_def_die;
llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
m_type_unit_support_files;
std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 85e1afd0d89761..cb5ec4ae026b3d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -110,6 +110,11 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
return GetBaseSymbolFile().GetDIEToVariable();
}
+SymbolFileDWARF::DIEToDIE &
+SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() {
+ return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE();
+}
+
SymbolFileDWARF::CompilerTypeToDIE &
SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 1500540424b524..3e8cfb885aaee9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -74,6 +74,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
+ DIEToDIE &GetDeclarationDIEToDefinitionDIE() override;
+
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
lldb::TypeSP
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 223518f0ae8241..cc23bb86f6805a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -16,60 +16,65 @@ using namespace lldb_private::plugin::dwarf;
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
+ bool is_forward_declaration,
UniqueDWARFASTType &entry) const {
for (const UniqueDWARFASTType &udt : m_collection) {
// Make sure the tags match
if (udt.m_die.Tag() == die.Tag()) {
- // Validate byte sizes of both types only if both are valid.
- if (udt.m_byte_size < 0 || byte_size < 0 ||
- udt.m_byte_size == byte_size) {
- // Make sure the file and line match
- if (udt.m_declaration == decl) {
- // The type has the same name, and was defined on the same file and
- // line. Now verify all of the parent DIEs match.
- DWARFDIE parent_arg_die = die.GetParent();
- DWARFDIE parent_pos_die = udt.m_die.GetParent();
- bool match = true;
- bool done = false;
- while (!done && match && parent_arg_die && parent_pos_die) {
- const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
- const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
- if (parent_arg_tag == parent_pos_tag) {
- switch (parent_arg_tag) {
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_namespace: {
- const char *parent_arg_die_name = parent_arg_die.GetName();
- if (parent_arg_die_name ==
- nullptr) // Anonymous (i.e. no-name) struct
- {
+ // If they are not both definition DIEs or both declaration DIEs, then
+ // don't check for byte size and declaration location, because declaration
+ // DIEs usually don't have those info.
+ bool matching_size_declaration =
+ udt.m_is_forward_declaration != is_forward_declaration
+ ? true
+ : (udt.m_byte_size < 0 || byte_size < 0 ||
+ udt.m_byte_size == byte_size) &&
+ udt.m_declaration == decl;
+ if (matching_size_declaration) {
+ // The type has the same name, and was defined on the same file and
+ // line. Now verify all of the parent DIEs match.
+ DWARFDIE parent_arg_die = die.GetParent();
+ DWARFDIE parent_pos_die = udt.m_die.GetParent();
+ bool match = true;
+ bool done = false;
+ while (!done && match && parent_arg_die && parent_pos_die) {
+ const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
+ const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
+ if (parent_arg_tag == parent_pos_tag) {
+ switch (parent_arg_tag) {
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_namespace: {
+ const char *parent_arg_die_name = parent_arg_die.GetName();
+ if (parent_arg_die_name ==
+ nullptr) // Anonymous (i.e. no-name) struct
+ {
+ match = false;
+ } else {
+ const char *parent_pos_die_name = parent_pos_die.GetName();
+ if (parent_pos_die_name == nullptr ||
+ ((parent_arg_die_name != parent_pos_die_name) &&
+ strcmp(parent_arg_die_name, parent_pos_die_name)))
match = false;
- } else {
- const char *parent_pos_die_name = parent_pos_die.GetName();
- if (parent_pos_die_name == nullptr ||
- ((parent_arg_die_name != parent_pos_die_name) &&
- strcmp(parent_arg_die_name, parent_pos_die_name)))
- match = false;
- }
- } break;
-
- case DW_TAG_compile_unit:
- case DW_TAG_partial_unit:
- done = true;
- break;
- default:
- break;
}
+ } break;
+
+ case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
+ done = true;
+ break;
+ default:
+ break;
}
- parent_arg_die = parent_arg_die.GetParent();
- parent_pos_die = parent_pos_die.GetParent();
}
+ parent_arg_die = parent_arg_die.GetParent();
+ parent_pos_die = parent_pos_die.GetParent();
+ }
- if (match) {
- entry = udt;
- return true;
- }
+ if (match) {
+ entry = udt;
+ return true;
}
}
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index bf3cbae55e5c7b..94619953d07ac5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -24,13 +24,16 @@ class UniqueDWARFASTType {
UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
- const Declaration &decl, int32_t byte_size)
+ const Declaration &decl, int32_t byte_size,
+ bool is_forward_declaration)
: m_type_sp(type_sp), m_die(die), m_declaration(decl),
- m_byte_size(byte_size) {}
+ m_byte_size(byte_size),
+ m_is_forward_declaration(is_forward_declaration) {}
UniqueDWARFASTType(const UniqueDWARFASTType &rhs)
: m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
- m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
+ m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size),
+ m_is_forward_declaration(rhs.m_is_forward_declaration) {}
~UniqueDWARFASTType() = default;
@@ -40,6 +43,7 @@ class UniqueDWARFASTType {
m_die = rhs.m_die;
m_declaration = rhs.m_declaration;
m_byte_size = rhs.m_byte_size;
+ m_is_forward_declaration = rhs.m_is_forward_declaration;
}
return *this;
}
@@ -48,6 +52,8 @@ class UniqueDWARFASTType {
DWARFDIE m_die;
Declaration m_declaration;
int32_t m_byte_size = -1;
+ // True if the m_die is a forward declaration DIE.
+ bool m_is_forward_declaration = true;
};
class UniqueDWARFASTTypeList {
@@ -63,7 +69,8 @@ class UniqueDWARFASTTypeList {
}
bool Find(const DWARFDIE &die, const Declaration &decl,
- const int32_t byte_size, UniqueDWARFASTType &entry) const;
+ const int32_t byte_size, bool is_forward_declaration,
+ UniqueDWARFASTType &entry) const;
protected:
typedef std::vector<UniqueDWARFASTType> collection;
@@ -81,11 +88,13 @@ class UniqueDWARFASTTypeMap {
}
bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl,
- const int32_t byte_size, UniqueDWARFASTType &entry) const {
+ const int32_t byte_size, bool is_forward_declaration,
+ UniqueDWARFASTType &entry) const {
const char *unique_name_cstr = name.GetCString();
collection::const_iterator pos = m_collection.find(unique_name_cstr);
if (pos != m_collection.end()) {
- return pos->second.Find(die, decl, byte_size, entry);
+ return pos->second.Find(die, decl, byte_size, is_forward_declaration,
+ entry);
}
return false;
}
>From 751a58d24ec9e32234d2bfa672f51d255bfd78fa Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 1 May 2024 10:25:28 -0400
Subject: [PATCH 2/2] fix format
---
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5a317db7e74028..c7069550ccf702 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1689,12 +1689,10 @@ DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
// and this DIE isn't the complete definition (we checked
// is_complete_objc_class above and know it is false), so the real
// definition is in here somewhere
- type_sp =
- FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+ type_sp = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile =
- GetDebugMapSymfile();
+ SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
// We weren't able to find a full declaration in this DWARF,
// see if we have a declaration anywhere else...
More information about the lldb-commits
mailing list