24#include "llvm/Support/FormatVariadic.h"
25#include "llvm/Support/ThreadPool.h"
49 std::vector<DWARFUnit *> units_to_index;
56 for (
size_t U = 0; U < main_info.
GetNumUnits(); ++U) {
59 units_to_index.push_back(unit);
62 for (
size_t U = 0; U < dwp_info->
GetNumUnits(); ++U) {
63 if (
auto *tu = llvm::dyn_cast<DWARFTypeUnit>(dwp_info->
GetUnitAtIndex(U)))
64 units_to_index.push_back(tu);
68 if (units_to_index.empty())
77 const uint64_t total_progress = units_to_index.size() * 2 + 8;
79 llvm::formatv(
"Manually indexing DWARF for {0}", module_desc.
GetData()),
82 std::vector<IndexSet> sets(units_to_index.size());
86 std::vector<std::optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
87 units_to_index.size());
88 auto parser_fn = [&](
size_t cu_idx) {
89 IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]);
93 auto extract_fn = [&](
size_t cu_idx) {
94 clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
110 for (
size_t i = 0; i < units_to_index.size(); ++i)
111 task_group.async(extract_fn, i);
116 for (
size_t i = 0; i < units_to_index.size(); ++i)
117 task_group.async(parser_fn, i);
122 for (
auto &set : sets)
123 result.
Append(set.*index);
147 log,
"ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]",
173 if (dwo_symbol_file == dwp) {
177 for (
size_t i = 0; i < dwo_info.
GetNumUnits(); ++i)
191 llvm::dwarf::DW_TAG_module)
205 case DW_TAG_array_type:
206 case DW_TAG_base_type:
207 case DW_TAG_class_type:
208 case DW_TAG_constant:
209 case DW_TAG_enumeration_type:
210 case DW_TAG_inlined_subroutine:
211 case DW_TAG_namespace:
212 case DW_TAG_imported_declaration:
213 case DW_TAG_string_type:
214 case DW_TAG_structure_type:
215 case DW_TAG_subprogram:
216 case DW_TAG_subroutine_type:
218 case DW_TAG_union_type:
219 case DW_TAG_unspecified_type:
220 case DW_TAG_variable:
227 const char *name =
nullptr;
228 const char *mangled_cstr =
nullptr;
229 bool is_declaration =
false;
230 bool has_address =
false;
231 bool has_location_or_const_value =
false;
232 bool is_global_or_static_variable =
false;
236 for (
size_t i = 0; i < attributes.
Size(); ++i) {
247 case DW_AT_declaration:
249 is_declaration = form_value.
Unsigned() != 0;
252 case DW_AT_MIPS_linkage_name:
253 case DW_AT_linkage_name:
269 case DW_AT_const_value:
270 has_location_or_const_value =
true;
271 is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable();
275 case DW_AT_specification:
277 specification_die_form = form_value;
284 case DW_TAG_inlined_subroutine:
285 case DW_TAG_subprogram:
288 bool is_objc_method =
false;
291 std::optional<const ObjCLanguage::MethodName> objc_method =
294 is_objc_method =
true;
296 objc_method->GetClassNameWithCategory());
297 ConstString objc_selector_name(objc_method->GetSelector());
299 objc_method->GetFullNameWithoutCategory().c_str());
300 ConstString class_name_no_category(objc_method->GetClassName());
302 if (class_name_with_category)
304 if (class_name_no_category &&
305 class_name_no_category != class_name_with_category)
307 if (objc_selector_name)
309 if (objc_fullname_no_category_name)
323 if (!is_method && !mangled_cstr && !is_objc_method)
331 if (name && name != mangled_cstr &&
332 ((mangled_cstr[0] ==
'_') ||
333 (::strcmp(name, mangled_cstr) != 0))) {
340 case DW_TAG_array_type:
341 case DW_TAG_base_type:
342 case DW_TAG_class_type:
343 case DW_TAG_constant:
344 case DW_TAG_enumeration_type:
345 case DW_TAG_string_type:
346 case DW_TAG_structure_type:
347 case DW_TAG_subroutine_type:
349 case DW_TAG_union_type:
350 case DW_TAG_unspecified_type:
351 if (name && !is_declaration)
353 if (mangled_cstr && !is_declaration)
357 case DW_TAG_namespace:
358 case DW_TAG_imported_declaration:
363 case DW_TAG_variable:
364 if (name && has_location_or_const_value && is_global_or_static_variable) {
375 if (mangled_cstr && name != mangled_cstr &&
376 ((mangled_cstr[0] ==
'_') || (::strcmp(name, mangled_cstr) != 0))) {
397 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
416 ConstString class_name,
bool must_be_implementation,
417 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
431 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
433 auto name = context[0].name;
447 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
452 if (name_type_mask & eFunctionNameTypeFull) {
459 return callback(die);
464 if (name_type_mask & eFunctionNameTypeBase) {
471 return callback(die);
477 if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.
IsValid()) {
483 if (name_type_mask & eFunctionNameTypeSelector &&
493 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
505 s.
Format(
"Manual DWARF index for ({0}) '{1:F}':",
508 s.
Printf(
"\nFunction basenames:\n");
510 s.
Printf(
"\nFunction fullnames:\n");
512 s.
Printf(
"\nFunction methods:\n");
514 s.
Printf(
"\nFunction selectors:\n");
516 s.
Printf(
"\nObjective-C class selectors:\n");
518 s.
Printf(
"\nGlobals and statics:\n");
522 s.
Printf(
"\nNamespaces:\n");
550 if (!strtab.
Decode(data, offset_ptr))
553 llvm::StringRef identifier((
const char *)data.
GetData(offset_ptr, 4), 4);
556 const uint32_t version = data.
GetU32(offset_ptr);
562 switch (data.
GetU8(offset_ptr)) {
622 if (!function_basenames.IsEmpty()) {
624 function_basenames.Encode(index_encoder, strtab);
626 if (!function_fullnames.IsEmpty()) {
628 function_fullnames.Encode(index_encoder, strtab);
630 if (!function_methods.IsEmpty()) {
632 function_methods.Encode(index_encoder, strtab);
634 if (!function_selectors.IsEmpty()) {
636 function_selectors.Encode(index_encoder, strtab);
638 if (!objc_class_selectors.IsEmpty()) {
640 objc_class_selectors.Encode(index_encoder, strtab);
642 if (!globals.IsEmpty()) {
644 globals.Encode(index_encoder, strtab);
646 if (!types.IsEmpty()) {
648 types.Encode(index_encoder, strtab);
650 if (!namespaces.IsEmpty()) {
652 namespaces.Encode(index_encoder, strtab);
664 bool &signature_mismatch) {
665 signature_mismatch =
false;
667 if (!signature.
Decode(data, offset_ptr))
670 signature_mismatch =
true;
674 if (!set.
Decode(data, offset_ptr))
676 m_set = std::move(set);
682 if (!signature.
Encode(encoder))
690 llvm::raw_string_ostream strm(key);
696 strm << objfile->
GetModule()->GetCacheKey() <<
"-dwarf-index-"
708 std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up =
713 mem_buffer_up->getBufferSize(),
716 bool signature_mismatch =
false;
718 const bool result =
Decode(data, &offset, signature_mismatch);
719 if (signature_mismatch)
constexpr uint32_t CURRENT_CACHE_VERSION
constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX")
@ kDataIDFunctionObjcClassSelectors
@ kDataIDFunctionFullnames
@ kDataIDFunctionSelectors
@ kDataIDFunctionBasenames
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
#define LLDB_SCOPED_TIMERF(...)
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Represents a generic declaration context in a program.
Many cache files require string tables to store data efficiently.
bool Encode(DataEncoder &encoder)
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
An binary data encoding class.
lldb::ByteOrder GetByteOrder() const
llvm::ArrayRef< uint8_t > GetData() const
Get a access to the bytes that this references.
void AppendU32(uint32_t value)
void AppendU8(uint8_t value)
Append a unsigned integer to the end of the owned data.
void AppendData(llvm::StringRef data)
Append a bytes to the end of the owned data.
uint8_t GetAddressByteSize() const
The address size to use when encoding pointers or addresses.
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::ThreadPool & GetThreadPool()
Shared thread poll. 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
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
static DataFileCache * GetIndexCache()
Get the global index file cache.
void LogMessage(Log *log, const char *format, Args &&...args)
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level=lldb::eDescriptionLevelFull)
static std::optional< const MethodName > Create(llvm::StringRef name, bool strict)
The static factory method for creating a MethodName.
A plug-in interface definition class for object file parsers.
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
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::string update={})
Increment the progress and send a notification to the intalled callback.
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.
Many cache files require string tables to store data efficiently.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)
void SetDebugInfoIndexWasLoadedFromCache() override
ObjectFile * GetObjectFile() override
void SetDebugInfoIndexWasSavedToCache() override
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
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< bool(DWARFDIE die)> callback, llvm::StringRef name={}) const
SymbolFileDWARFDwo * GetDwoSymbolFile()
bool IsSkeletonUnit() const
Note that this check only works for DWARF5+.
dw_offset_t GetFirstDIEOffset() const
dw_offset_t GetOffset() const
uint16_t GetVersion() const
die_iterator_range dies()
DWARFUnit & GetNonSkeletonUnit()
DWARFDIE GetDIE(dw_offset_t die_offset)
std::optional< uint64_t > GetDWOId()
void Dump(Stream &s) override
SymbolFileDWARF * m_dwarf
The DWARF file which we are indexing.
void IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, IndexSet &set)
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
static void IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language, IndexSet &set)
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
bool Encode(DataEncoder &encoder) const
Encode this object into a data encoder object.
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.
void GetObjCMethods(ConstString class_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 SaveToCache()
Save the symbol table data out into a cache.
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void Append(const NameToDIE &other)
void FindAllEntriesForUnit(DWARFUnit &unit, llvm::function_ref< bool(DIERef ref)> callback) const
unit must be the skeleton unit if possible, not GetNonSkeletonUnit().
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, const StringTableReader &strtab)
Decode a serialized version of this object from data.
bool Find(ConstString name, llvm::function_ref< bool(DIERef ref)> callback) const
void Insert(ConstString name, const DIERef &die_ref)
const std::shared_ptr< SymbolFileDWARFDwo > & GetDwpSymbolFile()
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()
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.
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.
NameToDIE function_basenames
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)
NameToDIE function_selectors
void Encode(DataEncoder &encoder) const
NameToDIE function_fullnames
NameToDIE function_methods
NameToDIE objc_class_selectors