Skip to content

Commit b7b77b0

Browse files
authored
Reapply [lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. (#98361)
This is a reapply of #92328 and #93839. It now passes the [test](de3f1b6), which crashes with the original reverted changes.
1 parent f2d6d74 commit b7b77b0

11 files changed

+366
-293
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

+151-180
Large diffs are not rendered by default.

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
109109
std::string GetDIEClassTemplateParams(
110110
const lldb_private::plugin::dwarf::DWARFDIE &die) override;
111111

112+
void MapDeclDIEToDefDIE(const lldb_private::plugin::dwarf::DWARFDIE &decl_die,
113+
const lldb_private::plugin::dwarf::DWARFDIE &def_die);
114+
112115
protected:
113116
/// Protected typedefs and members.
114117
/// @{
@@ -168,8 +171,10 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
168171
lldb_private::TypeSystemClang::TemplateParameterInfos
169172
&template_param_infos);
170173

171-
std::string
172-
GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die);
174+
void GetUniqueTypeNameAndDeclaration(
175+
const lldb_private::plugin::dwarf::DWARFDIE &die,
176+
lldb::LanguageType language, lldb_private::ConstString &unique_typename,
177+
lldb_private::Declaration &decl_declaration);
173178

174179
bool ParseChildMembers(
175180
const lldb_private::plugin::dwarf::DWARFDIE &die,

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

+55-23
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,13 @@ static ConstString GetDWARFMachOSegmentName() {
481481
return g_dwarf_section_name;
482482
}
483483

484+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
485+
SymbolFileDWARF::GetForwardDeclCompilerTypeToDIE() {
486+
if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
487+
return debug_map_symfile->GetForwardDeclCompilerTypeToDIE();
488+
return m_forward_decl_compiler_type_to_die;
489+
}
490+
484491
UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() {
485492
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
486493
if (debug_map_symfile)
@@ -1631,27 +1638,45 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
16311638
return true;
16321639
}
16331640

1634-
DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
1635-
if (dwarf_die) {
1636-
// Once we start resolving this type, remove it from the forward
1637-
// declaration map in case anyone child members or other types require this
1638-
// type to get resolved. The type will get resolved when all of the calls
1639-
// to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
1640-
GetForwardDeclCompilerTypeToDIE().erase(die_it);
1641-
1642-
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
1641+
DWARFDIE decl_die = GetDIE(die_it->getSecond());
1642+
// Once we start resolving this type, remove it from the forward
1643+
// declaration map in case anyone's child members or other types require this
1644+
// type to get resolved.
1645+
GetForwardDeclCompilerTypeToDIE().erase(die_it);
1646+
DWARFDIE def_die = FindDefinitionDIE(decl_die);
1647+
if (!def_die) {
1648+
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
1649+
if (debug_map_symfile) {
1650+
// We weren't able to find a full declaration in this DWARF, see
1651+
// if we have a declaration anywhere else...
1652+
def_die = debug_map_symfile->FindDefinitionDIE(decl_die);
1653+
}
1654+
}
1655+
if (!def_die) {
1656+
// If we don't have definition DIE, CompleteTypeFromDWARF will forcefully
1657+
// complete this type.
1658+
def_die = decl_die;
1659+
}
16431660

1644-
Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
1645-
if (log)
1646-
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
1647-
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
1648-
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
1649-
dwarf_die.Tag(), type->GetName().AsCString());
1650-
assert(compiler_type);
1651-
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
1652-
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
1661+
DWARFASTParser *dwarf_ast = GetDWARFParser(*def_die.GetCU());
1662+
if (!dwarf_ast)
1663+
return false;
1664+
Type *type = GetDIEToType().lookup(decl_die.GetDIE());
1665+
if (decl_die != def_die) {
1666+
GetDIEToType()[def_die.GetDIE()] = type;
1667+
DWARFASTParserClang *ast_parser =
1668+
static_cast<DWARFASTParserClang *>(dwarf_ast);
1669+
ast_parser->MapDeclDIEToDefDIE(decl_die, def_die);
16531670
}
1654-
return false;
1671+
1672+
Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
1673+
if (log)
1674+
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
1675+
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
1676+
def_die.GetID(), DW_TAG_value_to_name(def_die.Tag()), def_die.Tag(),
1677+
type->GetName().AsCString());
1678+
assert(compiler_type);
1679+
return dwarf_ast->CompleteTypeFromDWARF(def_die, type, compiler_type);
16551680
}
16561681

16571682
Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
@@ -3047,8 +3072,15 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
30473072

