@@ -301,7 +301,8 @@ using Entry = llvm::DWARFDebugNames::Entry;
301
301
// / If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
302
302
// / nullopt is returned.
303
303
std::optional<llvm::SmallVector<Entry, 4 >>
304
- getParentChain (Entry entry, uint32_t max_parents) {
304
+ getParentChain (Entry entry,
305
+ uint32_t max_parents = std::numeric_limits<uint32_t >::max()) {
305
306
llvm::SmallVector<Entry, 4 > parent_entries;
306
307
307
308
do {
@@ -374,6 +375,21 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
374
375
m_fallback.GetFullyQualifiedType (context, callback);
375
376
}
376
377
378
+ bool DebugNamesDWARFIndex::SameAsEntryContext (
379
+ const CompilerContext &query_context,
380
+ const DebugNames::Entry &entry) const {
381
+ // TODO: check dwarf tag matches.
382
+ // Peek at the AT_name of `entry` and test equality to `name`.
383
+ auto maybe_dieoffset = entry.getDIEUnitOffset ();
384
+ if (!maybe_dieoffset)
385
+ return false ;
386
+ DWARFUnit *unit = GetNonSkeletonUnit (entry);
387
+ if (!unit)
388
+ return false ;
389
+ return query_context.name ==
390
+ unit->PeekDIEName (unit->GetOffset () + *maybe_dieoffset);
391
+ }
392
+
377
393
bool DebugNamesDWARFIndex::SameParentChain (
378
394
llvm::ArrayRef<llvm::StringRef> parent_names,
379
395
llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
@@ -402,6 +418,49 @@ bool DebugNamesDWARFIndex::SameParentChain(
402
418
return true ;
403
419
}
404
420
421
+ bool DebugNamesDWARFIndex::SameParentChain (
422
+ llvm::ArrayRef<CompilerContext> parent_contexts,
423
+ llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
424
+ if (parent_entries.size () != parent_contexts.size ())
425
+ return false ;
426
+
427
+ // If the AT_name of any parent fails to match the expected name, we don't
428
+ // have a match.
429
+ for (auto [parent_context, parent_entry] :
430
+ llvm::zip_equal (parent_contexts, parent_entries))
431
+ if (!SameAsEntryContext (parent_context, parent_entry))
432
+ return false ;
433
+ return true ;
434
+ }
435
+
436
+ bool DebugNamesDWARFIndex::WithinParentChain (
437
+ llvm::ArrayRef<CompilerContext> query_contexts,
438
+ llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
439
+ if (query_contexts.size () == parent_chain.size ())
440
+ return SameParentChain (query_contexts, parent_chain);
441
+
442
+ size_t query_idx = 0 , chain_idx = 0 ;
443
+ while (query_idx < query_contexts.size () && chain_idx < parent_chain.size ()) {
444
+ if (query_contexts.size () - query_idx > parent_chain.size () - chain_idx) {
445
+ // Parent chain has not enough entries, we can't possibly have a match.
446
+ return false ;
447
+ }
448
+
449
+ if (SameAsEntryContext (query_contexts[query_idx],
450
+ parent_chain[chain_idx])) {
451
+ ++query_idx;
452
+ ++chain_idx;
453
+ } else {
454
+ // Name does not match, try next parent_chain entry if the current entry
455
+ // is namespace because the current one can be an inline namespace.
456
+ if (parent_chain[chain_idx].tag () != DW_TAG_namespace)
457
+ return false ;
458
+ ++chain_idx;
459
+ }
460
+ }
461
+ return query_idx == query_contexts.size ();
462
+ }
463
+
405
464
void DebugNamesDWARFIndex::GetTypes (
406
465
ConstString name, llvm::function_ref<bool (DWARFDIE die)> callback) {
407
466
for (const DebugNames::Entry &entry :
@@ -444,6 +503,73 @@ void DebugNamesDWARFIndex::GetNamespaces(
444
503
m_fallback.GetNamespaces (name, callback);
445
504
}
446
505
506
+ llvm::SmallVector<CompilerContext>
507
+ DebugNamesDWARFIndex::GetTypeQueryParentContexts (TypeQuery &query) {
508
+ std::vector<lldb_private::CompilerContext> &query_decl_context =
509
+ query.GetContextRef ();
510
+ llvm::SmallVector<CompilerContext> parent_contexts;
511
+ if (!query_decl_context.empty ()) {
512
+ auto rbegin = query_decl_context.rbegin (), rend = query_decl_context.rend ();
513
+ // Reverse the query decl context to match parent chain.
514
+ // Skip the last entry, it is the type we are looking for.
515
+ for (auto rit = rbegin + 1 ; rit != rend; ++rit)
516
+ // Skip any context without name because .debug_names might not encode
517
+ // them. (e.g. annonymous namespace)
518
+ if ((rit->kind & CompilerContextKind::AnyType) !=
519
+ CompilerContextKind::Invalid &&
520
+ !rit->name .IsEmpty ())
521
+ parent_contexts.push_back (*rit);
522
+ }
523
+ return parent_contexts;
524
+ }
525
+
526
+ void DebugNamesDWARFIndex::GetTypesWithQuery (
527
+ TypeQuery &query, llvm::function_ref<bool (DWARFDIE die)> callback) {
528
+ ConstString name = query.GetTypeBasename ();
529
+ std::vector<lldb_private::CompilerContext> query_context =
530
+ query.GetContextRef ();
531
+ if (query_context.size () <= 1 )
532
+ return GetTypes (name, callback);
533
+
534
+ llvm::SmallVector<CompilerContext> parent_contexts =
535
+ GetTypeQueryParentContexts (query);
536
+ // For each entry, grab its parent chain and check if we have a match.
537
+ for (const DebugNames::Entry &entry : m_debug_names_up->equal_range (name)) {
538
+ if (!isType (entry.tag ()))
539
+ continue ;
540
+
541
+ // If we get a NULL foreign_tu back, the entry doesn't match the type unit
542
+ // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
543
+ // didn't match.
544
+ std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit (entry);
545
+ if (foreign_tu && foreign_tu.value () == nullptr )
546
+ continue ;
547
+
548
+ std::optional<llvm::SmallVector<Entry, 4 >> parent_chain =
549
+ getParentChain (entry);
550
+ if (!parent_chain) {
551
+ // Fallback: use the base class implementation.
552
+ if (!ProcessEntry (entry, [&](DWARFDIE die) {
553
+ return ProcessTypeDieMatchQuery (query, die, callback);
554
+ }))
555
+ return ;
556
+ continue ;
557
+ }
558
+
559
+ // If parent_chain is shorter than parent_contexts, we can't possibly match.
560
+ if (parent_chain->size () < parent_contexts.size ())
561
+ continue ;
562
+ else if (WithinParentChain (parent_contexts, *parent_chain) &&
563
+ !ProcessEntry (entry, [&](DWARFDIE die) {
564
+ // After .debug_names filtering still sending to base class for
565
+ // further filtering before calling the callback.
566
+ return ProcessTypeDieMatchQuery (query, die, callback);
567
+ }))
568
+ return ;
569
+ }
570
+ m_fallback.GetTypesWithQuery (query, callback);
571
+ }
572
+
447
573
void DebugNamesDWARFIndex::GetFunctions (
448
574
const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
449
575
const CompilerDeclContext &parent_decl_ctx,
0 commit comments