1010#include " Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
1111#include " Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
1212#include " Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
13+ #include " Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
1314#include " lldb/Core/Module.h"
1415#include " lldb/Utility/RegularExpression.h"
1516#include " lldb/Utility/Stream.h"
@@ -34,6 +35,17 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
3435 module , std::move (index_up), debug_names, debug_str, dwarf));
3536}
3637
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+
3749llvm::DenseSet<dw_offset_t >
3850DebugNamesDWARFIndex::GetUnits (const DebugNames &debug_names) {
3951 llvm::DenseSet<dw_offset_t > result;
@@ -48,20 +60,80 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
4860 return result;
4961}
5062
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+
51120DWARFUnit *
52121DebugNamesDWARFIndex::GetNonSkeletonUnit (const DebugNames::Entry &entry) const {
122+
123+ if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit (entry))
124+ return foreign_tu.value ();
125+
53126 // Look for a DWARF unit offset (CU offset or local TU offset) as they are
54127 // both offsets into the .debug_info section.
55128 std::optional<uint64_t > unit_offset = entry.getCUOffset ();
56- if (!unit_offset) {
129+ if (!unit_offset)
57130 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 ();
60135 }
61-
62- DWARFUnit *cu =
63- m_debug_info.GetUnitAtOffset (DIERef::Section::DebugInfo, *unit_offset);
64- return cu ? &cu->GetNonSkeletonUnit () : nullptr ;
136+ return nullptr ;
65137}
66138
67139DWARFDIE DebugNamesDWARFIndex::GetDIE (const DebugNames::Entry &entry) const {
@@ -274,6 +346,13 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
274346 if (!isType (entry.tag ()))
275347 continue ;
276348
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+
277356 // Grab at most one extra parent, subsequent parents are not necessary to
278357 // test equality.
279358 std::optional<llvm::SmallVector<Entry, 4 >> parent_chain =
0 commit comments