[LoongArch][Clang] Make the parameters and return value of {x,}vorn.v builti ns ...
[llvm-project.git] / lldb / source / Plugins / SymbolFile / DWARF / DebugNamesDWARFIndex.cpp
blob6f2cb455ec00e154464c81d6f8a2988f87be3bc8
1 //===-- DebugNamesDWARFIndex.cpp ------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
10 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
12 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
13 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Utility/RegularExpression.h"
16 #include "lldb/Utility/Stream.h"
17 #include "llvm/ADT/Sequence.h"
18 #include <optional>
20 using namespace lldb_private;
21 using namespace lldb;
22 using namespace lldb_private::dwarf;
23 using namespace lldb_private::plugin::dwarf;
25 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
26 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
27 DWARFDataExtractor debug_str,
28 SymbolFileDWARF &dwarf) {
29 auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVMDWARF(),
30 debug_str.GetAsLLVM());
31 if (llvm::Error E = index_up->extract())
32 return std::move(E);
34 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
35 module, std::move(index_up), debug_names, debug_str, dwarf));
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));
46 return result;
49 llvm::DenseSet<dw_offset_t>
50 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
51 llvm::DenseSet<dw_offset_t> result;
52 for (const DebugNames::NameIndex &ni : debug_names) {
53 const uint32_t num_cus = ni.getCUCount();
54 for (uint32_t cu = 0; cu < num_cus; ++cu)
55 result.insert(ni.getCUOffset(cu));
56 const uint32_t num_tus = ni.getLocalTUCount();
57 for (uint32_t tu = 0; tu < num_tus; ++tu)
58 result.insert(ni.getLocalTUOffset(tu));
60 return result;
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;
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.
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.
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);
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.
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.
120 DWARFUnit *
121 DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {
123 if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry))
124 return foreign_tu.value();
126 // Look for a DWARF unit offset (CU offset or local TU offset) as they are
127 // both offsets into the .debug_info section.
128 std::optional<uint64_t> unit_offset = entry.getCUOffset();
129 if (!unit_offset)
130 unit_offset = entry.getLocalTUOffset();
131 if (unit_offset) {
132 if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo,
133 *unit_offset))
134 return &cu->GetNonSkeletonUnit();
136 return nullptr;
139 DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const {
140 DWARFUnit *unit = GetNonSkeletonUnit(entry);
141 std::optional<uint64_t> die_offset = entry.getDIEUnitOffset();
142 if (!unit || !die_offset)
143 return DWARFDIE();
144 if (DWARFDIE die = unit->GetDIE(unit->GetOffset() + *die_offset))
145 return die;
147 m_module.ReportErrorIfModifyDetected(
148 "the DWARF debug information has been modified (bad offset {0:x} in "
149 "debug_names section)\n",
150 *die_offset);
151 return DWARFDIE();
154 bool DebugNamesDWARFIndex::ProcessEntry(
155 const DebugNames::Entry &entry,
156 llvm::function_ref<bool(DWARFDIE die)> callback) {
157 DWARFDIE die = GetDIE(entry);
158 if (!die)
159 return true;
160 // Clang used to erroneously emit index entries for declaration DIEs in case
161 // when the definition is in a type unit (llvm.org/pr77696).
162 if (die.IsStructUnionOrClass() &&
163 die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
164 return true;
165 return callback(die);
168 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
169 const DebugNames::NameIndex &ni,
170 llvm::StringRef name) {
171 // Ignore SentinelErrors, log everything else.
172 LLDB_LOG_ERROR(
173 GetLog(DWARFLog::Lookups),
174 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
175 "Failed to parse index entries for index at {1:x}, name {2}: {0}",
176 ni.getUnitOffset(), name);
179 void DebugNamesDWARFIndex::GetGlobalVariables(
180 ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
181 for (const DebugNames::Entry &entry :
182 m_debug_names_up->equal_range(basename.GetStringRef())) {
183 if (entry.tag() != DW_TAG_variable)
184 continue;
186 if (!ProcessEntry(entry, callback))
187 return;
190 m_fallback.GetGlobalVariables(basename, callback);
193 void DebugNamesDWARFIndex::GetGlobalVariables(
194 const RegularExpression &regex,
195 llvm::function_ref<bool(DWARFDIE die)> callback) {
196 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
197 for (DebugNames::NameTableEntry nte: ni) {
198 Mangled mangled_name(nte.getString());
199 if (!mangled_name.NameMatches(regex))
200 continue;
202 uint64_t entry_offset = nte.getEntryOffset();
203 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
204 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
205 if (entry_or->tag() != DW_TAG_variable)
206 continue;
208 if (!ProcessEntry(*entry_or, callback))
209 return;
211 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
215 m_fallback.GetGlobalVariables(regex, callback);
218 void DebugNamesDWARFIndex::GetGlobalVariables(
219 DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
220 uint64_t cu_offset = cu.GetOffset();
221 bool found_entry_for_cu = false;
222 for (const DebugNames::NameIndex &ni : *m_debug_names_up) {
223 // Check if this name index contains an entry for the given CU.
224 bool cu_matches = false;
225 for (uint32_t i = 0; i < ni.getCUCount(); ++i) {
226 if (ni.getCUOffset(i) == cu_offset) {
227 cu_matches = true;
228 break;
231 if (!cu_matches)
232 continue;
234 for (DebugNames::NameTableEntry nte : ni) {
235 uint64_t entry_offset = nte.getEntryOffset();
236 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
237 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
238 if (entry_or->tag() != DW_TAG_variable)
239 continue;
240 if (entry_or->getCUOffset() != cu_offset)
241 continue;
243 found_entry_for_cu = true;
244 if (!ProcessEntry(*entry_or, callback))
245 return;
247 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
250 // If no name index for that particular CU was found, fallback to
251 // creating the manual index.
252 if (!found_entry_for_cu)
253 m_fallback.GetGlobalVariables(cu, callback);
256 void DebugNamesDWARFIndex::GetCompleteObjCClass(
257 ConstString class_name, bool must_be_implementation,
258 llvm::function_ref<bool(DWARFDIE die)> callback) {
259 // Keep a list of incomplete types as fallback for when we don't find the
260 // complete type.
261 std::vector<DWARFDIE> incomplete_types;
263 for (const DebugNames::Entry &entry :
264 m_debug_names_up->equal_range(class_name.GetStringRef())) {
265 if (entry.tag() != DW_TAG_structure_type &&
266 entry.tag() != DW_TAG_class_type)
267 continue;
269 DWARFDIE die = GetDIE(entry);
270 if (!die) {
271 // Report invalid
272 continue;
274 DWARFUnit *cu = die.GetCU();
275 if (!cu->Supports_DW_AT_APPLE_objc_complete_type()) {
276 incomplete_types.push_back(die);
277 continue;
280 if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
281 // If we find the complete version we're done.
282 callback(die);
283 return;
285 incomplete_types.push_back(die);
288 for (DWARFDIE die : incomplete_types)
289 if (!callback(die))
290 return;
292 m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
295 namespace {
296 using Entry = llvm::DWARFDebugNames::Entry;
298 /// If `entry` and all of its parents have an `IDX_parent`, use that information
299 /// to build and return a list of at most `max_parents` parent Entries.
300 /// `entry` itself is not included in the list.
301 /// If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
302 /// nullopt is returned.
303 std::optional<llvm::SmallVector<Entry, 4>>
304 getParentChain(Entry entry,
305 uint32_t max_parents = std::numeric_limits<uint32_t>::max()) {
306 llvm::SmallVector<Entry, 4> parent_entries;
308 do {
309 if (!entry.hasParentInformation())
310 return std::nullopt;
312 llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
313 if (!parent) {
314 // Bad data.
315 LLDB_LOG_ERROR(
316 GetLog(DWARFLog::Lookups), parent.takeError(),
317 "Failed to extract parent entry from a non-empty IDX_parent");
318 return std::nullopt;
321 // Last parent in the chain.
322 if (!parent->has_value())
323 break;
325 parent_entries.push_back(**parent);
326 entry = **parent;
327 } while (parent_entries.size() < max_parents);
329 return parent_entries;
331 } // namespace
333 void DebugNamesDWARFIndex::GetFullyQualifiedType(
334 const DWARFDeclContext &context,
335 llvm::function_ref<bool(DWARFDIE die)> callback) {
336 if (context.GetSize() == 0)
337 return;
339 llvm::StringRef leaf_name = context[0].name;
340 llvm::SmallVector<llvm::StringRef> parent_names;
341 for (auto idx : llvm::seq<int>(1, context.GetSize()))
342 parent_names.emplace_back(context[idx].name);
344 // For each entry, grab its parent chain and check if we have a match.
345 for (const DebugNames::Entry &entry :
346 m_debug_names_up->equal_range(leaf_name)) {
347 if (!isType(entry.tag()))
348 continue;
350 // If we get a NULL foreign_tu back, the entry doesn't match the type unit
351 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
352 // didn't match.
353 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
354 if (foreign_tu && foreign_tu.value() == nullptr)
355 continue;
357 // Grab at most one extra parent, subsequent parents are not necessary to
358 // test equality.
359 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
360 getParentChain(entry, parent_names.size() + 1);
362 if (!parent_chain) {
363 // Fallback: use the base class implementation.
364 if (!ProcessEntry(entry, [&](DWARFDIE die) {
365 return GetFullyQualifiedTypeImpl(context, die, callback);
367 return;
368 continue;
371 if (SameParentChain(parent_names, *parent_chain)) {
372 if (!ProcessEntry(entry, callback))
373 return;
376 m_fallback.GetFullyQualifiedType(context, callback);
379 bool DebugNamesDWARFIndex::SameAsEntryContext(
380 const CompilerContext &query_context,
381 const DebugNames::Entry &entry) const {
382 // TODO: check dwarf tag matches.
383 // Peek at the AT_name of `entry` and test equality to `name`.
384 auto maybe_dieoffset = entry.getDIEUnitOffset();
385 if (!maybe_dieoffset)
386 return false;
387 DWARFUnit *unit = GetNonSkeletonUnit(entry);
388 if (!unit)
389 return false;
390 return query_context.name ==
391 unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
394 bool DebugNamesDWARFIndex::SameParentChain(
395 llvm::ArrayRef<llvm::StringRef> parent_names,
396 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
398 if (parent_entries.size() != parent_names.size())
399 return false;
401 auto SameAsEntryATName = [this](llvm::StringRef name,
402 const DebugNames::Entry &entry) {
403 // Peek at the AT_name of `entry` and test equality to `name`.
404 auto maybe_dieoffset = entry.getDIEUnitOffset();
405 if (!maybe_dieoffset)
406 return false;
407 DWARFUnit *unit = GetNonSkeletonUnit(entry);
408 if (!unit)
409 return false;
410 return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
413 // If the AT_name of any parent fails to match the expected name, we don't
414 // have a match.
415 for (auto [parent_name, parent_entry] :
416 llvm::zip_equal(parent_names, parent_entries))
417 if (!SameAsEntryATName(parent_name, parent_entry))
418 return false;
419 return true;
422 bool DebugNamesDWARFIndex::SameParentChain(
423 llvm::ArrayRef<CompilerContext> parent_contexts,
424 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
425 if (parent_entries.size() != parent_contexts.size())
426 return false;
428 // If the AT_name of any parent fails to match the expected name, we don't
429 // have a match.
430 for (auto [parent_context, parent_entry] :
431 llvm::zip_equal(parent_contexts, parent_entries))
432 if (!SameAsEntryContext(parent_context, parent_entry))
433 return false;
434 return true;
437 bool DebugNamesDWARFIndex::WithinParentChain(
438 llvm::ArrayRef<CompilerContext> query_contexts,
439 llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
440 if (query_contexts.size() == parent_chain.size())
441 return SameParentChain(query_contexts, parent_chain);
443 // If parent chain does not have enough entries, we can't possibly have a
444 // match.
445 while (!query_contexts.empty() &&
446 query_contexts.size() <= parent_chain.size()) {
447 if (SameAsEntryContext(query_contexts.front(), parent_chain.front())) {
448 query_contexts = query_contexts.drop_front();
449 parent_chain = parent_chain.drop_front();
450 } else {
451 // Name does not match, try next parent_chain entry if the current entry
452 // is namespace because the current one can be an inline namespace.
453 if (parent_chain.front().tag() != DW_TAG_namespace)
454 return false;
455 parent_chain = parent_chain.drop_front();
458 return query_contexts.empty();
461 void DebugNamesDWARFIndex::GetTypes(
462 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
463 for (const DebugNames::Entry &entry :
464 m_debug_names_up->equal_range(name.GetStringRef())) {
465 if (isType(entry.tag())) {
466 if (!ProcessEntry(entry, callback))
467 return;
471 m_fallback.GetTypes(name, callback);
474 void DebugNamesDWARFIndex::GetTypes(
475 const DWARFDeclContext &context,
476 llvm::function_ref<bool(DWARFDIE die)> callback) {
477 auto name = context[0].name;
478 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
479 if (entry.tag() == context[0].tag) {
480 if (!ProcessEntry(entry, callback))
481 return;
485 m_fallback.GetTypes(context, callback);
488 void DebugNamesDWARFIndex::GetNamespaces(
489 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
490 for (const DebugNames::Entry &entry :
491 m_debug_names_up->equal_range(name.GetStringRef())) {
492 lldb_private::dwarf::Tag entry_tag = entry.tag();
493 if (entry_tag == DW_TAG_namespace ||
494 entry_tag == DW_TAG_imported_declaration) {
495 if (!ProcessEntry(entry, callback))
496 return;
500 m_fallback.GetNamespaces(name, callback);
503 llvm::SmallVector<CompilerContext>
504 DebugNamesDWARFIndex::GetTypeQueryParentContexts(TypeQuery &query) {
505 std::vector<lldb_private::CompilerContext> &query_decl_context =
506 query.GetContextRef();
507 llvm::SmallVector<CompilerContext> parent_contexts;
508 if (!query_decl_context.empty()) {
509 // Skip the last entry as it's the type we're matching parents for.
510 // Reverse the query decl context to match parent chain order.
511 llvm::ArrayRef<CompilerContext> parent_contexts_ref(
512 query_decl_context.data(), query_decl_context.size() - 1);
513 for (const CompilerContext &ctx : llvm::reverse(parent_contexts_ref)) {
514 // Skip any context without name because .debug_names might not encode
515 // them. (e.g. annonymous namespace)
516 if ((ctx.kind & CompilerContextKind::AnyType) !=
517 CompilerContextKind::Invalid &&
518 !ctx.name.IsEmpty())
519 parent_contexts.push_back(ctx);
522 return parent_contexts;
525 void DebugNamesDWARFIndex::GetTypesWithQuery(
526 TypeQuery &query, llvm::function_ref<bool(DWARFDIE die)> callback) {
527 ConstString name = query.GetTypeBasename();
528 std::vector<lldb_private::CompilerContext> query_context =
529 query.GetContextRef();
530 if (query_context.size() <= 1)
531 return GetTypes(name, callback);
533 llvm::SmallVector<CompilerContext> parent_contexts =
534 GetTypeQueryParentContexts(query);
535 // For each entry, grab its parent chain and check if we have a match.
536 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
537 if (!isType(entry.tag()))
538 continue;
540 // If we get a NULL foreign_tu back, the entry doesn't match the type unit
541 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
542 // didn't match.
543 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
544 if (foreign_tu && foreign_tu.value() == nullptr)
545 continue;
547 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
548 getParentChain(entry);
549 if (!parent_chain) {
550 // Fallback: use the base class implementation.
551 if (!ProcessEntry(entry, [&](DWARFDIE die) {
552 return ProcessTypeDIEMatchQuery(query, die, callback);
554 return;
555 continue;
558 if (WithinParentChain(parent_contexts, *parent_chain)) {
559 if (!ProcessEntry(entry, [&](DWARFDIE die) {
560 // After .debug_names filtering still sending to base class for
561 // further filtering before calling the callback.
562 return ProcessTypeDIEMatchQuery(query, die, callback);
564 // If the callback returns false, we're done.
565 return;
568 m_fallback.GetTypesWithQuery(query, callback);
571 void DebugNamesDWARFIndex::GetNamespacesWithParents(
572 ConstString name, const CompilerDeclContext &parent_decl_ctx,
573 llvm::function_ref<bool(DWARFDIE die)> callback) {
574 std::vector<lldb_private::CompilerContext> parent_contexts =
575 parent_decl_ctx.GetCompilerContext();
576 llvm::SmallVector<CompilerContext> parent_named_contexts;
577 std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
578 std::back_inserter(parent_named_contexts),
579 [](const CompilerContext &ctx) { return !ctx.name.IsEmpty(); });
580 for (const DebugNames::Entry &entry :
581 m_debug_names_up->equal_range(name.GetStringRef())) {
582 lldb_private::dwarf::Tag entry_tag = entry.tag();
583 if (entry_tag == DW_TAG_namespace ||
584 entry_tag == DW_TAG_imported_declaration) {
585 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
586 getParentChain(entry);
587 if (!parent_chain) {
588 // Fallback: use the base class implementation.
589 if (!ProcessEntry(entry, [&](DWARFDIE die) {
590 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
591 callback);
593 return;
594 continue;
597 if (WithinParentChain(parent_named_contexts, *parent_chain)) {
598 if (!ProcessEntry(entry, [&](DWARFDIE die) {
599 // After .debug_names filtering still sending to base class for
600 // further filtering before calling the callback.
601 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
602 callback);
604 // If the callback returns false, we're done.
605 return;
609 m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
612 void DebugNamesDWARFIndex::GetFunctions(
613 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
614 const CompilerDeclContext &parent_decl_ctx,
615 llvm::function_ref<bool(DWARFDIE die)> callback) {
616 ConstString name = lookup_info.GetLookupName();
617 std::set<DWARFDebugInfoEntry *> seen;
618 for (const DebugNames::Entry &entry :
619 m_debug_names_up->equal_range(name.GetStringRef())) {
620 Tag tag = entry.tag();
621 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
622 continue;
624 if (DWARFDIE die = GetDIE(entry)) {
625 if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx,
626 [&](DWARFDIE die) {
627 if (!seen.insert(die.GetDIE()).second)
628 return true;
629 return callback(die);
631 return;
635 m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
638 void DebugNamesDWARFIndex::GetFunctions(
639 const RegularExpression &regex,
640 llvm::function_ref<bool(DWARFDIE die)> callback) {
641 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
642 for (DebugNames::NameTableEntry nte: ni) {
643 if (!regex.Execute(nte.getString()))
644 continue;
646 uint64_t entry_offset = nte.getEntryOffset();
647 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
648 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
649 Tag tag = entry_or->tag();
650 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
651 continue;
653 if (!ProcessEntry(*entry_or, callback))
654 return;
656 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
660 m_fallback.GetFunctions(regex, callback);
663 void DebugNamesDWARFIndex::Dump(Stream &s) {
664 m_fallback.Dump(s);
666 std::string data;
667 llvm::raw_string_ostream os(data);
668 m_debug_names_up->dump(os);
669 s.PutCString(data);