10
10
#include " Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
11
11
#include " Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
12
12
#include " Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
13
+ #include " Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
13
14
#include " lldb/Core/Module.h"
14
15
#include " lldb/Utility/RegularExpression.h"
15
16
#include " lldb/Utility/Stream.h"
@@ -34,6 +35,17 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
34
35
module , std::move (index_up), debug_names, debug_str, dwarf));
35
36
}
36
37
38
+ llvm::DenseSet<uint64_t >
39
+ DebugNamesDWARFIndex::GetTypeUnitSignatures (const DebugNames &debug_names) {
40
+ llvm::DenseSet<uint64_t > result;
41
+ for (const DebugNames::NameIndex &ni : debug_names) {
42
+ const uint32_t num_tus = ni.getForeignTUCount ();
43
+ for (uint32_t tu = 0 ; tu < num_tus; ++tu)
44
+ result.insert (ni.getForeignTUSignature (tu));
45
+ }
46
+ return result;
47
+ }
48
+
37
49
llvm::DenseSet<dw_offset_t >
38
50
DebugNamesDWARFIndex::GetUnits (const DebugNames &debug_names) {
39
51
llvm::DenseSet<dw_offset_t > result;
@@ -48,20 +60,80 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
48
60
return result;
49
61
}
50
62
63
+ std::optional<DWARFTypeUnit *>
64
+ DebugNamesDWARFIndex::GetForeignTypeUnit (const DebugNames::Entry &entry) const {
65
+ std::optional<uint64_t > type_sig = entry.getForeignTUTypeSignature ();
66
+ if (!type_sig.has_value ())
67
+ return std::nullopt ;
68
+
69
+ // Ask the entry for the skeleton compile unit offset and fetch the .dwo
70
+ // file from it and get the type unit by signature from there. If we find
71
+ // the type unit in the .dwo file, we don't need to check that the
72
+ // DW_AT_dwo_name matches because each .dwo file can have its own type unit.
73
+ std::optional<uint64_t > cu_offset = entry.getRelatedCUOffset ();
74
+ if (!cu_offset)
75
+ return nullptr ; // Return NULL, this is a type unit, but couldn't find it.
76
+
77
+ DWARFUnit *cu =
78
+ m_debug_info.GetUnitAtOffset (DIERef::Section::DebugInfo, *cu_offset);
79
+ if (!cu)
80
+ return nullptr ; // Return NULL, this is a type unit, but couldn't find it.
81
+
82
+ auto dwp_sp = m_debug_info.GetDwpSymbolFile ();
83
+ if (!dwp_sp) {
84
+ // No .dwp file, we need to load the .dwo file.
85
+ DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit ();
86
+ // We don't need the check if the type unit matches the .dwo file if we have
87
+ // a .dwo file (not a .dwp), so we can just return the value here.
88
+ if (!dwo_cu.IsDWOUnit ())
89
+ return nullptr ; // We weren't able to load the .dwo file.
90
+ return dwo_cu.GetSymbolFileDWARF ().DebugInfo ().GetTypeUnitForHash (
91
+ *type_sig);
92
+ }
93
+ // We have a .dwp file, just get the type unit from there. We need to verify
94
+ // that the type unit that ended up in the final .dwp file is the right type
95
+ // unit. Type units have signatures which are the same across multiple .dwo
96
+ // files, but only one of those type units will end up in the .dwp file. The
97
+ // contents of type units for the same type can be different in different .dwo
98
+ // files, which means the DIE offsets might not be the same between two
99
+ // different type units. So we need to determine if this accelerator table
100
+ // matches the type unit that ended up in the .dwp file. If it doesn't match,
101
+ // then we need to ignore this accelerator table entry as the type unit that
102
+ // is in the .dwp file will have its own index. In order to determine if the
103
+ // type unit that ended up in a .dwp file matches this DebugNames::Entry, we
104
+ // need to find the skeleton compile unit for this entry.
105
+ DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo ().GetTypeUnitForHash (*type_sig);
106
+ if (!foreign_tu)
107
+ return nullptr ; // Return NULL, this is a type unit, but couldn't find it.
108
+
109
+ DWARFBaseDIE cu_die = cu->GetUnitDIEOnly ();
110
+ DWARFBaseDIE tu_die = foreign_tu->GetUnitDIEOnly ();
111
+ llvm::StringRef cu_dwo_name =
112
+ cu_die.GetAttributeValueAsString (DW_AT_dwo_name, nullptr );
113
+ llvm::StringRef tu_dwo_name =
114
+ tu_die.GetAttributeValueAsString (DW_AT_dwo_name, nullptr );
115
+ if (cu_dwo_name == tu_dwo_name)
116
+ return foreign_tu; // We found a match!
117
+ return nullptr ; // Return NULL, this is a type unit, but couldn't find it.
118
+ }
119
+
51
120
DWARFUnit *
52
121
DebugNamesDWARFIndex::GetNonSkeletonUnit (const DebugNames::Entry &entry) const {
122
+
123
+ if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit (entry))
124
+ return foreign_tu.value ();
125
+
53
126
// Look for a DWARF unit offset (CU offset or local TU offset) as they are
54
127
// both offsets into the .debug_info section.
55
128
std::optional<uint64_t > unit_offset = entry.getCUOffset ();
56
- if (!unit_offset) {
129
+ if (!unit_offset)
57
130
unit_offset = entry.getLocalTUOffset ();
58
- if (!unit_offset)
59
- return nullptr ;
131
+ if (unit_offset) {
132
+ if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset (DIERef::Section::DebugInfo,
133
+ *unit_offset))
134
+ return &cu->GetNonSkeletonUnit ();
60
135
}
61
-
62
- DWARFUnit *cu =
63
- m_debug_info.GetUnitAtOffset (DIERef::Section::DebugInfo, *unit_offset);
64
- return cu ? &cu->GetNonSkeletonUnit () : nullptr ;
136
+ return nullptr ;
65
137
}
66
138
67
139
DWARFDIE DebugNamesDWARFIndex::GetDIE (const DebugNames::Entry &entry) const {
@@ -274,6 +346,13 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
274
346
if (!isType (entry.tag ()))
275
347
continue ;
276
348
349
+ // If we get a NULL foreign_tu back, the entry doesn't match the type unit
350
+ // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
351
+ // didn't match.
352
+ std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit (entry);
353
+ if (foreign_tu && foreign_tu.value () == nullptr )
354
+ continue ;
355
+
277
356
// Grab at most one extra parent, subsequent parents are not necessary to
278
357
// test equality.
279
358
std::optional<llvm::SmallVector<Entry, 4 >> parent_chain =
0 commit comments