Skip to content

Commit 4cdeaec

Browse files
committed
Modified IsForeignTypeUnit to return a std::optional and modify to work with new DWARF changes.
1 parent 63d56ad commit 4cdeaec

File tree

3 files changed

+78
-73
lines changed

3 files changed

+78
-73
lines changed

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

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -61,53 +61,50 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
6161
return result;
6262
}
6363

64-
bool
65-
DebugNamesDWARFIndex::IsForeignTypeUnit(const DebugNames::Entry &entry,
66-
DWARFTypeUnit *&foreign_tu) const {
67-
foreign_tu = nullptr;
64+
std::optional<DWARFTypeUnit *>
65+
DebugNamesDWARFIndex::IsForeignTypeUnit(const DebugNames::Entry &entry) const {
6866
std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature();
6967
if (!type_sig.has_value())
70-
return false;
68+
return std::nullopt;
7169
auto dwp_sp = m_debug_info.GetDwpSymbolFile();
72-
if (dwp_sp) {
73-
// We have a .dwp file, just get the type unit from there.
74-
foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
75-
} else {
76-
// We have a .dwo file that contains the type unit.
77-
foreign_tu = nullptr; // TODO: fixme before checkin
70+
if (!dwp_sp) {
71+
// No .dwp file, we need to load the .dwo file.
72+
73+
// Ask the entry for the skeleton compile unit offset and fetch the .dwo
74+
// file from it and get the type unit by signature from there. If we find
75+
// the type unit in the .dwo file, we don't need to check that the
76+
// DW_AT_dwo_name matches because each .dwo file can have its own type unit.
77+
std::optional<uint64_t> unit_offset = entry.getForeignTUSkeletonCUOffset();
78+
if (!unit_offset)
79+
return nullptr; // Return NULL, this is a type unit, but couldn't find it.
80+
DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo,
81+
*unit_offset);
82+
if (!cu)
83+
return nullptr; // Return NULL, this is a type unit, but couldn't find it.
84+
DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit();
85+
// We don't need the check if the type unit matches the .dwo file if we have
86+
// a .dwo file (not a .dwp), so we can just return the value here.
87+
if (!dwo_cu.IsDWOUnit())
88+
return nullptr; // We weren't able to load the .dwo file.
89+
return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(*type_sig);
7890
}
79-
if (foreign_tu == nullptr)
80-
return true;
81-
// If this entry represents a foreign type unit, we need to verify that
82-
// the type unit that ended up in the final .dwp file is the right type
83-
// unit. Type units have signatures which are the same across multiple
84-
// .dwo files, but only one of those type units will end up in the .dwp
85-
// file. The contents of type units for the same type can be different
86-
// in different .dwo file, which means the DIE offsets might not be the
87-
// same between two different type units. So we need to determine if this
88-
// accelerator table matches the type unit in the .dwp file. If it doesn't
89-
// match, then we need to ignore this accelerator table entry as the type
90-
// unit that is in the .dwp file will have its own index.
91-
// In order to determine if the type unit that ended up in a .dwp file
92-
// matches this DebugNames::Entry, we need to find the skeleton compile
93-
// unit for this entry. We rely on each DebugNames::Entry either having
94-
// both a DW_IDX_type_unit and a DW_IDX_compile_unit, or the .debug_names
95-
// table has only a single compile unit with multiple type units. Once
96-
// we find the skeleton compile unit, we make sure the DW_AT_dwo_name
97-
// attributes match.
98-
const llvm::DWARFDebugNames::NameIndex *name_index = entry.getNameIndex();
99-
assert(name_index);
100-
// Ask the entry for the skeleton compile unit offset.
91+
// We have a .dwp file, just get the type unit from there. We need to verify
92+
// that the type unit that ended up in the final .dwp file is the right type
93+
// unit. Type units have signatures which are the same across multiple .dwo
94+
// files, but only one of those type units will end up in the .dwp file. The
95+
// contents of type units for the same type can be different in different .dwo
96+
// files, which means the DIE offsets might not be the same between two
97+
// different type units. So we need to determine if this accelerator table
98+
// matches the type unit that ended up in the .dwp file. If it doesn't match,
99+
// then we need to ignore this accelerator table entry as the type unit that
100+
// is in the .dwp file will have its own index. In order to determine if the
101+
// type unit that ended up in a .dwp file matches this DebugNames::Entry, we
102+
// need to find the skeleton compile unit for this entry.
103+
DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
104+
if (!foreign_tu)
105+
return nullptr; // Return NULL, this is a type unit, but couldn't find it.
106+
101107
std::optional<uint64_t> cu_offset = entry.getForeignTUSkeletonCUOffset();
102-
// If the entry doesn't specify the skeleton compile unit offset, then check
103-
// if the .debug_names table only has one compile unit. If so, then this is
104-
// the skeleton compile unit we should used.
105-
if (!cu_offset && name_index->getCUCount() == 1)
106-
cu_offset = name_index->getCUOffset(0);
107-
108-
// If we couldn't find the skeleton compile unit offset, be safe and say there
109-
// is no match. We don't want to use an invalid DIE offset on the wrong type
110-
// unit.
111108
if (cu_offset) {
112109
DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::DebugInfo, *cu_offset);
113110
if (cu) {
@@ -117,27 +114,30 @@ DebugNamesDWARFIndex::IsForeignTypeUnit(const DebugNames::Entry &entry,
117114
cu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
118115
llvm::StringRef tu_dwo_name =
119116
tu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
120-
if (cu_dwo_name != tu_dwo_name)
121-
foreign_tu = nullptr; // Ignore this entry, the DWO name doesn't match.
122-
} else {
123-
foreign_tu = nullptr; // Ignore this entry, we can find the skeleton CU
117+
if (cu_dwo_name == tu_dwo_name)
118+
return foreign_tu; // We found a match!
124119
}
125-
} else {
126-
foreign_tu = nullptr; // Ignore this entry, we can find the skeleton CU
127120
}
128-
return true;
121+
return nullptr; // Return NULL, this is a type unit, but couldn't find it.
129122
}
130123

131124
DWARFUnit *
132125
DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {
126+
127+
if (std::optional<DWARFTypeUnit *> foreign_tu = IsForeignTypeUnit(entry))
128+
return foreign_tu.value();
129+
133130
// Look for a DWARF unit offset (CU offset or local TU offset) as they are
134131
// both offsets into the .debug_info section.
135132
std::optional<uint64_t> unit_offset = entry.getCUOffset();
136133
if (!unit_offset)
137134
unit_offset = entry.getLocalTUOffset();
138-
DWARFUnit *cu =
139-
m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *unit_offset);
140-
return cu ? &cu->GetNonSkeletonUnit() : nullptr;
135+
if (unit_offset) {
136+
if (DWARFUnit *cu =
137+
m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *unit_offset))
138+
return &cu->GetNonSkeletonUnit();
139+
}
140+
return nullptr;
141141
}
142142

