Skip to content

Commit 7b077b1

Browse files
[lldb][DWARFIndex] Implement GetFullyQualifiedType query
Combines: 1. the accelerator table capability of finding parents 2. the DWARFUnit capability of finding the name of a DIE without parsing the whole CU.
1 parent f0cf444 commit 7b077b1

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
10+
#include "DWARFDeclContext.h"
1011
#include "Plugins/Language/ObjC/ObjCLanguage.h"
1112
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
1213
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
@@ -112,3 +113,21 @@ void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const {
112113
"bad die {0:x16} for '{1}')\n",
113114
ref.die_offset(), name.str().c_str());
114115
}
116+
117+
void DWARFIndex::GetFullyQualifiedType(
118+
const DWARFDeclContext &context,
119+
llvm::function_ref<bool(DWARFDIE die)> callback) {
120+
auto qualified_names = context.GetQualifiedNameAsVector();
121+
if (qualified_names.empty())
122+
return;
123+
auto parent_names = llvm::makeArrayRef(qualified_names).drop_front();
124+
GetTypes(context, [&](DWARFDIE die) {
125+
auto original_die = die;
126+
for (auto parent_name : parent_names) {
127+
die = die.GetParent();
128+
if (!die || die.GetName() != parent_name)
129+
return false;
130+
}
131+
return callback(original_die);
132+
});
133+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ class DWARFIndex {
5353
llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
5454
virtual void GetTypes(const DWARFDeclContext &context,
5555
llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
56+
57+
/// Finds all DIEs whose fully qualified name matches `context`. A base
58+
/// implementation is provided, and it uses the entire CU to check the DIE
59+
/// parent hierarchy. Specializations should override this if they are able
60+
/// to provide a faster implementation.
61+
virtual void
62+
GetFullyQualifiedType(const DWARFDeclContext &context,
63+
llvm::function_ref<bool(DWARFDIE die)> callback);
5664
virtual void
5765
GetNamespaces(ConstString name,
5866
llvm::function_ref<bool(DWARFDIE die)> callback) = 0;

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,55 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(
218218
m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
219219
}
220220

221+
void DebugNamesDWARFIndex::GetFullyQualifiedType(
222+
const DWARFDeclContext &context,
223+
llvm::function_ref<bool(DWARFDIE die)> callback) {
224+
if (!m_debug_names_up->supportsIdxParent())
225+
return DWARFIndex::GetFullyQualifiedType(context, callback);
226+
227+
auto qualified_names = context.GetQualifiedNameAsVector();
228+
if (qualified_names.empty())
229+
return;
230+
231+
auto CompareEntryATName = [this](llvm::StringRef expected_name,
232+
const DebugNames::Entry &entry) {
233+
auto maybe_dieoffset = entry.getDIEUnitOffset();
234+
if (!maybe_dieoffset)
235+
return false;
236+
auto die_ref = ToDIERef(entry);
237+
if (!die_ref)
238+
return false;
239+
return expected_name == m_debug_info.PeekDIEName(*die_ref);
240+
};
241+
242+
auto parent_names = llvm::makeArrayRef(qualified_names).drop_front();
243+
auto CheckParentChain = [&](DebugNames::Entry entry) {
244+
for (auto expected_name : parent_names) {
245+
auto maybe_parent_entry = entry.getParentDIEEntry();
246+
if (!maybe_parent_entry) {
247+
consumeError(maybe_parent_entry.takeError());
248+
return false;
249+
}
250+
entry = *maybe_parent_entry;
251+
if (!CompareEntryATName(expected_name, entry))
252+
return false;
253+
}
254+
/// All expected names matched. The remaining entry should have no parent
255+
/// for a match to occur.
256+
auto maybe_parent_entry = entry.getParentDIEEntry();
257+
if (maybe_parent_entry)
258+
return false;
259+
consumeError(maybe_parent_entry.takeError());
260+
return true;
261+
};
262+
263+
auto leaf_matches = m_debug_names_up->equal_range(qualified_names.front());
264+
for (const DebugNames::Entry &entry : leaf_matches)
265+
if (isType(entry.tag()) && CheckParentChain(entry) &&
266+
(!ProcessEntry(entry, callback)))
267+
return;
268+
}
269+
221270
void DebugNamesDWARFIndex::GetTypes(
222271
ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
223272
for (const DebugNames::Entry &entry :

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class DebugNamesDWARFIndex : public DWARFIndex {
4242
void GetCompleteObjCClass(
4343
ConstString class_name, bool must_be_implementation,
4444
llvm::function_ref<bool(DWARFDIE die)> callback) override;
45+
46+
/// Uses DWARF5's IDX_parent fields, when available, to speed up this query.
47+
void GetFullyQualifiedType(
48+
const DWARFDeclContext &context,
49+
llvm::function_ref<bool(DWARFDIE die)> callback) override;
4550
void GetTypes(ConstString name,
4651
llvm::function_ref<bool(DWARFDIE die)> callback) override;
4752
void GetTypes(const DWARFDeclContext &context,

0 commit comments

Comments
 (0)