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"
17#include "llvm/ADT/Sequence.h"
18#include <optional>
19
20using namespace lldb_private;
21using namespace lldb;
22using namespace lldb_private::dwarf;
23using namespace lldb_private::plugin::dwarf;
24
25llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
27 DWARFDataExtractor debug_str,
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);
33
34 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
35 module, std::move(index_up), debug_names, debug_str, dwarf));
36}
37
38llvm::DenseSet<uint64_t>
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));
45 }
46 return result;
47}
48
49llvm::DenseSet<dw_offset_t>
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));
59 }
60 return result;
61}
62
63std::optional<DWARFTypeUnit *>
64DebugNamesDWARFIndex::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;
68
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.
76
77 DWARFUnit *cu =
79 if (!cu)
80 return nullptr; // Return NULL, this is a type unit, but couldn't find it.
81
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.
91 *type_sig);
92 }
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.
108
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.
118}
119
120DWARFUnit *
121DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {
122
123 if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry))
124 return foreign_tu.value();
125
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) {
133 *unit_offset))
134 return &cu->GetNonSkeletonUnit();
135 }
136 return nullptr;
137}
138
139DWARFDIE 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;
146
148 "the DWARF debug information has been modified (bad offset {0:x} in "
149 "debug_names section)\n",
150 *die_offset);
151 return DWARFDIE();
152}
153
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);
166}
167
169 const DebugNames::NameIndex &ni,
170 llvm::StringRef name) {
171 // Ignore SentinelErrors, log everything else.
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);
177}
178
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;
185
186 if (!ProcessEntry(entry, callback))
187 return;
188 }
189
190 m_fallback.GetGlobalVariables(basename, callback);
191}
192
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;
201
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;
207
208 if (!ProcessEntry(*entry_or, callback))
209 return;
210 }
211 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
212 }
213 }
214
215 m_fallback.GetGlobalVariables(regex, callback);
216}
217
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;
229 }
230 }
231 if (!cu_matches)
232 continue;
233
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;
242
243 found_entry_for_cu = true;
244 if (!ProcessEntry(*entry_or, callback))
245 return;
246 }
247 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
248 }
249 }
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);
254}
255
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;
262
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;
268
269 DWARFDIE die = GetDIE(entry);
270 if (!die) {
271 // Report invalid
272 continue;
273 }
274
275 if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
276 // If we find the complete version we're done.
277 callback(die);
278 return;
279 }
280 incomplete_types.push_back(die);
281 }
282
283 for (DWARFDIE die : incomplete_types)
284 if (!callback(die))
285 return;
286
287 m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
288}
289
290namespace {
291using Entry = llvm::DWARFDebugNames::Entry;
292
293/// If `entry` and all of its parents have an `IDX_parent`, use that information
294/// to build and return a list of at most `max_parents` parent Entries.
295/// `entry` itself is not included in the list.
296/// If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
297/// nullopt is returned.
298std::optional<llvm::SmallVector<Entry, 4>>
299getParentChain(Entry entry,
300 uint32_t max_parents = std::numeric_limits<uint32_t>::max()) {
301 llvm::SmallVector<Entry, 4> parent_entries;
302
303 do {
304 if (!entry.hasParentInformation())
305 return std::nullopt;
306
307 llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
308 if (!parent) {
309 // Bad data.
311 GetLog(DWARFLog::Lookups), parent.takeError(),
312 "Failed to extract parent entry from a non-empty IDX_parent");
313 return std::nullopt;
314 }
315
316 // Last parent in the chain.
317 if (!parent->has_value())
318 break;
319
320 parent_entries.push_back(**parent);
321 entry = **parent;
322 } while (parent_entries.size() < max_parents);
323
324 return parent_entries;
325}
326} // namespace
327
329 const DWARFDeclContext &context,
330 llvm::function_ref<bool(DWARFDIE die)> callback) {
331 if (context.GetSize() == 0)
332 return;
333
334 llvm::StringRef leaf_name = context[0].name;
335 llvm::SmallVector<llvm::StringRef> parent_names;
336 for (auto idx : llvm::seq<int>(1, context.GetSize()))
337 parent_names.emplace_back(context[idx].name);
338
339 // For each entry, grab its parent chain and check if we have a match.
340 for (const DebugNames::Entry &entry :
341 m_debug_names_up->equal_range(leaf_name)) {
342 if (!isType(entry.tag()))
343 continue;
344
345 // If we get a NULL foreign_tu back, the entry doesn't match the type unit
346 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
347 // didn't match.
348 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
349 if (foreign_tu && foreign_tu.value() == nullptr)
350 continue;
351
352 // Grab at most one extra parent, subsequent parents are not necessary to
353 // test equality.
354 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
355 getParentChain(entry, parent_names.size() + 1);
356
357 if (!parent_chain) {
358 // Fallback: use the base class implementation.
359 if (!ProcessEntry(entry, [&](DWARFDIE die) {
360 return GetFullyQualifiedTypeImpl(context, die, callback);
361 }))
362 return;
363 continue;
364 }
365
366 if (SameParentChain(parent_names, *parent_chain)) {
367 if (!ProcessEntry(entry, callback))
368 return;
369 }
370 }
371 m_fallback.GetFullyQualifiedType(context, callback);
372}
373
375 const CompilerContext &query_context,
376 const DebugNames::Entry &entry) const {
377 // TODO: check dwarf tag matches.
378 // Peek at the AT_name of `entry` and test equality to `name`.
379 auto maybe_dieoffset = entry.getDIEUnitOffset();
380 if (!maybe_dieoffset)
381 return false;
382 DWARFUnit *unit = GetNonSkeletonUnit(entry);
383 if (!unit)
384 return false;
385 return query_context.name ==
386 unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
387}
388
390 llvm::ArrayRef<llvm::StringRef> parent_names,
391 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
392
393 if (parent_entries.size() != parent_names.size())
394 return false;
395
396 auto SameAsEntryATName = [this](llvm::StringRef name,
397 const DebugNames::Entry &entry) {
398 // Peek at the AT_name of `entry` and test equality to `name`.
399 auto maybe_dieoffset = entry.getDIEUnitOffset();
400 if (!maybe_dieoffset)
401 return false;
402 DWARFUnit *unit = GetNonSkeletonUnit(entry);
403 if (!unit)
404 return false;
405 return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
406 };
407
408 // If the AT_name of any parent fails to match the expected name, we don't
409 // have a match.
410 for (auto [parent_name, parent_entry] :
411 llvm::zip_equal(parent_names, parent_entries))
412 if (!SameAsEntryATName(parent_name, parent_entry))
413 return false;
414 return true;
415}
416
418 llvm::ArrayRef<CompilerContext> parent_contexts,
419 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
420 if (parent_entries.size() != parent_contexts.size())
421 return false;
422
423 // If the AT_name of any parent fails to match the expected name, we don't
424 // have a match.
425 for (auto [parent_context, parent_entry] :
426 llvm::zip_equal(parent_contexts, parent_entries))
427 if (!SameAsEntryContext(parent_context, parent_entry))
428 return false;
429 return true;
430}
431
433 llvm::ArrayRef<CompilerContext> query_contexts,
434 llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
435 if (query_contexts.size() == parent_chain.size())
436 return SameParentChain(query_contexts, parent_chain);
437
438 // If parent chain does not have enough entries, we can't possibly have a
439 // match.
440 while (!query_contexts.empty() &&
441 query_contexts.size() <= parent_chain.size()) {
442 if (SameAsEntryContext(query_contexts.front(), parent_chain.front())) {
443 query_contexts = query_contexts.drop_front();
444 parent_chain = parent_chain.drop_front();
445 } else {
446 // Name does not match, try next parent_chain entry if the current entry
447 // is namespace because the current one can be an inline namespace.
448 if (parent_chain.front().tag() != DW_TAG_namespace)
449 return false;
450 parent_chain = parent_chain.drop_front();
451 }
452 }
453 return query_contexts.empty();
454}
455
457 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
458 for (const DebugNames::Entry &entry :
459 m_debug_names_up->equal_range(name.GetStringRef())) {
460 if (isType(entry.tag())) {
461 if (!ProcessEntry(entry, callback))
462 return;
463 }
464 }
465
466 m_fallback.GetTypes(name, callback);
467}
468
470 const DWARFDeclContext &context,
471 llvm::function_ref<bool(DWARFDIE die)> callback) {
472 auto name = context[0].name;
473 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
474 if (entry.tag() == context[0].tag) {
475 if (!ProcessEntry(entry, callback))
476 return;
477 }
478 }
479
480 m_fallback.GetTypes(context, callback);
481}
482
484 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
485 for (const DebugNames::Entry &entry :
486 m_debug_names_up->equal_range(name.GetStringRef())) {
487 lldb_private::dwarf::Tag entry_tag = entry.tag();
488 if (entry_tag == DW_TAG_namespace ||
489 entry_tag == DW_TAG_imported_declaration) {
490 if (!ProcessEntry(entry, callback))
491 return;
492 }
493 }
494
495 m_fallback.GetNamespaces(name, callback);
496}
497
498llvm::SmallVector<CompilerContext>
500 std::vector<lldb_private::CompilerContext> &query_decl_context =
501 query.GetContextRef();
502 llvm::SmallVector<CompilerContext> parent_contexts;
503 if (!query_decl_context.empty()) {
504 // Skip the last entry as it's the type we're matching parents for.
505 // Reverse the query decl context to match parent chain order.
506 llvm::ArrayRef<CompilerContext> parent_contexts_ref(
507 query_decl_context.data(), query_decl_context.size() - 1);
508 for (const CompilerContext &ctx : llvm::reverse(parent_contexts_ref)) {
509 // Skip any context without name because .debug_names might not encode
510 // them. (e.g. annonymous namespace)
511 if ((ctx.kind & CompilerContextKind::AnyType) !=
513 !ctx.name.IsEmpty())
514 parent_contexts.push_back(ctx);
515 }
516 }
517 return parent_contexts;
518}
519
521 TypeQuery &query, llvm::function_ref<bool(DWARFDIE die)> callback) {
522 ConstString name = query.GetTypeBasename();
523 std::vector<lldb_private::CompilerContext> query_context =
524 query.GetContextRef();
525 if (query_context.size() <= 1 && !query.GetExactMatch())
526 return GetTypes(name, callback);
527
528 llvm::SmallVector<CompilerContext> parent_contexts =
530 // For each entry, grab its parent chain and check if we have a match.
531 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
532 if (!isType(entry.tag()))
533 continue;
534
535 // If we get a NULL foreign_tu back, the entry doesn't match the type unit
536 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
537 // didn't match.
538 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
539 if (foreign_tu && foreign_tu.value() == nullptr)
540 continue;
541
542 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
543 getParentChain(entry);
544 if (!parent_chain) {
545 // Fallback: use the base class implementation.
546 if (!ProcessEntry(entry, [&](DWARFDIE die) {
547 return ProcessTypeDIEMatchQuery(query, die, callback);
548 }))
549 return;
550 continue;
551 }
552
553 if (WithinParentChain(parent_contexts, *parent_chain)) {
554 if (!ProcessEntry(entry, [&](DWARFDIE die) {
555 // After .debug_names filtering still sending to base class for
556 // further filtering before calling the callback.
557 return ProcessTypeDIEMatchQuery(query, die, callback);
558 }))
559 // If the callback returns false, we're done.
560 return;
561 }
562 }
563 m_fallback.GetTypesWithQuery(query, callback);
564}
565
567 ConstString name, const CompilerDeclContext &parent_decl_ctx,
568 llvm::function_ref<bool(DWARFDIE die)> callback) {
569 std::vector<lldb_private::CompilerContext> parent_contexts =
570 parent_decl_ctx.GetCompilerContext();
571 llvm::SmallVector<CompilerContext> parent_named_contexts;
572 std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
573 std::back_inserter(parent_named_contexts),
574 [](const CompilerContext &ctx) { return !ctx.name.IsEmpty(); });
575 for (const DebugNames::Entry &entry :
576 m_debug_names_up->equal_range(name.GetStringRef())) {
577 lldb_private::dwarf::Tag entry_tag = entry.tag();
578 if (entry_tag == DW_TAG_namespace ||
579 entry_tag == DW_TAG_imported_declaration) {
580 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
581 getParentChain(entry);
582 if (!parent_chain) {
583 // Fallback: use the base class implementation.
584 if (!ProcessEntry(entry, [&](DWARFDIE die) {
585 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
586 callback);
587 }))
588 return;
589 continue;
590 }
591
592 if (WithinParentChain(parent_named_contexts, *parent_chain)) {
593 if (!ProcessEntry(entry, [&](DWARFDIE die) {
594 // After .debug_names filtering still sending to base class for
595 // further filtering before calling the callback.
596 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
597 callback);
598 }))
599 // If the callback returns false, we're done.
600 return;
601 }
602 }
603 }
604 m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
605}
606
608 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
609 const CompilerDeclContext &parent_decl_ctx,
610 llvm::function_ref<bool(DWARFDIE die)> callback) {
611 ConstString name = lookup_info.GetLookupName();
612 std::set<DWARFDebugInfoEntry *> seen;
613 for (const DebugNames::Entry &entry :
614 m_debug_names_up->equal_range(name.GetStringRef())) {
615 Tag tag = entry.tag();
616 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
617 continue;
618
619 if (DWARFDIE die = GetDIE(entry)) {
620 if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx,
621 [&](DWARFDIE die) {
622 if (!seen.insert(die.GetDIE()).second)
623 return true;
624 return callback(die);
625 }))
626 return;
627 }
628 }
629
630 m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
631}
632
634 const RegularExpression &regex,
635 llvm::function_ref<bool(DWARFDIE die)> callback) {
636 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
637 for (DebugNames::NameTableEntry nte: ni) {
638 if (!regex.Execute(nte.getString()))
639 continue;
640
641 uint64_t entry_offset = nte.getEntryOffset();
642 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
643 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
644 Tag tag = entry_or->tag();
645 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
646 continue;
647
648 if (!ProcessEntry(*entry_or, callback))
649 return;
650 }
651 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
652 }
653 }
654
655 m_fallback.GetFunctions(regex, callback);
656}
657
659 m_fallback.Dump(s);
660
661 std::string data;
662 llvm::raw_string_ostream os(data);
663 m_debug_names_up->dump(os);
664 s.PutCString(data);
665}
static llvm::raw_ostream & error(Stream &strm)
#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.
Definition: ConstString.h:197
llvm::DWARFDataExtractor GetAsLLVMDWARF() const
llvm::DataExtractor GetAsLLVM() const
A class that handles mangled names.
Definition: Mangled.h:33
bool NameMatches(ConstString name) const
Check if "name" matches either the mangled or demangled name.
Definition: Mangled.h:171
A class that encapsulates name lookup information.
Definition: Module.h:907
ConstString GetLookupName() const
Definition: Module.h:918
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:89
void ReportErrorIfModifyDetected(const char *format, Args &&...args)
Definition: Module.h:808
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:112
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:124
const std::shared_ptr< SymbolFileDWARFDwo > & GetDwpSymbolFile()
DWARFTypeUnit * GetTypeUnitForHash(uint64_t hash)
DWARFUnit * GetUnitAtOffset(DIERef::Section section, dw_offset_t cu_offset, uint32_t *idx_ptr=nullptr)
bool ProcessTypeDIEMatchQuery(TypeQuery &query, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
Check if the type die can meet the requirements of query.
Definition: DWARFIndex.cpp:137
bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback)
Helper function implementing common logic for processing function dies.
Definition: DWARFIndex.cpp:26
virtual void GetNamespacesWithParents(ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback)
Get namespace DIEs whose base name match.
Definition: DWARFIndex.cpp:165
virtual void GetFullyQualifiedType(const DWARFDeclContext &context, llvm::function_ref< bool(DWARFDIE die)> callback)
Finds all DIEs whose fully qualified name matches context.
Definition: DWARFIndex.cpp:113
bool ProcessNamespaceDieMatchParents(const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
Definition: DWARFIndex.cpp:173
virtual void GetTypesWithQuery(TypeQuery &query, llvm::function_ref< bool(DWARFDIE die)> callback)
Get type DIEs meeting requires of query.
Definition: DWARFIndex.cpp:130
bool GetFullyQualifiedTypeImpl(const DWARFDeclContext &context, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
Implementation of GetFullyQualifiedType to check a single entry, shareable with derived classes.
Definition: DWARFIndex.cpp:121
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition: DWARFUnit.h:177
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.
Definition: DWARFUnit.cpp:675
DWARFDIE GetDIE(dw_offset_t die_offset)
Definition: DWARFUnit.cpp:654
llvm::SmallVector< CompilerContext > GetTypeQueryParentContexts(TypeQuery &query)
static llvm::Expected< std::unique_ptr< DebugNamesDWARFIndex > > Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, SymbolFileDWARF &dwarf)
void GetTypesWithQuery(TypeQuery &query, llvm::function_ref< bool(DWARFDIE die)> callback) override
Get type DIEs meeting requires of query.
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 GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetNamespacesWithParents(ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback) override
Get namespace DIEs whose base name match.
void GetFullyQualifiedType(const DWARFDeclContext &context, llvm::function_ref< bool(DWARFDIE die)> callback) override
Uses DWARF5's IDX_parent fields, when available, to speed up this query.
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< bool(DWARFDIE die)> callback)
bool SameAsEntryContext(const CompilerContext &query_context, const DebugNames::Entry &entry) const
Returns true if .debug_names pool entry entry matches query_context.
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(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
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
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
Definition: SBAddress.h:15
CompilerContext allows an array of these items to be passed to perform detailed lookups in SymbolVend...
Definition: Type.h:52