brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.5 KiB · fa5baf1 Raw
671 lines · cpp
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-exception6//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 "lldb/lldb-private-enumerations.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>>27DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,28                             DWARFDataExtractor debug_str,29                             SymbolFileDWARF &dwarf) {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>40DebugNamesDWARFIndex::GetTypeUnitSignatures(const DebugNames &debug_names) {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>51DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {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 .dwo71  // file from it and get the type unit by signature from there. If we find72  // the type unit in the .dwo file, we don't need to check that the73  // 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 have88    // 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.91    return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(92        *type_sig);93  }94  // We have a .dwp file, just get the type unit from there. We need to verify95  // that the type unit that ended up in the final .dwp file is the right type96  // unit. Type units have signatures which are the same across multiple .dwo97  // files, but only one of those type units will end up in the .dwp file. The98  // contents of type units for the same type can be different in different .dwo99  // files, which means the DIE offsets might not be the same between two100  // different type units. So we need to determine if this accelerator table101  // 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 that103  // is in the .dwp file will have its own index. In order to determine if the104  // type unit that ended up in a .dwp file matches this DebugNames::Entry, we105  // 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 are128  // 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 155IterationAction DebugNamesDWARFIndex::ProcessEntry(156    const DebugNames::Entry &entry,157    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {158  DWARFDIE die = GetDIE(entry);159  if (!die)160    return IterationAction::Continue;161  // Clang used to erroneously emit index entries for declaration DIEs in case162  // when the definition is in a type unit (llvm.org/pr77696).163  if (die.IsStructUnionOrClass() &&164      die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))165    return IterationAction::Continue;166  return callback(die);167}168 169void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,170                                               const DebugNames::NameIndex &ni,171                                               llvm::StringRef name) {172  // Ignore SentinelErrors, log everything else.173  LLDB_LOG_ERROR(174      GetLog(DWARFLog::Lookups),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 180void DebugNamesDWARFIndex::GetGlobalVariables(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 195void DebugNamesDWARFIndex::GetGlobalVariables(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 220void DebugNamesDWARFIndex::GetGlobalVariables(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 to253  // creating the manual index.254  if (!found_entry_for_cu)255    m_fallback.GetGlobalVariables(cu, callback);256}257 258void DebugNamesDWARFIndex::GetCompleteObjCClass(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 the262  // 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 invalid274      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 information296/// 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.312      LLDB_LOG_ERROR(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} // namespace329 330void DebugNamesDWARFIndex::GetFullyQualifiedType(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 unit348    // in the .dwp file, or we were not able to load the .dwo file or the DWO ID349    // 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 to355    // 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);363          }) == IterationAction::Stop)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 376bool DebugNamesDWARFIndex::SameAsEntryContext(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 391bool DebugNamesDWARFIndex::SameParentChain(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't411  // 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 419bool DebugNamesDWARFIndex::SameParentChain(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't426  // 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 434bool DebugNamesDWARFIndex::WithinParentChain(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 a441  // 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 entry449      // 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 458void DebugNamesDWARFIndex::GetTypes(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 472void DebugNamesDWARFIndex::GetTypes(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 486void DebugNamesDWARFIndex::GetNamespaces(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>503DebugNamesDWARFIndex::GetTypeQueryParentContexts(TypeQuery &query) {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 encode514      // them. (e.g. annonymous namespace)515      if ((ctx.kind & CompilerContextKind::AnyType) !=516              CompilerContextKind::Invalid &&517          !ctx.name.IsEmpty())518        parent_contexts.push_back(ctx);519    }520  }521  return parent_contexts;522}523 524void DebugNamesDWARFIndex::GetTypesWithQuery(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 =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()))538      continue;539 540    // If we get a NULL foreign_tu back, the entry doesn't match the type unit541    // in the .dwp file, or we were not able to load the .dwo file or the DWO ID542    // 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);553          }) == IterationAction::Stop)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 base561            // class for further filtering before calling the562            // callback.563            return ProcessTypeDIEMatchQuery(query, die, callback);564          }) == IterationAction::Stop)565        return;566    }567  }568  m_fallback.GetTypesWithQuery(query, callback);569}570 571void DebugNamesDWARFIndex::GetNamespacesWithParents(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);592            }) == IterationAction::Stop)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 to600              // base class for further filtering before calling601              // the callback.602              return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,603                                                     callback);604            }) == IterationAction::Stop)605          return;606      }607    }608  }609  m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);610}611 612void DebugNamesDWARFIndex::GetFunctions(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)628                                 return IterationAction::Continue;629                               return callback(die);630                             }) == IterationAction::Stop)631        return;632    }633  }634 635  m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);636}637 638void DebugNamesDWARFIndex::GetFunctions(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 663void DebugNamesDWARFIndex::Dump(Stream &s) {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}671