143143
DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const {
@@ -349,14 +349,13 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
349349
if (!isType(entry.tag()))
350350
continue;
351351

352-
353-
DWARFTypeUnit *foreign_tu = nullptr;
354-
if (IsForeignTypeUnit(entry, foreign_tu)) {
355-
// If we get a NULL foreign_tu back, the entry doesn't match the type unit
356-
// in the .dwp file.
357-
if (!foreign_tu)
352+
// If we get a NULL foreign_tu back, the entry doesn't match the type unit
353+
// in the .dwp file, or we were not able to load the .dwo file or the DWO ID
354+
// didn't match.
355+
std::optional<DWARFTypeUnit *> foreign_tu = IsForeignTypeUnit(entry);
356+
if (foreign_tu && foreign_tu.value() == nullptr)
358357
continue;
359-
}
358+
360359
// Grab at most one extra parent, subsequent parents are not necessary to
361360
// test equality.
362361
std::optional<llvm::SmallVector<Entry, 4>> parent_chain =

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,17 @@ class DebugNamesDWARFIndex : public DWARFIndex {
100100
/// \param[in] entry
101101
/// The accelerator table entry to check.
102102
///
103-
/// \param[out] foreign_tu
104-
/// A reference to the foreign type unit pointer that will be filled in
105-
/// with a valid type unit if the entry matches the type unit, or filled in
106-
/// with NULL if the entry isn't valid for the type unit that ended up in
107-
/// the .dwp file.
108-
///
109103
/// \returns
110-
/// True if \a entry represents a foreign type unit, false otherwise.
111-
bool IsForeignTypeUnit(const DebugNames::Entry &entry, DWARFTypeUnit *&foreign_tu) const;
104+
/// A std::optional that has a value if this entry represents a foreign type
105+
/// unit. If the pointer is valid, then we were able to find and match the
106+
/// entry to the type unit in the .dwo or .dwp file. The returned value can
107+
/// have a valid, yet contain NULL in the following cases:
108+
/// - we were not able to load the .dwo file (missing or DWO ID mismatch)
109+
/// - we were able to load the .dwp file, but the type units DWO name
110+
/// doesn't match the originating skeleton compile unit's entry
111+
/// Returns std::nullopt if this entry is not a foreign type unit entry.
112+
std::optional<DWARFTypeUnit *>
113+
IsForeignTypeUnit(const DebugNames::Entry &entry) const;
112114

113115
DWARFTypeUnit *GetForeignTypeUnit(const DebugNames::Entry &entry) const;
114116

llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -678,15 +678,19 @@ DWARFDebugNames::Entry::getForeignTUSkeletonCUOffset() const {
678678
return std::nullopt;
679679
// Lookup the DW_IDX_compile_unit and make sure we have one, if we don't
680680
// we don't default to returning the first compile unit like getCUOffset().
681+
std::optional<uint64_t> CUIndex;
681682
std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit);
682-
if (!Off)
683-
return std::nullopt;
683+
if (Off) {
684+
CUIndex = Off->getAsUnsignedConstant();
685+
} else {
686+
// Check if there is only 1 CU and return that. Most .o files generate one
687+
// .debug_names table per source file where there is 1 CU and many TUs.
688+
if (NameIdx->getCUCount() == 1)
689+
CUIndex = 0;
690+
}
684691
// Extract the CU index and return the right CU offset.
685-
if (std::optional<uint64_t> CUIndex = Off->getAsUnsignedConstant()) {
686-
if (*CUIndex >= NameIdx->getCUCount())
687-
return std::nullopt;
692+
if (CUIndex && *CUIndex < NameIdx->getCUCount())
688693
return NameIdx->getCUOffset(*CUIndex);
689-
}
690694
return std::nullopt;
691695
}
692696

0 commit comments

Comments
 (0)