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...