25#include "llvm/Support/ThreadPool.h"
32using namespace llvm::dwarf;
42 m_dwarf->SetDebugInfoIndexWasLoadedFromCache();
50 std::vector<DWARFUnit *> units_to_index;
57 for (
size_t U = 0; U < main_info.
GetNumUnits(); ++U) {
60 units_to_index.push_back(unit);
63 for (
size_t U = 0; U < dwp_info->
GetNumUnits(); ++U) {
67 units_to_index.push_back(tu);
72 if (units_to_index.empty())
83 const uint64_t total_progress = units_to_index.size() * 2 + indices.size();
85 total_progress,
nullptr,
96 auto for_each_unit = [&](
auto &&fn) {
97 std::atomic<size_t> next_cu_idx = 0;
98 auto wrapper = [&fn, &next_cu_idx, &units_to_index,
99 &progress](
size_t worker_id) {
101 while ((cu_idx = next_cu_idx.fetch_add(1, std::memory_order_relaxed)) <
102 units_to_index.size()) {
103 fn(worker_id, cu_idx, units_to_index[cu_idx]);
108 for (
size_t i = 0; i < num_threads; ++i)
109 task_group.async(wrapper, i);
120 std::vector<std::optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
121 units_to_index.size());
122 for_each_unit([&clear_cu_dies](
size_t,
size_t idx,
DWARFUnit *unit) {
127 std::vector<IndexSet<NameToDIE>> sets(num_threads);
129 [
this, dwp_dwarf, &sets](
size_t worker_id,
size_t,
DWARFUnit *unit) {
130 IndexUnit(*unit, dwp_dwarf, sets[worker_id]);
136 task_group.async([
this, &sets, index, &progress]() {
138 for (
auto &set : sets)
139 result.
Append(set.*index);
155 log,
"ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]",
181 if (dwo_symbol_file == dwp) {
185 for (
size_t i = 0; i < dwo_info.
GetNumUnits(); ++i)
199 llvm::dwarf::DW_TAG_module)
213 case DW_TAG_array_type:
214 case DW_TAG_base_type:
215 case DW_TAG_class_type:
216 case DW_TAG_constant:
217 case DW_TAG_enumeration_type:
218 case DW_TAG_inlined_subroutine:
219 case DW_TAG_namespace:
220 case DW_TAG_imported_declaration:
221 case DW_TAG_string_type:
222 case DW_TAG_structure_type:
223 case DW_TAG_subprogram:
224 case DW_TAG_subroutine_type:
226 case DW_TAG_union_type:
227 case DW_TAG_unspecified_type:
228 case DW_TAG_variable:
242 const char *name =
nullptr;
243 const char *mangled_cstr =
nullptr;
244 bool is_declaration =
false;
245 bool has_address =
false;
246 bool has_location_or_const_value =
false;
247 bool is_global_or_static_variable =
false;
251 for (
size_t i = 0; i < attributes.
Size(); ++i) {
262 case DW_AT_declaration:
264 is_declaration = form_value.
Unsigned() != 0;
267 case DW_AT_MIPS_linkage_name:
268 case DW_AT_linkage_name:
284 case DW_AT_const_value:
285 has_location_or_const_value =
true;
286 is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable();
290 case DW_AT_specification:
292 specification_die_form = form_value;
299 case DW_TAG_inlined_subroutine:
300 case DW_TAG_subprogram:
303 bool is_objc_method =
false;
306 std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
309 is_objc_method =
true;
311 objc_method->GetClassNameWithCategory());
312 ConstString objc_selector_name(objc_method->GetSelector());
314 objc_method->GetFullNameWithoutCategory().c_str());
315 ConstString class_name_no_category(objc_method->GetClassName());
317 if (class_name_with_category)
319 if (class_name_no_category &&
320 class_name_no_category != class_name_with_category)
322 if (objc_selector_name)
324 if (objc_fullname_no_category_name)
338 if (!is_method && !mangled_cstr && !is_objc_method)
346 if (name && name != mangled_cstr &&
347 ((mangled_cstr[0] ==
'_') ||
348 (::strcmp(name, mangled_cstr) != 0))) {
355 case DW_TAG_array_type:
356 case DW_TAG_base_type:
357 case DW_TAG_class_type:
358 case DW_TAG_constant:
359 case DW_TAG_enumeration_type:
360 case DW_TAG_string_type:
361 case DW_TAG_structure_type:
362 case DW_TAG_subroutine_type:
364 case DW_TAG_union_type:
365 case DW_TAG_unspecified_type:
366 if (name && !is_declaration)
368 if (mangled_cstr && !is_declaration)
372 case DW_TAG_namespace:
373 case DW_TAG_imported_declaration:
378 case DW_TAG_member: {
383 bool parent_is_class_type =
false;
384 if (
auto parent = die.GetParent())
386 if (!parent_is_class_type || !is_declaration)
390 case DW_TAG_variable:
391 if (name && has_location_or_const_value && is_global_or_static_variable) {
402 if (mangled_cstr && name != mangled_cstr &&
403 ((mangled_cstr[0] ==
'_') || (::strcmp(name, mangled_cstr) != 0))) {
419 m_set.globals.Find(basename,
441 m_set.objc_class_selectors.Find(
446 ConstString class_name,
bool must_be_implementation,
449 m_set.types.Find(class_name,
464 auto name = context[0].name;
484 if (name_type_mask & eFunctionNameTypeFull) {
485 if (!
m_set.function_fullnames.Find(
491 return callback(die);
496 if (name_type_mask & eFunctionNameTypeBase) {
497 if (!
m_set.function_basenames.Find(
503 return callback(die);
509 if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.
IsValid()) {
510 if (!
m_set.function_methods.Find(
515 if (name_type_mask & eFunctionNameTypeSelector &&
517 if (!
m_set.function_selectors.Find(
528 if (!
m_set.function_basenames.Find(regex,
531 if (!
m_set.function_fullnames.Find(regex,
537 s.
Format(
"Manual DWARF index for ({0}) '{1:F}':",
538 m_module.GetArchitecture().GetArchitectureName(),
539 m_module.GetObjectFile()->GetFileSpec());
540 s.
Printf(
"\nFunction basenames:\n");
541 m_set.function_basenames.Dump(&s);
542 s.
Printf(
"\nFunction fullnames:\n");
543 m_set.function_fullnames.Dump(&s);
544 s.
Printf(
"\nFunction methods:\n");
545 m_set.function_methods.Dump(&s);
546 s.
Printf(
"\nFunction selectors:\n");
547 m_set.function_selectors.Dump(&s);
548 s.
Printf(
"\nObjective-C class selectors:\n");
549 m_set.objc_class_selectors.Dump(&s);
550 s.
Printf(
"\nGlobals and statics:\n");
551 m_set.globals.Dump(&s);
553 m_set.types.Dump(&s);
554 s.
Printf(
"\nNamespaces:\n");
555 m_set.namespaces.Dump(&s);
560 bool &signature_mismatch) {
561 signature_mismatch =
false;
563 if (!signature.
Decode(data, offset_ptr))
566 signature_mismatch =
true;
569 std::optional<IndexSet<NameToDIE>> set =
DecodeIndexSet(data, offset_ptr);
572 m_set = std::move(*set);
578 if (!signature.
Encode(encoder))
591 llvm::raw_string_ostream strm(key);
612 llvm::StringRef dwarf_index_suffix(
IsPartial() ?
"partial-" :
"full-");
614 strm << objfile->
GetModule()->GetCacheKey() <<
"-dwarf-index-"
615 << dwarf_index_suffix << llvm::format_hex(objfile->
GetCacheHash(), 10);
626 std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up =
631 mem_buffer_up->getBufferSize(),
634 bool signature_mismatch =
false;
636 const bool result =
Decode(data, &offset, signature_mismatch);
637 if (signature_mismatch)
654 m_dwarf->SetDebugInfoIndexWasSavedToCache();
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
#define LLDB_SCOPED_TIMERF(...)
Represents a generic declaration context in a program.
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
An binary data encoding class.
llvm::ArrayRef< uint8_t > GetData() const
Get a access to the bytes that this references.
This class enables data to be cached into a directory using the llvm caching code.
std::unique_ptr< llvm::MemoryBuffer > GetCachedData(llvm::StringRef key)
Get cached data from the cache directory for the specified key.
bool SetCachedData(llvm::StringRef key, llvm::ArrayRef< uint8_t > data)
Set cached data for the specified key.
Status RemoveCacheFile(llvm::StringRef key)
Remove the cache file associated with the key.
static llvm::ThreadPoolInterface & GetThreadPool()
Shared thread pool. Use only with ThreadPoolTaskGroup.
A class that measures elapsed time in an exception safe way.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
A class that encapsulates name lookup information.
lldb::FunctionNameType GetNameTypeMask() const
ConstString GetLookupName() const
static DataFileCache * GetIndexCache()
Get the global index file cache.
static std::optional< const ObjCMethodName > Create(llvm::StringRef name, bool strict)
The static factory method for creating a ObjCMethodName.
A plug-in interface definition class for object file parsers.
virtual uint32_t GetAddressByteSize() const =0
Gets the address size in bytes for the current object file.
uint32_t GetCacheHash()
Get a hash that can be used for caching object file releated information.
A Progress indicator helper class.
void Increment(uint64_t amount=1, std::optional< std::string > updated_detail={})
Increment the progress and send a notification to the installed callback.
static constexpr std::chrono::milliseconds kDefaultHighFrequencyReportTime
The default report time for high frequency progress reports.
llvm::StringRef GetText() const
Access the regular expression text.
const char * GetData() const
A stream class that can stream formatted output to a file.
void Format(const char *format, Args &&... args)
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Identifies a DWARF debug info entry within a given Module.
dw_attr_t AttributeAtIndex(uint32_t i) const
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const
std::optional< DIERef > GetDIERef() const
DWARFDIE GetFirstChild() const
bool IsStructUnionOrClass() const
DWARFDebugInfoEntry objects assume that they are living in one big vector and do pointer arithmetic o...
DWARFUnit * GetUnitAtIndex(size_t idx)
StatsDuration m_index_time
DIERefCallbackImpl DIERefCallback(llvm::function_ref< IterationAction(DWARFDIE die)> callback, llvm::StringRef name={}) const
bool IsSkeletonUnit() const
Note that this check only works for DWARF5+.
dw_offset_t GetFirstDIEOffset() const
dw_offset_t GetOffset() const
die_iterator_range dies()
ScopedExtractDIEs ExtractDIEsScoped()
DWARFUnit & GetNonSkeletonUnit()
DWARFDIE GetDIE(dw_offset_t die_offset)
SymbolFileDWARFDwo * GetDwoSymbolFile(bool load_all_debug_info=true)
uint16_t GetVersion() const override
std::optional< uint64_t > GetDWOId()
Get the DWO ID from the DWARFUnitHeader for DWARF5, or from the unit DIE's DW_AT_dwo_id or DW_AT_GNU_...
void IndexImpl()
Call ManualDWARFIndex::Index() instead.
void Dump(Stream &s) override
SymbolFileDWARF * m_dwarf
The DWARF file which we are indexing.
void IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, IndexSet< NameToDIE > &set)
bool IsPartial() const
Return true if this manual DWARF index is covering only part of the DWARF.
IndexSet< NameToDIE > m_set
bool Encode(DataEncoder &encoder) const
Encode this object into a data encoder object.
void GetGlobalVariables(ConstString basename, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void Index()
Reads the DWARF debug info to build the index once.
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
llvm::DenseSet< dw_offset_t > m_units_to_avoid
Which dwarf units should we skip while building the index.
std::string GetCacheKey()
Get the cache key string for this symbol table.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, bool &signature_mismatch)
Decode a serialized version of this object from data.
bool LoadFromCache()
Load the symbol table from the index cache.
std::once_flag m_indexed_flag
void GetObjCMethods(ConstString class_name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
static void IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language, IndexSet< NameToDIE > &set)
llvm::DenseSet< uint64_t > m_type_sigs_to_avoid
void SaveToCache()
Save the symbol table data out into a cache.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void GetTypes(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void GetNamespaces(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void Append(const NameToDIE &other)
static lldb::LanguageType GetLanguage(DWARFUnit &unit)
DWARFDebugInfo & DebugInfo()
static bool DIEInDeclContext(const CompilerDeclContext &parent_decl_ctx, const DWARFDIE &die, bool only_root_namespaces=false)
llvm::dwarf::Tag dw_tag_t
llvm::dwarf::Attribute dw_attr_t
lldb::ByteOrder InlHostByteOrder()
std::optional< IndexSet< NameToDIE > > DecodeIndexSet(const DataExtractor &data, lldb::offset_t *offset_ptr)
void EncodeIndexSet(const IndexSet< NameToDIE > &set, DataEncoder &encoder)
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.
LanguageType
Programming language type.
@ eLanguageTypeObjC_plus_plus
Objective-C++.
@ eLanguageTypeObjC
Objective-C.
A signature for a given file on disk.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)
Decode a serialized version of this object from data.
bool Encode(DataEncoder &encoder) const
Encode this object into a data encoder object.
static std::array< T(IndexSet::*), 8 > Indices()