18#include "llvm/ADT/Sequence.h" 
   24using namespace llvm::dwarf;
 
   26llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
 
   30  auto index_up = std::make_unique<DebugNames>(debug_names.
GetAsLLVMDWARF(),
 
   32  if (llvm::Error E = index_up->extract())
 
   36      module, std::move(index_up), debug_names, debug_str, 
dwarf));
 
 
   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));
 
 
   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));
 
 
   64std::optional<DWARFTypeUnit *>
 
   66  std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature();
 
   67  if (!type_sig.has_value())
 
   74  std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset();
 
  106  DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
 
  112  llvm::StringRef cu_dwo_name =
 
  114  llvm::StringRef tu_dwo_name =
 
  116  if (cu_dwo_name == tu_dwo_name)
 
 
  125    return foreign_tu.value();
 
  129  std::optional<uint64_t> unit_offset = entry.getCUOffset();
 
  131    unit_offset = entry.getLocalTUOffset();
 
  135      return &cu->GetNonSkeletonUnit();
 
 
  142  std::optional<uint64_t> die_offset = entry.getDIEUnitOffset();
 
  143  if (!unit || !die_offset)
 
  148  m_module.ReportErrorIfModifyDetected(
 
  149      "the DWARF debug information has been modified (bad offset {0:x} in " 
  150      "debug_names section)\n",
 
 
  156    const DebugNames::Entry &entry,
 
  166  return callback(die);
 
 
  170                                               const DebugNames::NameIndex &ni,
 
  171                                               llvm::StringRef name) {
 
  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);
 
 
  183  for (
const DebugNames::Entry &entry :
 
  185    if (entry.tag() != DW_TAG_variable)
 
  192  m_fallback.GetGlobalVariables(basename, callback);
 
 
  199    for (DebugNames::NameTableEntry nte: ni) {
 
  200      Mangled mangled_name(nte.getString());
 
  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)
 
  217  m_fallback.GetGlobalVariables(regex, callback);
 
 
  223  bool found_entry_for_cu = 
false;
 
  226    bool cu_matches = 
false;
 
  227    for (uint32_t i = 0; i < ni.getCUCount(); ++i) {
 
  228      if (ni.getCUOffset(i) == cu_offset) {
 
  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)
 
  242        if (entry_or->getCUOffset() != cu_offset)
 
  245        found_entry_for_cu = 
true;
 
  254  if (!found_entry_for_cu)
 
 
  259    ConstString class_name, 
bool must_be_implementation,
 
  263  std::vector<DWARFDIE> incomplete_types;
 
  265  for (
const DebugNames::Entry &entry :
 
  267    if (entry.tag() != DW_TAG_structure_type &&
 
  268        entry.tag() != DW_TAG_class_type)
 
  282    incomplete_types.push_back(die);
 
  285  for (
DWARFDIE die : incomplete_types)
 
  289  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
 
 
  293using Entry = llvm::DWARFDebugNames::Entry;
 
  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;
 
  306    if (!entry.hasParentInformation())
 
  309    llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
 
  314          "Failed to extract parent entry from a non-empty IDX_parent");
 
  319    if (!parent->has_value())
 
  322    parent_entries.push_back(**parent);
 
  324  } 
while (parent_entries.size() < max_parents);
 
  326  return parent_entries;
 
  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);
 
  342  for (
const DebugNames::Entry &entry :
 
  344    if (!isType(entry.tag()))
 
  351    if (foreign_tu && foreign_tu.value() == 
nullptr)
 
  356    std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
 
  357        getParentChain(entry, parent_names.size() + 1);
 
  373  m_fallback.GetFullyQualifiedType(context, callback);
 
 
  378    const DebugNames::Entry &entry)
 const {
 
  381  auto maybe_dieoffset = entry.getDIEUnitOffset();
 
  382  if (!maybe_dieoffset)
 
  387  return query_context.
name ==
 
 
  392    llvm::ArrayRef<llvm::StringRef> parent_names,
 
  393    llvm::ArrayRef<DebugNames::Entry> parent_entries)
 const {
 
  395  if (parent_entries.size() != parent_names.size())
 
  398  auto SameAsEntryATName = [
this](llvm::StringRef name,
 
  399                                  const DebugNames::Entry &entry) {
 
  401    auto maybe_dieoffset = entry.getDIEUnitOffset();
 
  402    if (!maybe_dieoffset)
 
  412  for (
auto [parent_name, parent_entry] :
 
  413       llvm::zip_equal(parent_names, parent_entries))
 
  414    if (!SameAsEntryATName(parent_name, parent_entry))
 
 
  420    llvm::ArrayRef<CompilerContext> parent_contexts,
 
  421    llvm::ArrayRef<DebugNames::Entry> parent_entries)
 const {
 
  422  if (parent_entries.size() != parent_contexts.size())
 
  427  for (
auto [parent_context, parent_entry] :
 
  428       llvm::zip_equal(parent_contexts, parent_entries))
 
 
  435    llvm::ArrayRef<CompilerContext> query_contexts,
 
  436    llvm::ArrayRef<DebugNames::Entry> parent_chain)
 const {
 
  437  if (query_contexts.size() == parent_chain.size())
 
  442  while (!query_contexts.empty() &&
 
  443         query_contexts.size() <= parent_chain.size()) {
 
  445      query_contexts = query_contexts.drop_front();
 
  446      parent_chain = parent_chain.drop_front();
 
  450      if (parent_chain.front().tag() != DW_TAG_namespace)
 
  452      parent_chain = parent_chain.drop_front();
 
  455  return query_contexts.empty();
 
 
  461  for (
const DebugNames::Entry &entry :
 
  463    if (isType(entry.tag())) {
 
 
  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) {
 
 
  489  for (
const DebugNames::Entry &entry :
 
  491    llvm::dwarf::Tag entry_tag = entry.tag();
 
  492    if (entry_tag == DW_TAG_namespace ||
 
  493        entry_tag == DW_TAG_imported_declaration) {
 
 
  502llvm::SmallVector<CompilerContext>
 
  504  std::vector<lldb_private::CompilerContext> &query_decl_context =
 
  506  llvm::SmallVector<CompilerContext> parent_contexts;
 
  507  if (!query_decl_context.empty()) {
 
  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)) {
 
  518        parent_contexts.push_back(ctx);
 
  521  return parent_contexts;
 
 
  528  std::vector<lldb_private::CompilerContext> query_context =
 
  533  llvm::SmallVector<CompilerContext> parent_contexts =
 
  536  for (
const DebugNames::Entry &entry : 
m_debug_names_up->equal_range(name)) {
 
  537    if (!isType(entry.tag()))
 
  544    if (foreign_tu && foreign_tu.value() == 
nullptr)
 
  547    std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
 
  548        getParentChain(entry);
 
  568  m_fallback.GetTypesWithQuery(query, callback);
 
 
  574  std::vector<lldb_private::CompilerContext> parent_contexts =
 
  576  llvm::SmallVector<CompilerContext> parent_named_contexts;
 
  577  std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
 
  578               std::back_inserter(parent_named_contexts),
 
  580  for (
const DebugNames::Entry &entry :
 
  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);
 
  609  m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
 
 
  617  std::set<DWARFDebugInfoEntry *> seen;
 
  618  for (
const DebugNames::Entry &entry :
 
  620    Tag tag = entry.tag();
 
  621    if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
 
  627                               if (!seen.insert(die.
GetDIE()).second)
 
  629                               return callback(die);
 
  635  m_fallback.GetFunctions(lookup_info, 
dwarf, parent_decl_ctx, callback);
 
 
  642    for (DebugNames::NameTableEntry nte: ni) {
 
  643      if (!regex.
Execute(nte.getString()))
 
  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)
 
 
  667  llvm::raw_string_ostream os(data);
 
 
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
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.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
A class that handles mangled names.
bool NameMatches(ConstString name) const
Check if "name" matches either the mangled or demangled name.
A class that encapsulates name lookup information.
ConstString GetLookupName() const
A class that describes an executable image and its associated object and symbol files.
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.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
A class that contains all state required for type lookups.
std::vector< lldb_private::CompilerContext > & GetContextRef()
Access the internal compiler context array.
bool GetExactMatch() const
ConstString GetTypeBasename() const
Get the type basename to use when searching the type indexes in each SymbolFile object.
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
bool IsStructUnionOrClass() const
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)
DWARFBaseDIE GetUnitDIEOnly()
SymbolFileDWARF & GetSymbolFileDWARF() const
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.
dw_offset_t GetOffset() const
DWARFUnit & GetNonSkeletonUnit()
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.
ManualDWARFIndex m_fallback
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.
llvm::DWARFDebugNames DebugNames
void Dump(Stream &s) override
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.
DWARFDebugInfo & m_debug_info
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
std::unique_ptr< DebugNames > m_debug_names_up
DWARFDebugInfo & DebugInfo()
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.
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...