17#include "llvm/ADT/Sequence.h"
25llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
29 auto index_up = std::make_unique<DebugNames>(debug_names.
GetAsLLVMDWARF(),
31 if (llvm::Error E = index_up->extract())
35 module, std::move(index_up), debug_names, debug_str,
dwarf));
38llvm::DenseSet<uint64_t>
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));
49llvm::DenseSet<dw_offset_t>
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));
63std::optional<DWARFTypeUnit *>
65 std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature();
66 if (!type_sig.has_value())
73 std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset();
105 DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
111 llvm::StringRef cu_dwo_name =
113 llvm::StringRef tu_dwo_name =
115 if (cu_dwo_name == tu_dwo_name)
124 return foreign_tu.value();
128 std::optional<uint64_t> unit_offset = entry.getCUOffset();
130 unit_offset = entry.getLocalTUOffset();
141 std::optional<uint64_t> die_offset = entry.getDIEUnitOffset();
142 if (!unit || !die_offset)
148 "the DWARF debug information has been modified (bad offset {0:x} in "
149 "debug_names section)\n",
155 const DebugNames::Entry &entry,
156 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
165 return callback(die);
169 const DebugNames::NameIndex &ni,
170 llvm::StringRef name) {
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);
181 for (
const DebugNames::Entry &entry :
183 if (entry.tag() != DW_TAG_variable)
195 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
197 for (DebugNames::NameTableEntry nte: ni) {
198 Mangled mangled_name(nte.getString());
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)
221 bool found_entry_for_cu =
false;
224 bool cu_matches =
false;
225 for (uint32_t i = 0; i < ni.getCUCount(); ++i) {
226 if (ni.getCUOffset(i) == cu_offset) {
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)
240 if (entry_or->getCUOffset() != cu_offset)
243 found_entry_for_cu =
true;
252 if (!found_entry_for_cu)
257 ConstString class_name,
bool must_be_implementation,
258 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
261 std::vector<DWARFDIE> incomplete_types;
263 for (
const DebugNames::Entry &entry :
265 if (entry.tag() != DW_TAG_structure_type &&
266 entry.tag() != DW_TAG_class_type)
280 incomplete_types.push_back(die);
283 for (
DWARFDIE die : incomplete_types)
291using Entry = llvm::DWARFDebugNames::Entry;
298std::optional<llvm::SmallVector<Entry, 4>>
299getParentChain(
Entry entry,
300 uint32_t max_parents = std::numeric_limits<uint32_t>::max()) {
301 llvm::SmallVector<Entry, 4> parent_entries;
304 if (!entry.hasParentInformation())
307 llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
312 "Failed to extract parent entry from a non-empty IDX_parent");
317 if (!parent->has_value())
320 parent_entries.push_back(**parent);
322 }
while (parent_entries.size() < max_parents);
324 return parent_entries;
330 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
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);
340 for (
const DebugNames::Entry &entry :
342 if (!isType(entry.tag()))
349 if (foreign_tu && foreign_tu.value() ==
nullptr)
354 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
355 getParentChain(entry, parent_names.size() + 1);
376 const DebugNames::Entry &entry)
const {
379 auto maybe_dieoffset = entry.getDIEUnitOffset();
380 if (!maybe_dieoffset)
385 return query_context.
name ==
390 llvm::ArrayRef<llvm::StringRef> parent_names,
391 llvm::ArrayRef<DebugNames::Entry> parent_entries)
const {
393 if (parent_entries.size() != parent_names.size())
396 auto SameAsEntryATName = [
this](llvm::StringRef name,
397 const DebugNames::Entry &entry) {
399 auto maybe_dieoffset = entry.getDIEUnitOffset();
400 if (!maybe_dieoffset)
410 for (
auto [parent_name, parent_entry] :
411 llvm::zip_equal(parent_names, parent_entries))
412 if (!SameAsEntryATName(parent_name, parent_entry))
418 llvm::ArrayRef<CompilerContext> parent_contexts,
419 llvm::ArrayRef<DebugNames::Entry> parent_entries)
const {
420 if (parent_entries.size() != parent_contexts.size())
425 for (
auto [parent_context, parent_entry] :
426 llvm::zip_equal(parent_contexts, parent_entries))
433 llvm::ArrayRef<CompilerContext> query_contexts,
434 llvm::ArrayRef<DebugNames::Entry> parent_chain)
const {
435 if (query_contexts.size() == parent_chain.size())
440 while (!query_contexts.empty() &&
441 query_contexts.size() <= parent_chain.size()) {
443 query_contexts = query_contexts.drop_front();
444 parent_chain = parent_chain.drop_front();
448 if (parent_chain.front().tag() != DW_TAG_namespace)
450 parent_chain = parent_chain.drop_front();
453 return query_contexts.empty();
458 for (
const DebugNames::Entry &entry :
460 if (isType(entry.tag())) {
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) {
485 for (
const DebugNames::Entry &entry :
487 lldb_private::dwarf::Tag entry_tag = entry.tag();
488 if (entry_tag == DW_TAG_namespace ||
489 entry_tag == DW_TAG_imported_declaration) {
498llvm::SmallVector<CompilerContext>
500 std::vector<lldb_private::CompilerContext> &query_decl_context =
502 llvm::SmallVector<CompilerContext> parent_contexts;
503 if (!query_decl_context.empty()) {
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)) {
514 parent_contexts.push_back(ctx);
517 return parent_contexts;
523 std::vector<lldb_private::CompilerContext> query_context =
528 llvm::SmallVector<CompilerContext> parent_contexts =
531 for (
const DebugNames::Entry &entry :
m_debug_names_up->equal_range(name)) {
532 if (!isType(entry.tag()))
539 if (foreign_tu && foreign_tu.value() ==
nullptr)
542 std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
543 getParentChain(entry);
568 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
569 std::vector<lldb_private::CompilerContext> parent_contexts =
571 llvm::SmallVector<CompilerContext> parent_named_contexts;
572 std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
573 std::back_inserter(parent_named_contexts),
575 for (
const DebugNames::Entry &entry :
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);
610 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
612 std::set<DWARFDebugInfoEntry *> seen;
613 for (
const DebugNames::Entry &entry :
615 Tag tag = entry.tag();
616 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
622 if (!seen.insert(die.
GetDIE()).second)
624 return callback(die);
635 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
637 for (DebugNames::NameTableEntry nte: ni) {
638 if (!regex.
Execute(nte.getString()))
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)
662 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.
void ReportErrorIfModifyDetected(const char *format, Args &&...args)
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
const std::shared_ptr< SymbolFileDWARFDwo > & GetDwpSymbolFile()
DWARFTypeUnit * GetTypeUnitForHash(uint64_t hash)
DWARFUnit * GetUnitAtOffset(DIERef::Section section, dw_offset_t cu_offset, uint32_t *idx_ptr=nullptr)
bool ProcessTypeDIEMatchQuery(TypeQuery &query, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
Check if the type die can meet the requirements of query.
bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback)
Helper function implementing common logic for processing function dies.
virtual void GetNamespacesWithParents(ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback)
Get namespace DIEs whose base name match.
virtual void GetFullyQualifiedType(const DWARFDeclContext &context, llvm::function_ref< bool(DWARFDIE die)> callback)
Finds all DIEs whose fully qualified name matches context.
bool ProcessNamespaceDieMatchParents(const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
virtual void GetTypesWithQuery(TypeQuery &query, llvm::function_ref< bool(DWARFDIE die)> callback)
Get type DIEs meeting requires of query.
bool GetFullyQualifiedTypeImpl(const DWARFDeclContext &context, DWARFDIE die, llvm::function_ref< bool(DWARFDIE die)> callback)
Implementation of GetFullyQualifiedType to check a single entry, shareable with derived classes.
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)
static llvm::Expected< std::unique_ptr< DebugNamesDWARFIndex > > Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, SymbolFileDWARF &dwarf)
void GetTypesWithQuery(TypeQuery &query, llvm::function_ref< bool(DWARFDIE die)> callback) override
Get type DIEs meeting requires of query.
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 GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetNamespacesWithParents(ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback) override
Get namespace DIEs whose base name match.
void GetFullyQualifiedType(const DWARFDeclContext &context, llvm::function_ref< bool(DWARFDIE die)> callback) override
Uses DWARF5's IDX_parent fields, when available, to speed up this query.
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
llvm::DWARFDebugNames DebugNames
void Dump(Stream &s) override
bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< bool(DWARFDIE die)> callback)
bool SameAsEntryContext(const CompilerContext &query_context, const DebugNames::Entry &entry) const
Returns true if .debug_names pool entry entry matches query_context.
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
DWARFDebugInfo & m_debug_info
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(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
void Dump(Stream &s) override
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
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.
CompilerContext allows an array of these items to be passed to perform detailed lookups in SymbolVend...