30483073
DWARFDIE
30493074
SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
3050-
if (!die.GetName())
3075+
const char *name = die.GetName();
3076+
if (!name)
30513077
return {};
3078+
if (!die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
3079+
return die;
3080+
3081+
Progress progress(llvm::formatv(
3082+
"Searching definition DIE in {0}: '{1}'",
3083+
GetObjectFile()->GetFileSpec().GetFilename().GetString(), name));
30523084

30533085
const dw_tag_t tag = die.Tag();
30543086

@@ -3058,7 +3090,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
30583090
log,
30593091
"SymbolFileDWARF::FindDefinitionDIE(tag={0} "
30603092
"({1}), name='{2}')",
3061-
DW_TAG_value_to_name(tag), tag, die.GetName());
3093+
DW_TAG_value_to_name(tag), tag, name);
30623094
}
30633095

30643096
// Get the type system that we are looking to find a type for. We will
@@ -3132,7 +3164,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
31323164
log,
31333165
"SymbolFileDWARF::FindDefinitionDIE(tag={0} ({1}), "
31343166
"name='{2}') ignoring die={3:x16} ({4})",
3135-
DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(),
3167+
DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
31363168
type_die.GetName());
31373169
}
31383170
return true;
@@ -3144,7 +3176,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
31443176
log,
31453177
"SymbolFileDWARF::FindDefinitionTypeDIE(tag={0} ({1}), name='{2}') "
31463178
"trying die={3:x16} ({4})",
3147-
DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(),
3179+
DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
31483180
type_dwarf_decl_ctx.GetQualifiedName());
31493181
}
31503182

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h

+8-7
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
342342

343343
virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; }
344344

345-
typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
346-
CompilerTypeToDIE;
347-
348-
virtual CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() {
349-
return m_forward_decl_compiler_type_to_die;
350-
}
345+
virtual llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
346+
GetForwardDeclCompilerTypeToDIE();
351347

352348
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
353349
DIEToVariableSP;
@@ -537,9 +533,14 @@ class SymbolFileDWARF : public SymbolFileCommon {
537533
NameToOffsetMap m_function_scope_qualified_name_map;
538534
std::unique_ptr<DWARFDebugRanges> m_ranges;
539535
UniqueDWARFASTTypeMap m_unique_ast_type_map;
536+
// A map from DIE to lldb_private::Type. For record type, the key might be
537+
// either declaration DIE or definition DIE.
540538
DIEToTypePtr m_die_to_type;
541539
DIEToVariableSP m_die_to_variable_sp;
542-
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
540+
// A map from CompilerType to the struct/class/union/enum DIE (might be a
541+
// declaration or a definition) that is used to construct it.
542+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
543+
m_forward_decl_compiler_type_to_die;
543544
llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
544545
m_type_unit_support_files;
545546
std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h

+9
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
284284
lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE(
285285
const DWARFDIE &die, ConstString type_name, bool must_be_implementation);
286286

287+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
288+
GetForwardDeclCompilerTypeToDIE() {
289+
return m_forward_decl_compiler_type_to_die;
290+
}
291+
287292
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() {
288293
return m_unique_ast_type_map;
289294
}
@@ -321,6 +326,10 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
321326
std::vector<uint32_t> m_func_indexes; // Sorted by address
322327
std::vector<uint32_t> m_glob_indexes;
323328
std::map<std::pair<ConstString, llvm::sys::TimePoint<>>, OSOInfoSP> m_oso_map;
329+
// A map from CompilerType to the struct/class/union/enum DIE (might be a
330+
// declaration or a definition) that is used to construct it.
331+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
332+
m_forward_decl_compiler_type_to_die;
324333
UniqueDWARFASTTypeMap m_unique_ast_type_map;
325334
LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
326335
DebugMap m_debug_map;

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
110110
return GetBaseSymbolFile().GetDIEToVariable();
111111
}
112112

113-
SymbolFileDWARF::CompilerTypeToDIE &
113+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
114114
SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
115115
return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
116116
}

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
7474

7575
DIEToVariableSP &GetDIEToVariable() override;
7676

77-
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
77+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
78+
GetForwardDeclCompilerTypeToDIE() override;
7879

7980
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
8081

lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp

+63-54
Original file line numberDiff line numberDiff line change
@@ -13,66 +13,75 @@
1313
using namespace lldb_private::dwarf;
1414
using namespace lldb_private::plugin::dwarf;
1515

