Skip to content

Commit 51dd4ea

Browse files
authored
Reapply [lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. (#92328)
This reapplies 9a7262c (#90663) and added #91808 as a fix. It was causing tests on macos to fail because `SymbolFileDWARF::GetForwardDeclCompilerTypeToDIE` returned the map owned by this symol file. When there were two symbol files, two different maps were created for caching from compiler type to DIE even if they are for the same module. The solution is to do the same as `SymbolFileDWARF::GetUniqueDWARFASTTypeMap`: inquery SymbolFileDWARFDebugMap first to get the shared underlying SymbolFile so the map is shared among multiple SymbolFileDWARF.
1 parent 8890214 commit 51dd4ea

12 files changed

+467
-392
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class DWARFASTParser {
6060

6161
virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0;
6262

63+
virtual lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) = 0;
64+
6365
static std::optional<SymbolFile::ArrayInfo>
6466
ParseChildArrayInfo(const DWARFDIE &parent_die,
6567
const ExecutionContext *exe_ctx = nullptr);

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

+218-179
Large diffs are not rendered by default.

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

+88-109
Large diffs are not rendered by default.

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

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ bool DebugNamesDWARFIndex::ProcessEntry(
8787
DWARFDIE die = dwarf.GetDIE(*ref);
8888
if (!die)
8989
return true;
90+
// Clang erroneously emits index entries for declaration DIEs in case when the
91+
// definition is in a type unit (llvm.org/pr77696). Weed those out.
92+
if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
93+
return true;
9094
return callback(die);
9195
}
9296

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

+32-19
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)
@@ -1632,27 +1639,33 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
16321639
return true;
16331640
}
16341641

1635-
DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
1636-
if (dwarf_die) {
1637-
// Once we start resolving this type, remove it from the forward
1638-
// declaration map in case anyone child members or other types require this
1639-
// type to get resolved. The type will get resolved when all of the calls
1640-
// to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
1641-
GetForwardDeclCompilerTypeToDIE().erase(die_it);
1642-
1643-
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
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+
DWARFDIE dwarf_die = GetDIE(die_it->second);
1646+
GetForwardDeclCompilerTypeToDIE().erase(die_it);
1647+
Type *type = nullptr;
1648+
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
1649+
type = dwarf_ast->FindDefinitionTypeForDIE(dwarf_die);
1650+
if (!type)
1651+
return false;
16441652

1645-
Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
1646-
if (log)
1647-
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
1648-
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
1649-
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
1650-
dwarf_die.Tag(), type->GetName().AsCString());
1651-
assert(compiler_type);
1652-
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
1653-
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
1653+
die_it = GetForwardDeclCompilerTypeToDIE().find(
1654+
compiler_type_no_qualifiers.GetOpaqueQualType());
1655+
if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
1656+
dwarf_die = GetDIE(die_it->getSecond());
1657+
GetForwardDeclCompilerTypeToDIE().erase(die_it);
16541658
}
1655-
return false;
1659+
1660+
if (Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion))
1661+
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
1662+
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
1663+
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
1664+
dwarf_die.Tag(), type->GetName().AsCString());
1665+
assert(compiler_type);
1666+
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
1667+
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
1668+
return true;
16561669
}
16571670

16581671
Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,

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

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

336336
virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; }
337337

338-
typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
339-
CompilerTypeToDIE;
340-
341-
virtual CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() {
342-
return m_forward_decl_compiler_type_to_die;
343-
}
338+
virtual llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
339+
GetForwardDeclCompilerTypeToDIE();
344340

345341
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
346342
DIEToVariableSP;
@@ -533,9 +529,14 @@ class SymbolFileDWARF : public SymbolFileCommon {
533529
NameToOffsetMap m_function_scope_qualified_name_map;
534530
std::unique_ptr<DWARFDebugRanges> m_ranges;
535531
UniqueDWARFASTTypeMap m_unique_ast_type_map;
532+
// A map from DIE to lldb_private::Type. For record type, the key might be
533+
// either declaration DIE or definition DIE.
536534
DIEToTypePtr m_die_to_type;
537535
DIEToVariableSP m_die_to_variable_sp;
538-
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
536+
// A map from CompilerType to the struct/class/union/enum DIE (might be a
537+
// declaration or a definition) that is used to construct it.
538+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
539+
m_forward_decl_compiler_type_to_die;
539540
llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
540541
m_type_unit_support_files;
541542
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
@@ -72,7 +72,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
7272

7373
DIEToVariableSP &GetDIEToVariable() override;
7474

75-
CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
75+
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
76+
GetForwardDeclCompilerTypeToDIE() override;
7677

7778
UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
7879

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

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

69-
if (match) {
70-
entry = udt;
71-
return true;
61+
case DW_TAG_compile_unit:
62+
case DW_TAG_partial_unit:
63+
done = true;
64+
break;
65+
default:
66+
break;
7267
}
7368
}
69+
parent_arg_die = parent_arg_die.GetParent();
70+
parent_pos_die = parent_pos_die.GetParent();
71+
}
72+
73+
if (match) {
74+
return &udt;
7475
}
7576
}
7677
}
77-
return false;
78+
return nullptr;
7879
}

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

