LLDB mainline
DebugNamesDWARFIndex.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
14#include "lldb/Core/Module.h"
16#include "lldb/Utility/Stream.h"
18#include "llvm/ADT/Sequence.h"
19#include <optional>
20
21using namespace lldb;
22using namespace lldb_private;
23using namespace lldb_private::plugin::dwarf;
24using namespace llvm::dwarf;
25
26llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
28 DWARFDataExtractor debug_str,
30 auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVMDWARF(),
31 debug_str.GetAsLLVM());
32 if (llvm::Error E = index_up->extract())
33 return std::move(E);
34
35 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
36 module, std::move(index_up), debug_names, debug_str, dwarf));
37}
38
39llvm::DenseSet<uint64_t>
41 llvm::DenseSet<uint64_t> result;
42 for (const DebugNames::NameIndex &ni : debug_names) {
43 const uint32_t num_tus = ni.getForeignTUCount();
44 for (uint32_t tu = 0; tu < num_tus; ++tu)
45 result.insert(ni.getForeignTUSignature(tu));
46 }
47 return result;
48}
49
50llvm::DenseSet<dw_offset_t>
52 llvm::DenseSet<dw_offset_t> result;
53 for (const DebugNames::NameIndex &ni : debug_names) {
54 const uint32_t num_cus = ni.getCUCount();
55 for (uint32_t cu = 0; cu < num_cus; ++cu)
56 result.insert(ni.getCUOffset(cu));
57 const uint32_t num_tus = ni.getLocalTUCount();
58 for (uint32_t tu = 0; tu < num_tus; ++tu)
59 result.insert(ni.getLocalTUOffset(tu));
60 }
61 return result;
62}
63
64std::optional<DWARFTypeUnit *>
65DebugNamesDWARFIndex::GetForeignTypeUnit(const DebugNames::Entry &entry) const {
66 std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature();
67 if (!type_sig.has_value())
68 return std::nullopt;
69
70 // Ask the entry for the skeleton compile unit offset and fetch the .dwo
71 // file from it and get the type unit by signature from there. If we find
72 // the type unit in the .dwo file, we don't need to check that the
73 // DW_AT_dwo_name matches because each .dwo file can have its own type unit.
74 std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset();
75 if (!cu_offset)
76 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
77
78 DWARFUnit *cu =
79 m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
80 if (!cu)
81 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
82
83 auto dwp_sp = m_debug_info.GetDwpSymbolFile();
84 if (!dwp_sp) {
85 // No .dwp file, we need to load the .dwo file.
86 DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit();
87 // We don't need the check if the type unit matches the .dwo file if we have
88 // a .dwo file (not a .dwp), so we can just return the value here.
89 if (!dwo_cu.IsDWOUnit())
90 return nullptr; // We weren't able to load the .dwo file.
92 *type_sig);
93 }
94 // We have a .dwp file, just get the type unit from there. We need to verify
95 // that the type unit that ended up in the final .dwp file is the right type
96 // unit. Type units have signatures which are the same across multiple .dwo
97 // files, but only one of those type units will end up in the .dwp file. The
98 // contents of type units for the same type can be different in different .dwo
99 // files, which means the DIE offsets might not be the same between two
100 // different type units. So we need to determine if this accelerator table
101 // matches the type unit that ended up in the .dwp file. If it doesn't match,
102 // then we need to ignore this accelerator table entry as the type unit that
103 // is in the .dwp file will have its own index. In order to determine if the
104 // type unit that ended up in a .dwp file matches this DebugNames::Entry, we
105 // need to find the skeleton compile unit for this entry.
106 DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
107 if (!foreign_tu)
108 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
109
110 DWARFBaseDIE cu_die = cu->GetUnitDIEOnly();
111 DWARFBaseDIE tu_die = foreign_tu->GetUnitDIEOnly();
112 llvm::StringRef cu_dwo_name =
113 cu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
114 llvm::StringRef tu_dwo_name =
115 tu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
116 if (cu_dwo_name == tu_dwo_name)
117 return foreign_tu; // We found a match!
118 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
119}
120
121DWARFUnit *
122DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {
123
124 if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry))
125 return foreign_tu.value();
126
127 // Look for a DWARF unit offset (CU offset or local TU offset) as they are
128 // both offsets into the .debug_info section.
129 std::optional<uint64_t> unit_offset = entry.getCUOffset();
130 if (!unit_offset)
131 unit_offset = entry.getLocalTUOffset();
132 if (unit_offset) {
133 if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo,
134 *unit_offset))
135 return &cu->GetNonSkeletonUnit();
136 }
137 return nullptr;
138}
139
140DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const {
141 DWARFUnit *unit = GetNonSkeletonUnit(entry);
142 std::optional<uint64_t> die_offset = entry.getDIEUnitOffset();
143 if (!unit || !die_offset)
144 return DWARFDIE();
145 if (DWARFDIE die = unit->GetDIE(unit->GetOffset() + *die_offset))
146 return die;
147
148 m_module.ReportErrorIfModifyDetected(
149 "the DWARF debug information has been modified (bad offset {0:x} in "
150 "debug_names section)\n",
151 *die_offset);
152 return DWARFDIE();
153}
154
156 const DebugNames::Entry &entry,
157 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
158 DWARFDIE die = GetDIE(entry);
159 if (!die)
161 // Clang used to erroneously emit index entries for declaration DIEs in case
162 // when the definition is in a type unit (llvm.org/pr77696).
163 if (die.IsStructUnionOrClass() &&
164 die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
166 return callback(die);
167}
168
170 const DebugNames::NameIndex &ni,
171 llvm::StringRef name) {
172 // Ignore SentinelErrors, log everything else.
175 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
176 "Failed to parse index entries for index at {1:x}, name {2}: {0}",
177 ni.getUnitOffset(), name);
178}
179
181 ConstString basename,
182 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
183 for (const DebugNames::Entry &entry :
184 m_debug_names_up->equal_range(basename.GetStringRef())) {
185 if (entry.tag() != DW_TAG_variable)
186 continue;
187
188 if (ProcessEntry(entry, callback) == IterationAction::Stop)
189 return;
190 }
191
192 m_fallback.GetGlobalVariables(basename, callback);
193}
194
196 const RegularExpression &regex,
197 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
198 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
199 for (DebugNames::NameTableEntry nte: ni) {
200 Mangled mangled_name(nte.getString());
201 if (!mangled_name.NameMatches(regex))
202 continue;
203
204 uint64_t entry_offset = nte.getEntryOffset();
205 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
206 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
207 if (entry_or->tag() != DW_TAG_variable)
208 continue;
209
210 if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
211 return;
212 }
213 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
214 }
215 }
216
217 m_fallback.GetGlobalVariables(regex, callback);
218}
219
221 DWARFUnit &cu, llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
222 uint64_t cu_offset = cu.GetOffset();
223 bool found_entry_for_cu = false;
224 for (const DebugNames::NameIndex &ni : *m_debug_names_up) {
225 // Check if this name index contains an entry for the given CU.
226 bool cu_matches = false;
227 for (uint32_t i = 0; i < ni.getCUCount(); ++i) {
228 if (ni.getCUOffset(i) == cu_offset) {
229 cu_matches = true;
230 break;
231 }
232 }
233 if (!cu_matches)
234 continue;
235
236 for (DebugNames::NameTableEntry nte : ni) {
237 uint64_t entry_offset = nte.getEntryOffset();
238 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
239 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
240 if (entry_or->tag() != DW_TAG_variable)
241 continue;
242 if (entry_or->getCUOffset() != cu_offset)
243 continue;
244
245 found_entry_for_cu = true;
246 if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
247 return;
248 }
249 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
250 }
251 }
252 // If no name index for that particular CU was found, fallback to
253 // creating the manual index.
254 if (!found_entry_for_cu)
255 m_fallback.GetGlobalVariables(cu, callback);
256}
257
259 ConstString class_name, bool must_be_implementation,
260 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
261 // Keep a list of incomplete types as fallback for when we don't find the
262 // complete type.
263 std::vector<DWARFDIE> incomplete_types;
264
265 for (const DebugNames::Entry &entry :
266 m_debug_names_up->equal_range(class_name.GetStringRef())) {
267 if (entry.tag() != DW_TAG_structure_type &&
268 entry.tag() != DW_TAG_class_type)
269 continue;
270
271 DWARFDIE die = GetDIE(entry);
272 if (!die) {
273 // Report invalid
274 continue;
275 }
276
277 if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
278 // If we find the complete version we're done.
279 callback(die);
280 return;
281 }
282 incomplete_types.push_back(die);
283 }
284
285 for (DWARFDIE die : incomplete_types)
286 if (callback(die) == IterationAction::Stop)
287 return;
288
289 m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
290}
291
292namespace {
293using Entry = llvm::DWARFDebugNames::Entry;
294
295/// If `entry` and all of its parents have an `IDX_parent`, use that information
296/// to build and return a list of at most `max_parents` parent Entries.
297/// `entry` itself is not included in the list.
298/// If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
299/// nullopt is returned.
300std::optional<llvm::SmallVector<Entry, 4>>
301getParentChain(Entry entry,
302 uint32_t max_parents = std::numeric_limits<uint32_t>::max()) {
303 llvm::SmallVector<Entry, 4> parent_entries;
304
305 do {
306 if (!entry.hasParentInformation())
307 return std::nullopt;
308
309 llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
310 if (!parent) {
311 // Bad data.
313 GetLog(DWARFLog::Lookups), parent.takeError(),
314 "Failed to extract parent entry from a non-empty IDX_parent");
315 return std::nullopt;
316 }
317
318 // Last parent in the chain.
319 if (!parent->has_value())
320 break;
321
322 parent_entries.push_back(**parent);
323 entry = **parent;
324 } while (parent_entries.size() < max_parents);
325
326 return parent_entries;
327}
328} // namespace
329
331 const DWARFDeclContext &context,
332 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
333 if (context.GetSize() == 0)
334 return;
335
336 llvm::StringRef leaf_name = context[0].name;
337 llvm::SmallVector<llvm::StringRef> parent_names;
338 for (auto idx : llvm::seq<int>(1, context.GetSize()))
339 parent_names.emplace_back(context[idx].name);
340
341 // For each entry, grab its parent chain and check if we have a match.
342 for (const DebugNames::Entry &entry :
343 m_debug_names_up->equal_range(leaf_name)) {
344 if (!isType(entry.tag()))
345 continue;
346
347 // If we get a NULL foreign_tu back, the entry doesn't match the type unit
348 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
349 // didn't match.
350 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
351 if (foreign_tu && foreign_tu.value() == nullptr)
352 continue;
353
354 // Grab at most one extra parent, subsequent parents are not necessary to
355 // test equality.
356 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
357 getParentChain(entry, parent_names.size() + 1);
358
359 if (!parent_chain) {
360 // Fallback: use the base class implementation.
361 if (ProcessEntry(entry, [&](DWARFDIE die) {
362 return GetFullyQualifiedTypeImpl(context, die, callback);
364 return;
365 continue;
366 }
367
368 if (SameParentChain(parent_names, *parent_chain)) {
369 if (ProcessEntry(entry, callback) == IterationAction::Stop)
370 return;
371 }
372 }
373 m_fallback.GetFullyQualifiedType(context, callback);
374}
375
377 const CompilerContext &query_context,
378 const DebugNames::Entry &entry) const {
379 // TODO: check dwarf tag matches.
380 // Peek at the AT_name of `entry` and test equality to `name`.
381 auto maybe_dieoffset = entry.getDIEUnitOffset();
382 if (!maybe_dieoffset)
383 return false;
384 DWARFUnit *unit = GetNonSkeletonUnit(entry);
385 if (!unit)
386 return false;
387 return query_context.name ==
388 unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
389}
390
392 llvm::ArrayRef<llvm::StringRef> parent_names,
393 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
394
395 if (parent_entries.size() != parent_names.size())
396 return false;
397
398 auto SameAsEntryATName = [this](llvm::StringRef name,
399 const DebugNames::Entry &entry) {
400 // Peek at the AT_name of `entry` and test equality to `name`.
401 auto maybe_dieoffset = entry.getDIEUnitOffset();
402 if (!maybe_dieoffset)
403 return false;
404 DWARFUnit *unit = GetNonSkeletonUnit(entry);
405 if (!unit)
406 return false;
407 return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
408 };
409
410 // If the AT_name of any parent fails to match the expected name, we don't
411 // have a match.
412 for (auto [parent_name, parent_entry] :
413 llvm::zip_equal(parent_names, parent_entries))
414 if (!SameAsEntryATName(parent_name, parent_entry))
415 return false;
416 return true;
417}
418
420 llvm::ArrayRef<CompilerContext> parent_contexts,
421 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
422 if (parent_entries.size() != parent_contexts.size())
423 return false;
424
425 // If the AT_name of any parent fails to match the expected name, we don't
426 // have a match.
427 for (auto [parent_context, parent_entry] :
428 llvm::zip_equal(parent_contexts, parent_entries))
429 if (!SameAsEntryContext(parent_context, parent_entry))
430 return false;
431 return true;
432}
433
435 llvm::ArrayRef<CompilerContext> query_contexts,
436 llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
437 if (query_contexts.size() == parent_chain.size())
438 return SameParentChain(query_contexts, parent_chain);
439
440 // If parent chain does not have enough entries, we can't possibly have a
441 // match.
442 while (!query_contexts.empty() &&
443 query_contexts.size() <= parent_chain.size()) {
444 if (SameAsEntryContext(query_contexts.front(), parent_chain.front())) {
445 query_contexts = query_contexts.drop_front();
446 parent_chain = parent_chain.drop_front();
447 } else {
448 // Name does not match, try next parent_chain entry if the current entry
449 // is namespace because the current one can be an inline namespace.
450 if (parent_chain.front().tag() != DW_TAG_namespace)
451 return false;
452 parent_chain = parent_chain.drop_front();
453 }
454 }
455 return query_contexts.empty();
456}
457
459 ConstString name,
460 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
461 for (const DebugNames::Entry &entry :
462 m_debug_names_up->equal_range(name.GetStringRef())) {
463 if (isType(entry.tag())) {
464 if (ProcessEntry(entry, callback) == IterationAction::Stop)
465 return;
466 }
467 }
468
469 m_fallback.GetTypes(name, callback);
470}
471
473 const DWARFDeclContext &context,
474 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
475 auto name = context[0].name;
476 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
477 if (entry.tag() == context[0].tag) {
478 if (ProcessEntry(entry, callback) == IterationAction::Stop)
479 return;
480 }
481 }
482
483 m_fallback.GetTypes(context, callback);
484}
485
487 ConstString name,
488 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
489 for (const DebugNames::Entry &entry :
490 m_debug_names_up->equal_range(name.GetStringRef())) {
491 llvm::dwarf::Tag entry_tag = entry.tag();
492 if (entry_tag == DW_TAG_namespace ||
493 entry_tag == DW_TAG_imported_declaration) {
494 if (ProcessEntry(entry, callback) == IterationAction::Stop)
495 return;
496 }
497 }
498
499 m_fallback.GetNamespaces(name, callback);
500}
501
502llvm::SmallVector<CompilerContext>
504 std::vector<lldb_private::CompilerContext> &query_decl_context =
505 query.GetContextRef();
506 llvm::SmallVector<CompilerContext> parent_contexts;
507 if (!query_decl_context.empty()) {
508 // Skip the last entry as it's the type we're matching parents for.
509 // Reverse the query decl context to match parent chain order.
510 llvm::ArrayRef<CompilerContext> parent_contexts_ref(
511 query_decl_context.data(), query_decl_context.size() - 1);
512 for (const CompilerContext &ctx : llvm::reverse(parent_contexts_ref)) {
513 // Skip any context without name because .debug_names might not encode
514 // them. (e.g. annonymous namespace)
515 if ((ctx.kind & CompilerContextKind::AnyType) !=
517 !ctx.name.IsEmpty())
518 parent_contexts.push_back(ctx);
519 }
520 }
521 return parent_contexts;
522}
523
525 TypeQuery &query,
526 llvm::function_ref<IterationAction(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 && !query.GetExactMatch())
531 return GetTypes(name, callback);
532
533 llvm::SmallVector<CompilerContext> parent_contexts =
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;
539
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;
546
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;
556 }
557
558 if (WithinParentChain(parent_contexts, *parent_chain)) {
559 if (ProcessEntry(entry, [&](DWARFDIE die) {
560 // After .debug_names filtering still sending to base
561 // class for further filtering before calling the
562 // callback.
563 return ProcessTypeDIEMatchQuery(query, die, callback);
565 return;
566 }
567 }
568 m_fallback.GetTypesWithQuery(query, callback);
569}
570
572 ConstString name, const CompilerDeclContext &parent_decl_ctx,
573 llvm::function_ref<IterationAction(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 llvm::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;
595 }
596
597 if (WithinParentChain(parent_named_contexts, *parent_chain)) {
598 if (ProcessEntry(entry, [&](DWARFDIE die) {
599 // After .debug_names filtering still sending to
600 // base class for further filtering before calling
601 // the callback.
602 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
603 callback);
605 return;
606 }
607 }
608 }
609 m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
610}
611
613 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
614 const CompilerDeclContext &parent_decl_ctx,
615 llvm::function_ref<IterationAction(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;
623
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)
629 return callback(die);
631 return;
632 }
633 }
634
635 m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
636}
637
639 const RegularExpression &regex,
640 llvm::function_ref<IterationAction(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;
645
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;
652
653 if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
654 return;
655 }
656 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
657 }
658 }
659
660 m_fallback.GetFunctions(regex, callback);
661}
662
664 m_fallback.Dump(s);
665
666 std::string data;
667 llvm::raw_string_ostream os(data);
668 m_debug_names_up->dump(os);
669 s.PutCString(data);
670}
static llvm::raw_ostream & error(Stream &strm)
FormatEntity::Entry Entry
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
Represents a generic declaration context in a program.
std::vector< lldb_private::CompilerContext > GetCompilerContext() const
Populate a valid compiler context from the current decl context.
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
llvm::DWARFDataExtractor GetAsLLVMDWARF() const
llvm::DataExtractor GetAsLLVM() const
A class that handles mangled names.
Definition Mangled.h:34
bool NameMatches(ConstString name) const
Check if "name" matches either the mangled or demangled name.
Definition Mangled.h:178
A class that encapsulates name lookup information.
Definition Module.h:916
ConstString GetLookupName() const
Definition Module.h:927
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:90
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
A class that contains all state required for type lookups.
Definition Type.h:104
std::vector< lldb_private::CompilerContext > & GetContextRef()
Access the internal compiler context array.
Definition Type.h:322
bool GetExactMatch() const
Definition Type.h:270
ConstString GetTypeBasename() const
Get the type basename to use when searching the type indexes in each SymbolFile object.
Definition Type.cpp:113
const char * GetAttributeValueAsString(const dw_attr_t attr, const char *fail_value) const
uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition DWARFDIE.cpp:126
DWARFTypeUnit * GetTypeUnitForHash(uint64_t hash)
IterationAction GetFullyQualifiedTypeImpl(const DWARFDeclContext &context, DWARFDIE die, llvm::function_ref< IterationAction(DWARFDIE die)> callback)
Implementation of GetFullyQualifiedType to check a single entry, shareable with derived classes.
IterationAction ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< IterationAction(DWARFDIE die)> callback)
Helper function implementing common logic for processing function dies.
IterationAction ProcessTypeDIEMatchQuery(TypeQuery &query, DWARFDIE die, llvm::function_ref< IterationAction(DWARFDIE die)> callback)
Check if the type die can meet the requirements of query.
IterationAction ProcessNamespaceDieMatchParents(const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, llvm::function_ref< IterationAction(DWARFDIE die)> callback)
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition DWARFUnit.h:200
llvm::StringRef PeekDIEName(dw_offset_t die_offset)
Returns the AT_Name of the DIE at die_offset, if it exists, without parsing the entire compile unit.
DWARFDIE GetDIE(dw_offset_t die_offset)
llvm::SmallVector< CompilerContext > GetTypeQueryParentContexts(TypeQuery &query)
DebugNamesDWARFIndex(Module &module, std::unique_ptr< llvm::DWARFDebugNames > debug_names_up, DWARFDataExtractor debug_names_data, DWARFDataExtractor debug_str_data, SymbolFileDWARF &dwarf)
static llvm::Expected< std::unique_ptr< DebugNamesDWARFIndex > > Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, SymbolFileDWARF &dwarf)
IterationAction ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< IterationAction(DWARFDIE die)> callback)
void GetTypes(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
static llvm::DenseSet< uint64_t > GetTypeUnitSignatures(const DebugNames &debug_names)
static void MaybeLogLookupError(llvm::Error error, const DebugNames::NameIndex &ni, llvm::StringRef name)
DWARFDIE GetDIE(const DebugNames::Entry &entry) const
std::optional< DWARFTypeUnit * > GetForeignTypeUnit(const DebugNames::Entry &entry) const
Checks if an entry is a foreign TU and fetch the type unit.
bool WithinParentChain(llvm::ArrayRef< CompilerContext > parent_contexts, llvm::ArrayRef< DebugNames::Entry > parent_chain) const
Returns true if parent_contexts entries are within parent_chain.
void GetFullyQualifiedType(const DWARFDeclContext &context, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Uses DWARF5's IDX_parent fields, when available, to speed up this query.
void GetTypesWithQuery(TypeQuery &query, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Get type DIEs meeting requires of query.
void GetNamespacesWithParents(ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Get namespace DIEs whose base name match.
void GetNamespaces(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
bool SameAsEntryContext(const CompilerContext &query_context, const DebugNames::Entry &entry) const
Returns true if .debug_names pool entry entry matches query_context.
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void GetGlobalVariables(ConstString basename, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
bool SameParentChain(llvm::ArrayRef< llvm::StringRef > parent_names, llvm::ArrayRef< DebugNames::Entry > parent_entries) const
Returns true if parent_entries have identical names to parent_names.
static llvm::DenseSet< dw_offset_t > GetUnits(const DebugNames &debug_names)
DWARFUnit * GetNonSkeletonUnit(const DebugNames::Entry &entry) const
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
IterationAction
Useful for callbacks whose return type indicates whether to continue iteration or short-circuit.
CompilerContext allows an array of these items to be passed to perform detailed lookups in SymbolVend...
Definition Type.h:52