24 #include "llvm/Support/FormatVariadic.h"
25 #include "llvm/Support/ThreadPool.h"
38 if (LoadFromCache()) {
39 m_dwarf->SetDebugInfoIndexWasLoadedFromCache();
47 std::vector<DWARFUnit *> units_to_index;
54 for (
size_t U = 0; U < main_info.
GetNumUnits(); ++U) {
56 if (unit && m_units_to_avoid.count(unit->
GetOffset()) == 0)
57 units_to_index.push_back(unit);
60 for (
size_t U = 0; U < dwp_info->
GetNumUnits(); ++U) {
61 if (
auto *tu = llvm::dyn_cast<DWARFTypeUnit>(dwp_info->
GetUnitAtIndex(U)))
62 units_to_index.push_back(tu);
66 if (units_to_index.empty())
75 const uint64_t total_progress = units_to_index.size() * 2 + 8;
77 llvm::formatv(
"Manually indexing DWARF for {0}", module_desc.
GetData()),
80 std::vector<IndexSet> sets(units_to_index.size());
84 std::vector<llvm::Optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
85 units_to_index.size());
86 auto parser_fn = [&](
size_t cu_idx) {
87 IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]);
91 auto extract_fn = [&](
size_t cu_idx) {
92 clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
108 for (
size_t i = 0; i < units_to_index.size(); ++i)
109 task_group.async(extract_fn, i);
114 for (
size_t i = 0; i < units_to_index.size(); ++i)
115 task_group.async(parser_fn, i);
120 for (
auto &
set : sets)
126 task_group.async(finalize_fn, &IndexSet::function_basenames);
127 task_group.async(finalize_fn, &IndexSet::function_fullnames);
128 task_group.async(finalize_fn, &IndexSet::function_methods);
129 task_group.async(finalize_fn, &IndexSet::function_selectors);
130 task_group.async(finalize_fn, &IndexSet::objc_class_selectors);
131 task_group.async(finalize_fn, &IndexSet::globals);
132 task_group.async(finalize_fn, &IndexSet::types);
133 task_group.async(finalize_fn, &IndexSet::namespaces);
145 log,
"ManualDWARFIndex::IndexUnit for unit at .debug_info[0x%8.8x]",
151 IndexUnitImpl(unit, cu_language,
set);
157 if (dwo_symbol_file == dwp) {
161 for (
size_t i = 0; i < dwo_info.
GetNumUnits(); ++i)
174 case DW_TAG_array_type:
175 case DW_TAG_base_type:
176 case DW_TAG_class_type:
177 case DW_TAG_constant:
178 case DW_TAG_enumeration_type:
179 case DW_TAG_inlined_subroutine:
180 case DW_TAG_namespace:
181 case DW_TAG_string_type:
182 case DW_TAG_structure_type:
183 case DW_TAG_subprogram:
184 case DW_TAG_subroutine_type:
186 case DW_TAG_union_type:
187 case DW_TAG_unspecified_type:
188 case DW_TAG_variable:
196 const char *name =
nullptr;
197 const char *mangled_cstr =
nullptr;
198 bool is_declaration =
false;
200 bool has_address =
false;
201 bool has_location_or_const_value =
false;
202 bool is_global_or_static_variable =
false;
205 const size_t num_attributes = die.GetAttributes(&unit, attributes);
206 if (num_attributes > 0) {
207 for (
uint32_t i = 0; i < num_attributes; ++i) {
216 case DW_AT_declaration:
218 is_declaration = form_value.
Unsigned() != 0;
221 case DW_AT_MIPS_linkage_name:
222 case DW_AT_linkage_name:
238 case DW_AT_const_value:
239 has_location_or_const_value =
true;
240 is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable();
244 case DW_AT_specification:
246 specification_die_form = form_value;
254 case DW_TAG_inlined_subroutine:
255 case DW_TAG_subprogram:
258 bool is_objc_method =
false;
262 if (objc_method.
IsValid(
true)) {
263 is_objc_method =
true;
271 if (class_name_with_category)
272 set.objc_class_selectors.Insert(class_name_with_category, ref);
273 if (class_name_no_category &&
274 class_name_no_category != class_name_with_category)
275 set.objc_class_selectors.Insert(class_name_no_category, ref);
276 if (objc_selector_name)
277 set.function_selectors.Insert(objc_selector_name, ref);
278 if (objc_fullname_no_category_name)
279 set.function_fullnames.Insert(objc_fullname_no_category_name,
292 if (!is_method && !mangled_cstr && !is_objc_method)
300 if (name && name != mangled_cstr &&
301 ((mangled_cstr[0] ==
'_') ||
302 (::strcmp(name, mangled_cstr) != 0))) {
309 case DW_TAG_array_type:
310 case DW_TAG_base_type:
311 case DW_TAG_class_type:
312 case DW_TAG_constant:
313 case DW_TAG_enumeration_type:
314 case DW_TAG_string_type:
315 case DW_TAG_structure_type:
316 case DW_TAG_subroutine_type:
318 case DW_TAG_union_type:
319 case DW_TAG_unspecified_type:
320 if (name && !is_declaration)
322 if (mangled_cstr && !is_declaration)
326 case DW_TAG_namespace:
331 case DW_TAG_variable:
332 if (name && has_location_or_const_value && is_global_or_static_variable) {
343 if (mangled_cstr && name != mangled_cstr &&
344 ((mangled_cstr[0] ==
'_') || (::strcmp(name, mangled_cstr) != 0))) {
359 m_set.globals.Find(basename,
365 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
367 m_set.globals.Find(regex, DIERefCallback(callback, regex.
GetText()));
374 m_set.globals.FindAllEntriesForUnit(unit, DIERefCallback(callback));
380 m_set.objc_class_selectors.Find(
381 class_name, DIERefCallback(callback, class_name.
GetStringRef()));
385 ConstString class_name,
bool must_be_implementation,
386 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
388 m_set.types.Find(class_name,
395 m_set.types.Find(name, DIERefCallback(callback, name.
GetStringRef()));
400 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
402 auto name = context[0].name;
404 DIERefCallback(callback, llvm::StringRef(name)));
410 m_set.namespaces.Find(name, DIERefCallback(callback, name.
GetStringRef()));
416 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
419 if (name_type_mask & eFunctionNameTypeFull) {
420 if (!m_set.function_fullnames.Find(
421 name, DIERefCallback(
426 return callback(die);
431 if (name_type_mask & eFunctionNameTypeBase) {
432 if (!m_set.function_basenames.Find(
433 name, DIERefCallback(
438 return callback(die);
444 if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.
IsValid()) {
445 if (!m_set.function_methods.Find(
450 if (name_type_mask & eFunctionNameTypeSelector &&
452 if (!m_set.function_selectors.Find(
460 llvm::function_ref<
bool(
DWARFDIE die)> callback) {
463 if (!m_set.function_basenames.Find(regex,
464 DIERefCallback(callback, regex.
GetText())))
466 if (!m_set.function_fullnames.Find(regex,
467 DIERefCallback(callback, regex.
GetText())))
472 s.
Format(
"Manual DWARF index for ({0}) '{1:F}':",
473 m_module.GetArchitecture().GetArchitectureName(),
474 m_module.GetObjectFile()->GetFileSpec());
475 s.
Printf(
"\nFunction basenames:\n");
476 m_set.function_basenames.Dump(&s);
477 s.
Printf(
"\nFunction fullnames:\n");
478 m_set.function_fullnames.Dump(&s);
479 s.
Printf(
"\nFunction methods:\n");
480 m_set.function_methods.Dump(&s);
481 s.
Printf(
"\nFunction selectors:\n");
482 m_set.function_selectors.Dump(&s);
483 s.
Printf(
"\nObjective-C class selectors:\n");
484 m_set.objc_class_selectors.Dump(&s);
485 s.
Printf(
"\nGlobals and statics:\n");
486 m_set.globals.Dump(&s);
488 m_set.types.Dump(&s);
489 s.
Printf(
"\nNamespaces:\n");
490 m_set.namespaces.Dump(&s);
514 if (!strtab.
Decode(data, offset_ptr))
517 llvm::StringRef identifier((
const char *)data.
GetData(offset_ptr, 4), 4);
526 switch (data.
GetU8(offset_ptr)) {
532 if (!function_basenames.Decode(data, offset_ptr, strtab))
536 if (!function_fullnames.Decode(data, offset_ptr, strtab))
540 if (!function_methods.Decode(data, offset_ptr, strtab))
544 if (!function_selectors.Decode(data, offset_ptr, strtab))
548 if (!objc_class_selectors.Decode(data, offset_ptr, strtab))
552 if (!globals.Decode(data, offset_ptr, strtab))
556 if (!types.Decode(data, offset_ptr, strtab))
560 if (!namespaces.Decode(data, offset_ptr, strtab))
579 DataEncoder index_encoder(encoder.GetByteOrder(),
580 encoder.GetAddressByteSize());
586 if (!function_basenames.IsEmpty()) {
588 function_basenames.Encode(index_encoder, strtab);
590 if (!function_fullnames.IsEmpty()) {
592 function_fullnames.Encode(index_encoder, strtab);
594 if (!function_methods.IsEmpty()) {
596 function_methods.Encode(index_encoder, strtab);
598 if (!function_selectors.IsEmpty()) {
600 function_selectors.Encode(index_encoder, strtab);
602 if (!objc_class_selectors.IsEmpty()) {
604 objc_class_selectors.Encode(index_encoder, strtab);
606 if (!globals.IsEmpty()) {
608 globals.Encode(index_encoder, strtab);
610 if (!types.IsEmpty()) {
612 types.Encode(index_encoder, strtab);
614 if (!namespaces.IsEmpty()) {
616 namespaces.Encode(index_encoder, strtab);
623 encoder.AppendData(index_encoder.GetData());
628 bool &signature_mismatch) {
629 signature_mismatch =
false;
631 if (!signature.
Decode(data, offset_ptr))
634 signature_mismatch =
true;
638 if (!
set.Decode(data, offset_ptr))
640 m_set = std::move(
set);
646 if (!signature.
Encode(encoder))
648 m_set.Encode(encoder);
654 llvm::raw_string_ostream strm(key);
659 ObjectFile *objfile = m_dwarf->GetObjectFile();
660 strm << objfile->
GetModule()->GetCacheKey() <<
"-dwarf-index-"
669 ObjectFile *objfile = m_dwarf->GetObjectFile();
672 std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up =
677 mem_buffer_up->getBufferSize(),
680 bool signature_mismatch =
false;
682 const bool result = Decode(data, &offset, signature_mismatch);
683 if (signature_mismatch)
692 ObjectFile *objfile = m_dwarf->GetObjectFile();
700 m_dwarf->SetDebugInfoIndexWasSavedToCache();