+13-23
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,19 @@ class UniqueDWARFASTType {
2323
// Constructors and Destructors
2424
UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
2525

26-
UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
27-
const Declaration &decl, int32_t byte_size)
28-
: m_type_sp(type_sp), m_die(die), m_declaration(decl),
29-
m_byte_size(byte_size) {}
30-
3126
UniqueDWARFASTType(const UniqueDWARFASTType &rhs)
3227
: m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
33-
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
28+
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size),
29+
m_is_forward_declaration(rhs.m_is_forward_declaration) {}
3430

3531
~UniqueDWARFASTType() = default;
3632

37-
UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) {
38-
if (this != &rhs) {
39-
m_type_sp = rhs.m_type_sp;
40-
m_die = rhs.m_die;
41-
m_declaration = rhs.m_declaration;
42-
m_byte_size = rhs.m_byte_size;
43-
}
44-
return *this;
45-
}
46-
4733
lldb::TypeSP m_type_sp;
4834
DWARFDIE m_die;
4935
Declaration m_declaration;
5036
int32_t m_byte_size = -1;
37+
// True if the m_die is a forward declaration DIE.
38+
bool m_is_forward_declaration = true;
5139
};
5240

5341
class UniqueDWARFASTTypeList {
@@ -62,8 +50,9 @@ class UniqueDWARFASTTypeList {
6250
m_collection.push_back(entry);
6351
}
6452

65-
bool Find(const DWARFDIE &die, const Declaration &decl,
66-
const int32_t byte_size, UniqueDWARFASTType &entry) const;
53+
UniqueDWARFASTType *Find(const DWARFDIE &die, const Declaration &decl,
54+
const int32_t byte_size,
55+
bool is_forward_declaration);
6756

6857
protected:
6958
typedef std::vector<UniqueDWARFASTType> collection;
@@ -80,14 +69,15 @@ class UniqueDWARFASTTypeMap {
8069
m_collection[name.GetCString()].Append(entry);
8170
}
8271

83-
bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl,
84-
const int32_t byte_size, UniqueDWARFASTType &entry) const {
72+
UniqueDWARFASTType *Find(ConstString name, const DWARFDIE &die,
73+
const Declaration &decl, const int32_t byte_size,
74+
bool is_forward_declaration) {
8575
const char *unique_name_cstr = name.GetCString();
86-
collection::const_iterator pos = m_collection.find(unique_name_cstr);
76+
collection::iterator pos = m_collection.find(unique_name_cstr);
8777
if (pos != m_collection.end()) {
88-
return pos->second.Find(die, decl, byte_size, entry);
78+
return pos->second.Find(die, decl, byte_size, is_forward_declaration);
8979
}
90-
return false;
80+
return nullptr;
9181
}
9282

9383
protected:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Test definition DIE searching is delayed until complete type is required.
2+
3+
# UNSUPPORTED: system-windows
4+
5+
# RUN: split-file %s %t
6+
# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -gdwarf -o %t.out
7+
# RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s
8+
9+
# CHECK: (lldb) p v1
10+
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2<t1>'
11+
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
12+
# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2<t1>' resolving forward declaration...
13+
# CHECK: (t2<t1>) {}
14+
# CHECK: (lldb) p v2
15+
# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
16+
# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration...
17+
18+
#--- lldb.cmd
19+
log enable dwarf comp
20+
p v1
21+
p v2
22+
23+
#--- main.cpp
24+
template<typename T>
25+
struct t2 {
26+
};
27+
struct t1;
28+
t2<t1> v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it.
29+
int main() {
30+
}
31+
32+
#--- t1_def.cpp
33+
struct t1 { // this CU contains definition DIE for t1.
34+
int x;
35+
};
36+
t1 v2;

0 commit comments

Comments
 (0)