1 //===-- DebugNamesDWARFIndex.cpp ------------------------------------------===//
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
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"
20 using namespace lldb_private
;
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())
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
));
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
));
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())
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();
75 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
78 m_debug_info
.GetUnitAtOffset(DIERef::Section::DebugInfo
, *cu_offset
);
80 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
82 auto dwp_sp
= m_debug_info
.GetDwpSymbolFile();
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(
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
);
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.
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();
130 unit_offset
= entry
.getLocalTUOffset();
132 if (DWARFUnit
*cu
= m_debug_info
.GetUnitAtOffset(DIERef::Section::DebugInfo
,
134 return &cu
->GetNonSkeletonUnit();
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
)
144 if (DWARFDIE die
= unit
->GetDIE(unit
->GetOffset() + *die_offset
))
147 m_module
.ReportErrorIfModifyDetected(
148 "the DWARF debug information has been modified (bad offset {0:x} in "
149 "debug_names section)\n",
154 bool DebugNamesDWARFIndex::ProcessEntry(
155 const DebugNames::Entry
&entry
,
156 llvm::function_ref
<bool(DWARFDIE die
)> callback
) {
157 DWARFDIE die
= GetDIE(entry
);
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))
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.
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
)
186 if (!ProcessEntry(entry
, callback
))
190 m_fallback
.GetGlobalVariables(basename
, callback
);
193 void DebugNamesDWARFIndex::GetGlobalVariables(
194 const RegularExpression
®ex
,
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
))
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
)
208 if (!ProcessEntry(*entry_or
, callback
))
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
) {
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
)
240 if (entry_or
->getCUOffset() != cu_offset
)
243 found_entry_for_cu
= true;
244 if (!ProcessEntry(*entry_or
, callback
))
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
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
)
269 DWARFDIE die
= GetDIE(entry
);
274 DWARFUnit
*cu
= die
.GetCU();
275 if (!cu
->Supports_DW_AT_APPLE_objc_complete_type()) {
276 incomplete_types
.push_back(die
);
280 if (die
.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type
, 0)) {
281 // If we find the complete version we're done.
285 incomplete_types
.push_back(die
);
288 for (DWARFDIE die
: incomplete_types
)
292 m_fallback
.GetCompleteObjCClass(class_name
, must_be_implementation
, callback
);
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
;
309 if (!entry
.hasParentInformation())
312 llvm::Expected
<std::optional
<Entry
>> parent
= entry
.getParentDIEEntry();
316 GetLog(DWARFLog::Lookups
), parent
.takeError(),
317 "Failed to extract parent entry from a non-empty IDX_parent");
321 // Last parent in the chain.
322 if (!parent
->has_value())
325 parent_entries
.push_back(**parent
);
327 } while (parent_entries
.size() < max_parents
);
329 return parent_entries
;
333 void DebugNamesDWARFIndex::GetFullyQualifiedType(
334 const DWARFDeclContext
&context
,
335 llvm::function_ref
<bool(DWARFDIE die
)> callback
) {
336 if (context
.GetSize() == 0)
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()))
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
353 std::optional
<DWARFTypeUnit
*> foreign_tu
= GetForeignTypeUnit(entry
);
354 if (foreign_tu
&& foreign_tu
.value() == nullptr)
357 // Grab at most one extra parent, subsequent parents are not necessary to
359 std::optional
<llvm::SmallVector
<Entry
, 4>> parent_chain
=
360 getParentChain(entry
, parent_names
.size() + 1);
363 // Fallback: use the base class implementation.
364 if (!ProcessEntry(entry
, [&](DWARFDIE die
) {
365 return GetFullyQualifiedTypeImpl(context
, die
, callback
);
371 if (SameParentChain(parent_names
, *parent_chain
)) {
372 if (!ProcessEntry(entry
, callback
))
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
)
387 DWARFUnit
*unit
= GetNonSkeletonUnit(entry
);
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())
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
)
407 DWARFUnit
*unit
= GetNonSkeletonUnit(entry
);
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
415 for (auto [parent_name
, parent_entry
] :
416 llvm::zip_equal(parent_names
, parent_entries
))
417 if (!SameAsEntryATName(parent_name
, parent_entry
))
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())
428 // If the AT_name of any parent fails to match the expected name, we don't
430 for (auto [parent_context
, parent_entry
] :
431 llvm::zip_equal(parent_contexts
, parent_entries
))
432 if (!SameAsEntryContext(parent_context
, parent_entry
))
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
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();
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
)
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
))
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
))
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
))
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
&&
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()))
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
543 std::optional
<DWARFTypeUnit
*> foreign_tu
= GetForeignTypeUnit(entry
);
544 if (foreign_tu
&& foreign_tu
.value() == nullptr)
547 std::optional
<llvm::SmallVector
<Entry
, 4>> parent_chain
=
548 getParentChain(entry
);
550 // Fallback: use the base class implementation.
551 if (!ProcessEntry(entry
, [&](DWARFDIE die
) {
552 return ProcessTypeDIEMatchQuery(query
, die
, callback
);
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.
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
);
588 // Fallback: use the base class implementation.
589 if (!ProcessEntry(entry
, [&](DWARFDIE die
) {
590 return ProcessNamespaceDieMatchParents(parent_decl_ctx
, die
,
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
,
604 // If the callback returns false, we're done.
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
)
624 if (DWARFDIE die
= GetDIE(entry
)) {
625 if (!ProcessFunctionDIE(lookup_info
, die
, parent_decl_ctx
,
627 if (!seen
.insert(die
.GetDIE()).second
)
629 return callback(die
);
635 m_fallback
.GetFunctions(lookup_info
, dwarf
, parent_decl_ctx
, callback
);
638 void DebugNamesDWARFIndex::GetFunctions(
639 const RegularExpression
®ex
,
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()))
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
)
653 if (!ProcessEntry(*entry_or
, callback
))
656 MaybeLogLookupError(entry_or
.takeError(), ni
, nte
.getString());
660 m_fallback
.GetFunctions(regex
, callback
);
663 void DebugNamesDWARFIndex::Dump(Stream
&s
) {
667 llvm::raw_string_ostream
os(data
);
668 m_debug_names_up
->dump(os
);