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 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> 19 20 using namespace lldb_private; 21 using namespace lldb; 22 using namespace lldb_private::dwarf; 23 using namespace lldb_private::plugin::dwarf; 24 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); 33 34 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex( 35 module, std::move(index_up), debug_names, debug_str, dwarf)); 36 } 37 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)); 45 } 46 return result; 47 } 48 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)); 59 } 60 return result; 61 } 62 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; 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 = 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. 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. 90 return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash( 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 120 DWARFUnit * 121 DebugNamesDWARFIndex::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) { 132 if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, 133 *unit_offset)) 134 return &cu->GetNonSkeletonUnit(); 135 } 136 return nullptr; 137 } 138 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; 146 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(); 152 } 153 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); 166 } 167 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); 177 } 178 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; 185 186 if (!ProcessEntry(entry, callback)) 187 return; 188 } 189 190 m_fallback.GetGlobalVariables(basename, callback); 191 } 192 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)) 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 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; 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 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; 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 290 namespace { 291 using 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. 298 std::optional<llvm::SmallVector<Entry, 4>> 299 getParentChain(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. 310 LLDB_LOG_ERROR( 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 328 void DebugNamesDWARFIndex::GetFullyQualifiedType( 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 374 bool DebugNamesDWARFIndex::SameAsEntryContext( 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 389 bool DebugNamesDWARFIndex::SameParentChain( 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 417 bool DebugNamesDWARFIndex::SameParentChain( 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 432 bool DebugNamesDWARFIndex::WithinParentChain( 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 456 void DebugNamesDWARFIndex::GetTypes( 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 469 void DebugNamesDWARFIndex::GetTypes( 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 483 void DebugNamesDWARFIndex::GetNamespaces( 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 498 llvm::SmallVector<CompilerContext> 499 DebugNamesDWARFIndex::GetTypeQueryParentContexts(TypeQuery &query) { 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) != 512 CompilerContextKind::Invalid && 513 !ctx.name.IsEmpty()) 514 parent_contexts.push_back(ctx); 515 } 516 } 517 return parent_contexts; 518 } 519 520 void DebugNamesDWARFIndex::GetTypesWithQuery( 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 = 529 GetTypeQueryParentContexts(query); 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 566 void DebugNamesDWARFIndex::GetNamespacesWithParents( 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 607 void DebugNamesDWARFIndex::GetFunctions( 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 633 void DebugNamesDWARFIndex::GetFunctions( 634 const RegularExpression ®ex, 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 658 void DebugNamesDWARFIndex::Dump(Stream &s) { 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 } 666