16-
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
17-
const lldb_private::Declaration &decl,
18-
const int32_t byte_size,
19-
UniqueDWARFASTType &entry) const {
20-
for (const UniqueDWARFASTType &udt : m_collection) {
21-
// Make sure the tags match
22-
if (udt.m_die.Tag() == die.Tag()) {
23-
// Validate byte sizes of both types only if both are valid.
24-
if (udt.m_byte_size < 0 || byte_size < 0 ||
25-
udt.m_byte_size == byte_size) {
26-
// Make sure the file and line match
27-
if (udt.m_declaration == decl) {
28-
// The type has the same name, and was defined on the same file and
29-
// line. Now verify all of the parent DIEs match.
30-
DWARFDIE parent_arg_die = die.GetParent();
31-
DWARFDIE parent_pos_die = udt.m_die.GetParent();
32-
bool match = true;
33-
bool done = false;
34-
while (!done && match && parent_arg_die && parent_pos_die) {
35-
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
36-
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
37-
if (parent_arg_tag == parent_pos_tag) {
38-
switch (parent_arg_tag) {
39-
case DW_TAG_class_type:
40-
case DW_TAG_structure_type:
41-
case DW_TAG_union_type:
42-
case DW_TAG_namespace: {
43-
const char *parent_arg_die_name = parent_arg_die.GetName();
44-
if (parent_arg_die_name ==
45-
nullptr) // Anonymous (i.e. no-name) struct
46-
{
47-
match = false;
48-
} else {
49-
const char *parent_pos_die_name = parent_pos_die.GetName();
50-
if (parent_pos_die_name == nullptr ||
51-
((parent_arg_die_name != parent_pos_die_name) &&
52-
strcmp(parent_arg_die_name, parent_pos_die_name)))
53-
match = false;
54-
}
55-
} break;
16+
static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
17+
return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
18+
Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
19+
}
5620

57-
case DW_TAG_compile_unit:
58-
case DW_TAG_partial_unit:
59-
done = true;
60-
break;
61-
default:
62-
break;
63-
}
21+
UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
22+
const DWARFDIE &die, const lldb_private::Declaration &decl,
23+
const int32_t byte_size, bool is_forward_declaration) {
24+
for (UniqueDWARFASTType &udt : m_collection) {
25+
// Make sure the tags match
26+
if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
27+
IsStructOrClassTag(die.Tag()))) {
28+
// If they are not both definition DIEs or both declaration DIEs, then
29+
// don't check for byte size and declaration location, because declaration
30+
// DIEs usually don't have those info.
31+
bool matching_size_declaration =
32+
udt.m_is_forward_declaration != is_forward_declaration
33+
? true
34+
: (udt.m_byte_size < 0 || byte_size < 0 ||
35+
udt.m_byte_size == byte_size) &&
36+
udt.m_declaration == decl;
37+
if (!matching_size_declaration)
38+
continue;
39+
// The type has the same name, and was defined on the same file and
40+
// line. Now verify all of the parent DIEs match.
41+
DWARFDIE parent_arg_die = die.GetParent();
42+
DWARFDIE parent_pos_die = udt.m_die.GetParent();
43+
bool match = true;
44+
bool done = false;
45+
while (!done && match && parent_arg_die && parent_pos_die) {
46+
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
47+
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
48+
if (parent_arg_tag == parent_pos_tag ||
49+
(IsStructOrClassTag(parent_arg_tag) &&
50+
IsStructOrClassTag(parent_pos_tag))) {
51+
switch (parent_arg_tag) {
52+
case DW_TAG_class_type:
53+
case DW_TAG_structure_type:
54+
case DW_TAG_union_type:
55+
case DW_TAG_namespace: {
56+
const char *parent_arg_die_name = parent_arg_die.GetName();
57+
if (parent_arg_die_name == nullptr) {
58+
// Anonymous (i.e. no-name) struct
59+
match = false;
60+
} else {
61+
const char *parent_pos_die_name = parent_pos_die.GetName();
62+
if (parent_pos_die_name == nullptr ||
63+
((parent_arg_die_name != parent_pos_die_name) &&
64+
strcmp(parent_arg_die_name, parent_pos_die_name)))
65+
match = false;
6466
}
65-
parent_arg_die = parent_arg_die.GetParent();
66-
parent_pos_die = parent_pos_die.GetParent();
67-
}
67+
} break;
6868

69-
if (match) {
70-
entry = udt;
71-
return true;
69+
case DW_TAG_compile_unit:
70+
case DW_TAG_partial_unit:
71+
done = true;
72+
break;
73+
default:
74+
break;
7275
}
7376
}
77+
parent_arg_die = parent_arg_die.GetParent();
78+
parent_pos_die = parent_pos_die.GetParent();
79+
}
80+
81+
if (match) {
82+
return &udt;
7483
}
7584
}
7685
}
77-
return false;
86+
return nullptr;
7887
}

0 commit comments

Comments
 (0)