[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
Thu May 2 11:11:10 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/3] [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/3] fix format
---
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5a317db7e74028..c7069550ccf702 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1689,12 +1689,10 @@ DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
// and this DIE isn't the complete definition (we checked
// is_complete_objc_class above and know it is false), so the real
// definition is in here somewhere
- type_sp =
- FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+ type_sp = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile =
- GetDebugMapSymfile();
+ SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
// We weren't able to find a full declaration in this DWARF,
// see if we have a declaration anywhere else...
>From c0a539ec9b3b468e5568cd6f569f51663fdafcac Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Thu, 2 May 2024 14:08:11 -0400
Subject: [PATCH 3/3] address comments
---
.../Plugins/SymbolFile/DWARF/DWARFASTParser.h | 6 +
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 166 ++++++++++++++----
.../SymbolFile/DWARF/DWARFASTParserClang.h | 10 ++
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 146 ++++-----------
.../SymbolFile/DWARF/SymbolFileDWARF.h | 10 --
.../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 5 -
.../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 2 -
7 files changed, 179 insertions(+), 166 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 66db396279e063..14b9cba05d3215 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -60,6 +60,12 @@ class DWARFASTParser {
virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0;
+ // Return true if we found the definition DIE for it. is_forward_declaration
+ // is set to true if the parameter die is a declaration.
+ virtual bool
+ FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
+ bool &is_forward_declaration) = 0;
+
static std::optional<SymbolFile::ArrayInfo>
ParseChildArrayInfo(const DWARFDIE &parent_die,
const ExecutionContext *exe_ctx = nullptr);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 7ad661c9a9d49b..8a8c303e1a8b2d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -154,6 +154,27 @@ static bool TagIsRecordType(dw_tag_t tag) {
}
}
+static bool
+IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die,
+ const ParsedDWARFTypeAttributes &attrs,
+ LanguageType cu_language) {
+ if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
+ !die.HasChildren() && cu_language == eLanguageTypeObjC) {
+ // Work around an issue with clang at the moment where forward
+ // declarations for objective C classes are emitted as:
+ // DW_TAG_structure_type [2]
+ // DW_AT_name( "ForwardObjcClass" )
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_decl_file( "..." )
+ // DW_AT_decl_line( 1 )
+ //
+ // Note that there is no DW_AT_declaration and there are no children,
+ // and the byte size is zero.
+ return true;
+ }
+ return attrs.is_forward_declaration;
+}
+
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
const DWARFDIE &die,
Log *log) {
@@ -249,12 +270,10 @@ static void ForcefullyCompleteType(CompilerType type) {
/// This function serves a similar purpose as RequireCompleteType above, but it
/// avoids completing the type if it is not immediately necessary. It only
/// ensures we _can_ complete the type later.
-static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
- ClangASTImporter &ast_importer,
- clang::DeclContext *decl_ctx,
- const DWARFDIE &decl_ctx_die,
- const DWARFDIE &die,
- const char *type_name_cstr) {
+void DWARFASTParserClang::PrepareContextToReceiveMembers(
+ TypeSystemClang &ast, clang::DeclContext *decl_ctx,
+ const DWARFDIE &decl_ctx_die, const DWARFDIE &die,
+ const char *type_name_cstr) {
auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
if (!tag_decl_ctx)
return; // Non-tag context are always ready.
@@ -270,6 +289,7 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
// If this type was not imported from an external AST, there's nothing to do.
CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
+ ClangASTImporter &ast_importer = GetClangASTImporter();
if (type && ast_importer.CanImport(type)) {
auto qual_type = ClangUtil::GetQualType(type);
if (ast_importer.RequireCompleteType(qual_type))
@@ -284,7 +304,8 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
// 1. Found the the definition DIE and start its definition with
// TypeSystemClang::StartTagDeclarationDefinition.
// 2. Unable to find it, then need to forcefully complete it.
- die.GetDWARF()->FindDefinitionDIE(decl_ctx_die);
+ bool is_forward_declaration = false;
+ FindDefinitionDIE(decl_ctx_die, is_forward_declaration);
if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
return;
// We don't have a type definition and/or the import failed. We must
@@ -631,8 +652,8 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
DWARFDIE decl_ctx_die;
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, &decl_ctx_die);
- PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
- decl_ctx_die, die, attrs.name.GetCString());
+ PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+ attrs.name.GetCString());
if (attrs.type.IsValid()) {
// Try to parse a typedef from the (DWARF embedded in the) Clang
@@ -1648,6 +1669,96 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
return qualified_name;
}
+bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die,
+ bool &is_forward_declaration) {
+ ParsedDWARFTypeAttributes attrs(die);
+ is_forward_declaration = IsForwardDeclaration(
+ die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU()));
+ if (!is_forward_declaration)
+ return true;
+
+ const dw_tag_t tag = die.Tag();
+ TypeSP type_sp;
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration DIE, trying to find definition DIE",
+ static_cast<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 =
+ dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile =
+ dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
+ die, attrs.name, true);
+ }
+ }
+
+ if (type_sp && log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
+ "\"{3}\" is an "
+ "incomplete objc type, complete type is {4:x8}",
+ static_cast<void *>(this), die.GetOffset(),
+ DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+ type_sp->GetID());
+ }
+ }
+ }
+
+ type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF, see
+ // if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
+ }
+ if (type_sp && log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration, complete type is {4:x8}",
+ static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+ attrs.name.GetCString(), type_sp->GetID());
+ }
+ }
+ if (type_sp)
+ return true;
+
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+ "forward declaration, unable to find definition DIE for it",
+ static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+ attrs.name.GetCString());
+ }
+ return false;
+}
+
TypeSP
DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
const DWARFDIE &die,
@@ -1668,6 +1779,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
ConstString unique_typename(attrs.name);
Declaration unique_decl(attrs.decl);
uint64_t byte_size = attrs.byte_size.value_or(0);
+ attrs.is_forward_declaration = IsForwardDeclaration(die, attrs, cu_language);
if (attrs.name) {
if (Language::LanguageIsCPlusPlus(cu_language)) {
@@ -1689,8 +1801,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
LinkDeclContextToDIE(
GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
if (!attrs.is_forward_declaration) {
- dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(
- unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef());
// If the parameter DIE is definition and the entry in the map is
// declaration, then we need to update the entry to point to the
// definition DIE.
@@ -1703,10 +1813,18 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
// it's used in ParseSubroutine to determine if we need to copy cxx
// method types from a declaration DIE to this definition DIE.
type_sp->SetID(die.GetID());
+ clang_type = type_sp->GetForwardCompilerType();
if (attrs.class_language != eLanguageTypeObjC &&
attrs.class_language != eLanguageTypeObjC_plus_plus)
- TypeSystemClang::StartTagDeclarationDefinition(
- type_sp->GetForwardCompilerType());
+ TypeSystemClang::StartTagDeclarationDefinition(clang_type);
+
+ CompilerType compiler_type_no_qualifiers =
+ ClangUtil::RemoveFastQualifiers(clang_type);
+ auto result = dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
+ compiler_type_no_qualifiers.GetOpaqueQualType(),
+ *die.GetDIERef());
+ if (!result.second)
+ result.first->second = *die.GetDIERef();
}
}
return type_sp;
@@ -1730,21 +1848,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
default_accessibility = eAccessPrivate;
}
- if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
- !die.HasChildren() && cu_language == eLanguageTypeObjC) {
- // Work around an issue with clang at the moment where forward
- // declarations for objective C classes are emitted as:
- // DW_TAG_structure_type [2]
- // DW_AT_name( "ForwardObjcClass" )
- // DW_AT_byte_size( 0x00 )
- // DW_AT_decl_file( "..." )
- // DW_AT_decl_line( 1 )
- //
- // Note that there is no DW_AT_declaration and there are no children,
- // and the byte size is zero.
- attrs.is_forward_declaration = true;
- }
-
if (attrs.is_forward_declaration) {
// See if the type comes from a Clang module and if so, track down
// that type.
@@ -1759,8 +1862,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, &decl_ctx_die);
- PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
- decl_ctx_die, die, attrs.name.GetCString());
+ PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+ attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
// Check the decl context that contains this class/struct/union. If
@@ -1809,9 +1912,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,
attrs.exports_symbols);
}
- if (!attrs.is_forward_declaration)
- dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(),
- *die.GetDIERef());
// Store a forward declaration to this class type in case any
// parameters in any class methods need it for the clang types for
// function prototypes.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 8d4af203bb2871..b884d6869add84 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -108,6 +108,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
lldb_private::ConstString GetDIEClassTemplateParams(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+ bool FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
+ bool &is_forward_declaration) override;
+
protected:
/// Protected typedefs and members.
/// @{
@@ -246,6 +249,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
lldb::ModuleSP
GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die);
+ void PrepareContextToReceiveMembers(
+ lldb_private::TypeSystemClang &ast,
+ clang::DeclContext *decl_ctx,
+ const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die,
+ const lldb_private::plugin::dwarf::DWARFDIE &die,
+ const char *type_name_cstr);
+
static bool classof(const DWARFASTParser *Parser) {
return Parser->GetKind() == Kind::DWARFASTParserClang;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c7069550ccf702..d2f66b00c17941 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1631,126 +1631,40 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
return true;
}
- DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond()));
- if (dwarf_die) {
- // Once we start resolving this type, remove it from the forward
- // declaration map in case anyone child members or other types require this
- // type to get resolved. The type will get resolved when all of the calls
- // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
- // Need to get a new iterator because FindDefinitionDIE might add new
- // entries into the map and invalidate previous iterator.
- auto die_it = GetForwardDeclCompilerTypeToDIE().find(
- compiler_type_no_qualifiers.GetOpaqueQualType());
- if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
- GetForwardDeclCompilerTypeToDIE().erase(die_it);
- }
-
- Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
+ // Once we start resolving this type, remove it from the forward
+ // declaration map in case anyone child members or other types require this
+ // type to get resolved.
+ DWARFDIE dwarf_die = GetDIE(die_it->second);
+ GetForwardDeclCompilerTypeToDIE().erase(die_it);
+ // The DWARFASTParser might determine if this is a declaration or not with
+ // information other than DW_AT_declaration depending on the language.
+ bool is_forward_declaration = false;
+ bool found_def_die = false;
+ if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
+ found_def_die =
+ dwarf_ast->FindDefinitionDIE(dwarf_die, is_forward_declaration);
+ if (!found_def_die)
+ return false;
- Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
- if (log)
- GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
- log, "{0:x8}: {1} '{2}' resolving forward declaration...",
- dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
- type->GetName().AsCString());
- assert(compiler_type);
- if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
- return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
+ die_it = GetForwardDeclCompilerTypeToDIE().find(
+ compiler_type_no_qualifiers.GetOpaqueQualType());
+ if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
+ dwarf_die = GetDIE(die_it->getSecond());
+ GetForwardDeclCompilerTypeToDIE().erase(die_it);
}
- return false;
-}
-DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
- auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
- if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
- return GetDIE(def_die_it->getSecond());
+ Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
- ParsedDWARFTypeAttributes attrs(die);
- const dw_tag_t tag = die.Tag();
- TypeSP type_sp;
- Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
- if (log) {
- GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
- "forward declaration DIE, trying to find definition DIE",
- static_cast<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();
+ Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
+ if (log)
+ GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log, "{0:x8}: {1} '{2}' resolving forward declaration...",
+ dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
+ type->GetName().AsCString());
+ assert(compiler_type);
+ if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
+ return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
+ return true;
}
Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 86d5a3d4f6c46d..94aa810680c52c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -182,8 +182,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
void FindFunctions(const RegularExpression ®ex, bool include_inlines,
SymbolContextList &sc_list) override;
- DWARFDIE FindDefinitionDIE(const DWARFDIE &die);
-
void
GetMangledNamesForFunction(const std::string &scope_qualified_name,
std::vector<ConstString> &mangled_names) override;
@@ -344,11 +342,6 @@ 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;
@@ -547,9 +540,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
// A map from CompilerType to the struct/class/union/enum DIE (might be a
// declaration or a definition) that is used to construct it.
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
- // A map from a struct/class/union/enum DIE (might be a declaration or a
- // definition) to its definition DIE.
- DIEToDIE m_die_to_def_die;
llvm::DenseMap<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 cb5ec4ae026b3d..85e1afd0d89761 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -110,11 +110,6 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
return GetBaseSymbolFile().GetDIEToVariable();
}
-SymbolFileDWARF::DIEToDIE &
-SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() {
- return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE();
-}
-
SymbolFileDWARF::CompilerTypeToDIE &
SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 3e8cfb885aaee9..1500540424b524 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -74,8 +74,6 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
- DIEToDIE &GetDeclarationDIEToDefinitionDIE() override;
-
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
lldb::TypeSP
More information about the lldb-commits
mailing list