15ffd83dbSDimitry Andric //===-- ManualDWARFIndex.cpp ----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h" 100b57cec5SDimitry Andric #include "Plugins/Language/ObjC/ObjCLanguage.h" 110b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 120b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 130b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" 140b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" 1504eeddc0SDimitry Andric #include "lldb/Core/DataFileCache.h" 1681ad6265SDimitry Andric #include "lldb/Core/Debugger.h" 170b57cec5SDimitry Andric #include "lldb/Core/Module.h" 18fe6060f1SDimitry Andric #include "lldb/Core/Progress.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 2004eeddc0SDimitry Andric #include "lldb/Utility/DataEncoder.h" 2104eeddc0SDimitry Andric #include "lldb/Utility/DataExtractor.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 230b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 24fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 255ffd83dbSDimitry Andric #include "llvm/Support/ThreadPool.h" 26bdd1243dSDimitry Andric #include <optional> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace lldb_private; 290b57cec5SDimitry Andric using namespace lldb; 3081ad6265SDimitry Andric using namespace lldb_private::dwarf; 315f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric void ManualDWARFIndex::Index() { 3404eeddc0SDimitry Andric if (m_indexed) 350b57cec5SDimitry Andric return; 3604eeddc0SDimitry Andric m_indexed = true; 370b57cec5SDimitry Andric 38349cc55cSDimitry Andric ElapsedTime elapsed(m_index_time); 3904eeddc0SDimitry Andric LLDB_SCOPED_TIMERF("%p", static_cast<void *>(m_dwarf)); 4004eeddc0SDimitry Andric if (LoadFromCache()) { 4104eeddc0SDimitry Andric m_dwarf->SetDebugInfoIndexWasLoadedFromCache(); 4204eeddc0SDimitry Andric return; 4304eeddc0SDimitry Andric } 445ffd83dbSDimitry Andric 4504eeddc0SDimitry Andric DWARFDebugInfo &main_info = m_dwarf->DebugInfo(); 4604eeddc0SDimitry Andric SymbolFileDWARFDwo *dwp_dwarf = m_dwarf->GetDwpSymbolFile().get(); 475ffd83dbSDimitry Andric DWARFDebugInfo *dwp_info = dwp_dwarf ? &dwp_dwarf->DebugInfo() : nullptr; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric std::vector<DWARFUnit *> units_to_index; 505ffd83dbSDimitry Andric units_to_index.reserve(main_info.GetNumUnits() + 515ffd83dbSDimitry Andric (dwp_info ? dwp_info->GetNumUnits() : 0)); 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric // Process all units in the main file, as well as any type units in the dwp 545ffd83dbSDimitry Andric // file. Type units in dwo files are handled when we reach the dwo file in 555ffd83dbSDimitry Andric // IndexUnit. 565ffd83dbSDimitry Andric for (size_t U = 0; U < main_info.GetNumUnits(); ++U) { 575ffd83dbSDimitry Andric DWARFUnit *unit = main_info.GetUnitAtIndex(U); 580b57cec5SDimitry Andric if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0) 590b57cec5SDimitry Andric units_to_index.push_back(unit); 600b57cec5SDimitry Andric } 615ffd83dbSDimitry Andric if (dwp_info && dwp_info->ContainsTypeUnits()) { 625ffd83dbSDimitry Andric for (size_t U = 0; U < dwp_info->GetNumUnits(); ++U) { 63*0fca6ea1SDimitry Andric if (auto *tu = 64*0fca6ea1SDimitry Andric llvm::dyn_cast<DWARFTypeUnit>(dwp_info->GetUnitAtIndex(U))) { 65*0fca6ea1SDimitry Andric if (!m_type_sigs_to_avoid.contains(tu->GetTypeHash())) 665ffd83dbSDimitry Andric units_to_index.push_back(tu); 675ffd83dbSDimitry Andric } 685ffd83dbSDimitry Andric } 69*0fca6ea1SDimitry Andric } 705ffd83dbSDimitry Andric 710b57cec5SDimitry Andric if (units_to_index.empty()) 720b57cec5SDimitry Andric return; 730b57cec5SDimitry Andric 74fe6060f1SDimitry Andric StreamString module_desc; 75fe6060f1SDimitry Andric m_module.GetDescription(module_desc.AsRawOstream(), 76fe6060f1SDimitry Andric lldb::eDescriptionLevelBrief); 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric // Include 2 passes per unit to index for extracting DIEs from the unit and 79fe6060f1SDimitry Andric // indexing the unit, and then 8 extra entries for finalizing each index set. 80fe6060f1SDimitry Andric const uint64_t total_progress = units_to_index.size() * 2 + 8; 817a6dacacSDimitry Andric Progress progress("Manually indexing DWARF", module_desc.GetData(), 82fe6060f1SDimitry Andric total_progress); 83fe6060f1SDimitry Andric 840b57cec5SDimitry Andric std::vector<IndexSet> sets(units_to_index.size()); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // Keep memory down by clearing DIEs for any units if indexing 870b57cec5SDimitry Andric // caused us to load the unit's DIEs. 88bdd1243dSDimitry Andric std::vector<std::optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies( 890b57cec5SDimitry Andric units_to_index.size()); 900b57cec5SDimitry Andric auto parser_fn = [&](size_t cu_idx) { 915ffd83dbSDimitry Andric IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]); 92fe6060f1SDimitry Andric progress.Increment(); 930b57cec5SDimitry Andric }; 940b57cec5SDimitry Andric 95fe6060f1SDimitry Andric auto extract_fn = [&](size_t cu_idx) { 960b57cec5SDimitry Andric clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped(); 97fe6060f1SDimitry Andric progress.Increment(); 980b57cec5SDimitry Andric }; 990b57cec5SDimitry Andric 1005ffd83dbSDimitry Andric // Share one thread pool across operations to avoid the overhead of 1015ffd83dbSDimitry Andric // recreating the threads. 10281ad6265SDimitry Andric llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); 1035ffd83dbSDimitry Andric 1040b57cec5SDimitry Andric // Create a task runner that extracts dies for each DWARF unit in a 1055ffd83dbSDimitry Andric // separate thread. 1060b57cec5SDimitry Andric // First figure out which units didn't have their DIEs already 1070b57cec5SDimitry Andric // parsed and remember this. If no DIEs were parsed prior to this index 1080b57cec5SDimitry Andric // function call, we are going to want to clear the CU dies after we are 1090b57cec5SDimitry Andric // done indexing to make sure we don't pull in all DWARF dies, but we need 1100b57cec5SDimitry Andric // to wait until all units have been indexed in case a DIE in one 1110b57cec5SDimitry Andric // unit refers to another and the indexes accesses those DIEs. 1125ffd83dbSDimitry Andric for (size_t i = 0; i < units_to_index.size(); ++i) 11381ad6265SDimitry Andric task_group.async(extract_fn, i); 11481ad6265SDimitry Andric task_group.wait(); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Now create a task runner that can index each DWARF unit in a 1170b57cec5SDimitry Andric // separate thread so we can index quickly. 1185ffd83dbSDimitry Andric for (size_t i = 0; i < units_to_index.size(); ++i) 11981ad6265SDimitry Andric task_group.async(parser_fn, i); 12081ad6265SDimitry Andric task_group.wait(); 1210b57cec5SDimitry Andric 122fe6060f1SDimitry Andric auto finalize_fn = [this, &sets, &progress](NameToDIE(IndexSet::*index)) { 1230b57cec5SDimitry Andric NameToDIE &result = m_set.*index; 1240b57cec5SDimitry Andric for (auto &set : sets) 1250b57cec5SDimitry Andric result.Append(set.*index); 1260b57cec5SDimitry Andric result.Finalize(); 127fe6060f1SDimitry Andric progress.Increment(); 1280b57cec5SDimitry Andric }; 1290b57cec5SDimitry Andric 13081ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::function_basenames); 13181ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::function_fullnames); 13281ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::function_methods); 13381ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::function_selectors); 13481ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::objc_class_selectors); 13581ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::globals); 13681ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::types); 13781ad6265SDimitry Andric task_group.async(finalize_fn, &IndexSet::namespaces); 13881ad6265SDimitry Andric task_group.wait(); 13904eeddc0SDimitry Andric 14004eeddc0SDimitry Andric SaveToCache(); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1435ffd83dbSDimitry Andric void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, 1445ffd83dbSDimitry Andric IndexSet &set) { 1451fd87a68SDimitry Andric Log *log = GetLog(DWARFLog::Lookups); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (log) { 1480b57cec5SDimitry Andric m_module.LogMessage( 149bdd1243dSDimitry Andric log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]", 1500b57cec5SDimitry Andric unit.GetOffset()); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1535ffd83dbSDimitry Andric const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit); 1540b57cec5SDimitry Andric 155bdd1243dSDimitry Andric // First check if the unit has a DWO ID. If it does then we only want to index 156bdd1243dSDimitry Andric // the .dwo file or nothing at all. If we have a compile unit where we can't 157bdd1243dSDimitry Andric // locate the .dwo/.dwp file we don't want to index anything from the skeleton 158bdd1243dSDimitry Andric // compile unit because it is usally has no children unless 159bdd1243dSDimitry Andric // -fsplit-dwarf-inlining was used at compile time. This option will add a 160bdd1243dSDimitry Andric // copy of all DW_TAG_subprogram and any contained DW_TAG_inline_subroutine 161bdd1243dSDimitry Andric // DIEs so that symbolication will still work in the absence of the .dwo/.dwp 162bdd1243dSDimitry Andric // file, but the functions have no return types and all arguments and locals 163bdd1243dSDimitry Andric // have been removed. So we don't want to index any of these hacked up 164bdd1243dSDimitry Andric // function types. Types can still exist in the skeleton compile unit DWARF 165bdd1243dSDimitry Andric // though as some functions have template parameter types and other things 166bdd1243dSDimitry Andric // that cause extra copies of types to be included, but we should find these 167bdd1243dSDimitry Andric // types in the .dwo file only as methods could have return types removed and 16806c3fb27SDimitry Andric // we don't have to index incomplete types from the skeleton compile unit. 169bdd1243dSDimitry Andric if (unit.GetDWOId()) { 17006c3fb27SDimitry Andric // Index the .dwo or dwp instead of the skeleton unit. 1710b57cec5SDimitry Andric if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) { 1725ffd83dbSDimitry Andric // Type units in a dwp file are indexed separately, so we just need to 17306c3fb27SDimitry Andric // process the split unit here. However, if the split unit is in a dwo 17406c3fb27SDimitry Andric // file, then we need to process type units here. 1755ffd83dbSDimitry Andric if (dwo_symbol_file == dwp) { 1765ffd83dbSDimitry Andric IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set); 1775ffd83dbSDimitry Andric } else { 1785ffd83dbSDimitry Andric DWARFDebugInfo &dwo_info = dwo_symbol_file->DebugInfo(); 1790b57cec5SDimitry Andric for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i) 1800b57cec5SDimitry Andric IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set); 1810b57cec5SDimitry Andric } 18206c3fb27SDimitry Andric return; 1830b57cec5SDimitry Andric } 18406c3fb27SDimitry Andric // This was a DWARF5 skeleton CU and the .dwo file couldn't be located. 18506c3fb27SDimitry Andric if (unit.GetVersion() >= 5 && unit.IsSkeletonUnit()) 18606c3fb27SDimitry Andric return; 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric // Either this is a DWARF 4 + fission CU with the .dwo file 18906c3fb27SDimitry Andric // missing, or it's a -gmodules pch or pcm. Try to detect the 19006c3fb27SDimitry Andric // latter by checking whether the first DIE is a DW_TAG_module. 19106c3fb27SDimitry Andric // If it's a pch/pcm, continue indexing it. 19206c3fb27SDimitry Andric if (unit.GetDIE(unit.GetFirstDIEOffset()).GetFirstChild().Tag() != 19306c3fb27SDimitry Andric llvm::dwarf::DW_TAG_module) 19406c3fb27SDimitry Andric return; 19506c3fb27SDimitry Andric } 19606c3fb27SDimitry Andric // We have a normal compile unit which we want to index. 197bdd1243dSDimitry Andric IndexUnitImpl(unit, cu_language, set); 198bdd1243dSDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit, 2010b57cec5SDimitry Andric const LanguageType cu_language, 2020b57cec5SDimitry Andric IndexSet &set) { 2030b57cec5SDimitry Andric for (const DWARFDebugInfoEntry &die : unit.dies()) { 2040b57cec5SDimitry Andric const dw_tag_t tag = die.Tag(); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric switch (tag) { 2070b57cec5SDimitry Andric case DW_TAG_array_type: 2080b57cec5SDimitry Andric case DW_TAG_base_type: 2090b57cec5SDimitry Andric case DW_TAG_class_type: 2100b57cec5SDimitry Andric case DW_TAG_constant: 2110b57cec5SDimitry Andric case DW_TAG_enumeration_type: 2120b57cec5SDimitry Andric case DW_TAG_inlined_subroutine: 2130b57cec5SDimitry Andric case DW_TAG_namespace: 21406c3fb27SDimitry Andric case DW_TAG_imported_declaration: 2150b57cec5SDimitry Andric case DW_TAG_string_type: 2160b57cec5SDimitry Andric case DW_TAG_structure_type: 2170b57cec5SDimitry Andric case DW_TAG_subprogram: 2180b57cec5SDimitry Andric case DW_TAG_subroutine_type: 2190b57cec5SDimitry Andric case DW_TAG_typedef: 2200b57cec5SDimitry Andric case DW_TAG_union_type: 2210b57cec5SDimitry Andric case DW_TAG_unspecified_type: 2220b57cec5SDimitry Andric case DW_TAG_variable: 2230b57cec5SDimitry Andric break; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric default: 2260b57cec5SDimitry Andric continue; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric const char *name = nullptr; 2300b57cec5SDimitry Andric const char *mangled_cstr = nullptr; 2310b57cec5SDimitry Andric bool is_declaration = false; 2320b57cec5SDimitry Andric bool has_address = false; 2330b57cec5SDimitry Andric bool has_location_or_const_value = false; 2340b57cec5SDimitry Andric bool is_global_or_static_variable = false; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric DWARFFormValue specification_die_form; 23706c3fb27SDimitry Andric DWARFAttributes attributes = die.GetAttributes(&unit); 23806c3fb27SDimitry Andric for (size_t i = 0; i < attributes.Size(); ++i) { 2390b57cec5SDimitry Andric dw_attr_t attr = attributes.AttributeAtIndex(i); 2400b57cec5SDimitry Andric DWARFFormValue form_value; 2410b57cec5SDimitry Andric switch (attr) { 24206c3fb27SDimitry Andric default: 24306c3fb27SDimitry Andric break; 2440b57cec5SDimitry Andric case DW_AT_name: 2450b57cec5SDimitry Andric if (attributes.ExtractFormValueAtIndex(i, form_value)) 2460b57cec5SDimitry Andric name = form_value.AsCString(); 2470b57cec5SDimitry Andric break; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric case DW_AT_declaration: 2500b57cec5SDimitry Andric if (attributes.ExtractFormValueAtIndex(i, form_value)) 2510b57cec5SDimitry Andric is_declaration = form_value.Unsigned() != 0; 2520b57cec5SDimitry Andric break; 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric case DW_AT_MIPS_linkage_name: 2550b57cec5SDimitry Andric case DW_AT_linkage_name: 2560b57cec5SDimitry Andric if (attributes.ExtractFormValueAtIndex(i, form_value)) 2570b57cec5SDimitry Andric mangled_cstr = form_value.AsCString(); 2580b57cec5SDimitry Andric break; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric case DW_AT_low_pc: 2610b57cec5SDimitry Andric case DW_AT_high_pc: 2620b57cec5SDimitry Andric case DW_AT_ranges: 2630b57cec5SDimitry Andric has_address = true; 2640b57cec5SDimitry Andric break; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric case DW_AT_entry_pc: 2670b57cec5SDimitry Andric has_address = true; 2680b57cec5SDimitry Andric break; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric case DW_AT_location: 2710b57cec5SDimitry Andric case DW_AT_const_value: 2720b57cec5SDimitry Andric has_location_or_const_value = true; 2735ffd83dbSDimitry Andric is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable(); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric break; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric case DW_AT_specification: 2780b57cec5SDimitry Andric if (attributes.ExtractFormValueAtIndex(i, form_value)) 2790b57cec5SDimitry Andric specification_die_form = form_value; 2800b57cec5SDimitry Andric break; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric DIERef ref = *DWARFDIE(&unit, &die).GetDIERef(); 2850b57cec5SDimitry Andric switch (tag) { 2860b57cec5SDimitry Andric case DW_TAG_inlined_subroutine: 2870b57cec5SDimitry Andric case DW_TAG_subprogram: 2880b57cec5SDimitry Andric if (has_address) { 2890b57cec5SDimitry Andric if (name) { 2900b57cec5SDimitry Andric bool is_objc_method = false; 2910b57cec5SDimitry Andric if (cu_language == eLanguageTypeObjC || 2920b57cec5SDimitry Andric cu_language == eLanguageTypeObjC_plus_plus) { 29306c3fb27SDimitry Andric std::optional<const ObjCLanguage::MethodName> objc_method = 29406c3fb27SDimitry Andric ObjCLanguage::MethodName::Create(name, true); 29506c3fb27SDimitry Andric if (objc_method) { 2960b57cec5SDimitry Andric is_objc_method = true; 2970b57cec5SDimitry Andric ConstString class_name_with_category( 29806c3fb27SDimitry Andric objc_method->GetClassNameWithCategory()); 29906c3fb27SDimitry Andric ConstString objc_selector_name(objc_method->GetSelector()); 3000b57cec5SDimitry Andric ConstString objc_fullname_no_category_name( 30106c3fb27SDimitry Andric objc_method->GetFullNameWithoutCategory().c_str()); 30206c3fb27SDimitry Andric ConstString class_name_no_category(objc_method->GetClassName()); 3030b57cec5SDimitry Andric set.function_fullnames.Insert(ConstString(name), ref); 3040b57cec5SDimitry Andric if (class_name_with_category) 3050b57cec5SDimitry Andric set.objc_class_selectors.Insert(class_name_with_category, ref); 3060b57cec5SDimitry Andric if (class_name_no_category && 3070b57cec5SDimitry Andric class_name_no_category != class_name_with_category) 3080b57cec5SDimitry Andric set.objc_class_selectors.Insert(class_name_no_category, ref); 3090b57cec5SDimitry Andric if (objc_selector_name) 3100b57cec5SDimitry Andric set.function_selectors.Insert(objc_selector_name, ref); 3110b57cec5SDimitry Andric if (objc_fullname_no_category_name) 3120b57cec5SDimitry Andric set.function_fullnames.Insert(objc_fullname_no_category_name, 3130b57cec5SDimitry Andric ref); 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric // If we have a mangled name, then the DW_AT_name attribute is 3170b57cec5SDimitry Andric // usually the method name without the class or any parameters 3180b57cec5SDimitry Andric bool is_method = DWARFDIE(&unit, &die).IsMethod(); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric if (is_method) 3210b57cec5SDimitry Andric set.function_methods.Insert(ConstString(name), ref); 3220b57cec5SDimitry Andric else 3230b57cec5SDimitry Andric set.function_basenames.Insert(ConstString(name), ref); 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric if (!is_method && !mangled_cstr && !is_objc_method) 3260b57cec5SDimitry Andric set.function_fullnames.Insert(ConstString(name), ref); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric if (mangled_cstr) { 3290b57cec5SDimitry Andric // Make sure our mangled name isn't the same string table entry as 3300b57cec5SDimitry Andric // our name. If it starts with '_', then it is ok, else compare the 3310b57cec5SDimitry Andric // string to make sure it isn't the same and we don't end up with 3320b57cec5SDimitry Andric // duplicate entries 3330b57cec5SDimitry Andric if (name && name != mangled_cstr && 3340b57cec5SDimitry Andric ((mangled_cstr[0] == '_') || 3350b57cec5SDimitry Andric (::strcmp(name, mangled_cstr) != 0))) { 3360b57cec5SDimitry Andric set.function_fullnames.Insert(ConstString(mangled_cstr), ref); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric break; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric case DW_TAG_array_type: 3430b57cec5SDimitry Andric case DW_TAG_base_type: 3440b57cec5SDimitry Andric case DW_TAG_class_type: 3450b57cec5SDimitry Andric case DW_TAG_constant: 3460b57cec5SDimitry Andric case DW_TAG_enumeration_type: 3470b57cec5SDimitry Andric case DW_TAG_string_type: 3480b57cec5SDimitry Andric case DW_TAG_structure_type: 3490b57cec5SDimitry Andric case DW_TAG_subroutine_type: 3500b57cec5SDimitry Andric case DW_TAG_typedef: 3510b57cec5SDimitry Andric case DW_TAG_union_type: 3520b57cec5SDimitry Andric case DW_TAG_unspecified_type: 3530b57cec5SDimitry Andric if (name && !is_declaration) 3540b57cec5SDimitry Andric set.types.Insert(ConstString(name), ref); 3550b57cec5SDimitry Andric if (mangled_cstr && !is_declaration) 3560b57cec5SDimitry Andric set.types.Insert(ConstString(mangled_cstr), ref); 3570b57cec5SDimitry Andric break; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric case DW_TAG_namespace: 36006c3fb27SDimitry Andric case DW_TAG_imported_declaration: 3610b57cec5SDimitry Andric if (name) 3620b57cec5SDimitry Andric set.namespaces.Insert(ConstString(name), ref); 3630b57cec5SDimitry Andric break; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric case DW_TAG_variable: 3660b57cec5SDimitry Andric if (name && has_location_or_const_value && is_global_or_static_variable) { 3670b57cec5SDimitry Andric set.globals.Insert(ConstString(name), ref); 3680b57cec5SDimitry Andric // Be sure to include variables by their mangled and demangled names if 3690b57cec5SDimitry Andric // they have any since a variable can have a basename "i", a mangled 3700b57cec5SDimitry Andric // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name 3710b57cec5SDimitry Andric // "(anonymous namespace)::i"... 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric // Make sure our mangled name isn't the same string table entry as our 3740b57cec5SDimitry Andric // name. If it starts with '_', then it is ok, else compare the string 3750b57cec5SDimitry Andric // to make sure it isn't the same and we don't end up with duplicate 3760b57cec5SDimitry Andric // entries 3770b57cec5SDimitry Andric if (mangled_cstr && name != mangled_cstr && 3780b57cec5SDimitry Andric ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { 3790b57cec5SDimitry Andric set.globals.Insert(ConstString(mangled_cstr), ref); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric break; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric default: 3850b57cec5SDimitry Andric continue; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3905ffd83dbSDimitry Andric void ManualDWARFIndex::GetGlobalVariables( 3915ffd83dbSDimitry Andric ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) { 3920b57cec5SDimitry Andric Index(); 3935ffd83dbSDimitry Andric m_set.globals.Find(basename, 3945ffd83dbSDimitry Andric DIERefCallback(callback, basename.GetStringRef())); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3975ffd83dbSDimitry Andric void ManualDWARFIndex::GetGlobalVariables( 3985ffd83dbSDimitry Andric const RegularExpression ®ex, 3995ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 4000b57cec5SDimitry Andric Index(); 4015ffd83dbSDimitry Andric m_set.globals.Find(regex, DIERefCallback(callback, regex.GetText())); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4045ffd83dbSDimitry Andric void ManualDWARFIndex::GetGlobalVariables( 405349cc55cSDimitry Andric DWARFUnit &unit, llvm::function_ref<bool(DWARFDIE die)> callback) { 4060b57cec5SDimitry Andric Index(); 4075ffd83dbSDimitry Andric m_set.globals.FindAllEntriesForUnit(unit, DIERefCallback(callback)); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4105ffd83dbSDimitry Andric void ManualDWARFIndex::GetObjCMethods( 4115ffd83dbSDimitry Andric ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) { 4120b57cec5SDimitry Andric Index(); 4135ffd83dbSDimitry Andric m_set.objc_class_selectors.Find( 4145ffd83dbSDimitry Andric class_name, DIERefCallback(callback, class_name.GetStringRef())); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4175ffd83dbSDimitry Andric void ManualDWARFIndex::GetCompleteObjCClass( 4185ffd83dbSDimitry Andric ConstString class_name, bool must_be_implementation, 4195ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 4200b57cec5SDimitry Andric Index(); 4215ffd83dbSDimitry Andric m_set.types.Find(class_name, 4225ffd83dbSDimitry Andric DIERefCallback(callback, class_name.GetStringRef())); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4255ffd83dbSDimitry Andric void ManualDWARFIndex::GetTypes( 4265ffd83dbSDimitry Andric ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) { 4270b57cec5SDimitry Andric Index(); 4285ffd83dbSDimitry Andric m_set.types.Find(name, DIERefCallback(callback, name.GetStringRef())); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4315ffd83dbSDimitry Andric void ManualDWARFIndex::GetTypes( 4325ffd83dbSDimitry Andric const DWARFDeclContext &context, 4335ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 4340b57cec5SDimitry Andric Index(); 4355ffd83dbSDimitry Andric auto name = context[0].name; 4365ffd83dbSDimitry Andric m_set.types.Find(ConstString(name), 4375ffd83dbSDimitry Andric DIERefCallback(callback, llvm::StringRef(name))); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4405ffd83dbSDimitry Andric void ManualDWARFIndex::GetNamespaces( 4415ffd83dbSDimitry Andric ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) { 4420b57cec5SDimitry Andric Index(); 4435ffd83dbSDimitry Andric m_set.namespaces.Find(name, DIERefCallback(callback, name.GetStringRef())); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4465ffd83dbSDimitry Andric void ManualDWARFIndex::GetFunctions( 447bdd1243dSDimitry Andric const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, 448bdd1243dSDimitry Andric const CompilerDeclContext &parent_decl_ctx, 4495ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 4500b57cec5SDimitry Andric Index(); 451bdd1243dSDimitry Andric ConstString name = lookup_info.GetLookupName(); 452bdd1243dSDimitry Andric FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeFull) { 4555ffd83dbSDimitry Andric if (!m_set.function_fullnames.Find( 4565ffd83dbSDimitry Andric name, DIERefCallback( 4575ffd83dbSDimitry Andric [&](DWARFDIE die) { 4585ffd83dbSDimitry Andric if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, 4595ffd83dbSDimitry Andric die)) 4605ffd83dbSDimitry Andric return true; 4615ffd83dbSDimitry Andric return callback(die); 4625ffd83dbSDimitry Andric }, 4635ffd83dbSDimitry Andric name.GetStringRef()))) 4645ffd83dbSDimitry Andric return; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeBase) { 4675ffd83dbSDimitry Andric if (!m_set.function_basenames.Find( 4685ffd83dbSDimitry Andric name, DIERefCallback( 4695ffd83dbSDimitry Andric [&](DWARFDIE die) { 4705ffd83dbSDimitry Andric if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, 4715ffd83dbSDimitry Andric die)) 4725ffd83dbSDimitry Andric return true; 4735ffd83dbSDimitry Andric return callback(die); 4745ffd83dbSDimitry Andric }, 4755ffd83dbSDimitry Andric name.GetStringRef()))) 4765ffd83dbSDimitry Andric return; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) { 4805ffd83dbSDimitry Andric if (!m_set.function_methods.Find( 4815ffd83dbSDimitry Andric name, DIERefCallback(callback, name.GetStringRef()))) 4825ffd83dbSDimitry Andric return; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeSelector && 4860b57cec5SDimitry Andric !parent_decl_ctx.IsValid()) { 4875ffd83dbSDimitry Andric if (!m_set.function_selectors.Find( 4885ffd83dbSDimitry Andric name, DIERefCallback(callback, name.GetStringRef()))) 4895ffd83dbSDimitry Andric return; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4935ffd83dbSDimitry Andric void ManualDWARFIndex::GetFunctions( 4945ffd83dbSDimitry Andric const RegularExpression ®ex, 4955ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 4960b57cec5SDimitry Andric Index(); 4970b57cec5SDimitry Andric 4985ffd83dbSDimitry Andric if (!m_set.function_basenames.Find(regex, 4995ffd83dbSDimitry Andric DIERefCallback(callback, regex.GetText()))) 5005ffd83dbSDimitry Andric return; 5015ffd83dbSDimitry Andric if (!m_set.function_fullnames.Find(regex, 5025ffd83dbSDimitry Andric DIERefCallback(callback, regex.GetText()))) 5035ffd83dbSDimitry Andric return; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric void ManualDWARFIndex::Dump(Stream &s) { 5070b57cec5SDimitry Andric s.Format("Manual DWARF index for ({0}) '{1:F}':", 5080b57cec5SDimitry Andric m_module.GetArchitecture().GetArchitectureName(), 5090b57cec5SDimitry Andric m_module.GetObjectFile()->GetFileSpec()); 5100b57cec5SDimitry Andric s.Printf("\nFunction basenames:\n"); 5110b57cec5SDimitry Andric m_set.function_basenames.Dump(&s); 5120b57cec5SDimitry Andric s.Printf("\nFunction fullnames:\n"); 5130b57cec5SDimitry Andric m_set.function_fullnames.Dump(&s); 5140b57cec5SDimitry Andric s.Printf("\nFunction methods:\n"); 5150b57cec5SDimitry Andric m_set.function_methods.Dump(&s); 5160b57cec5SDimitry Andric s.Printf("\nFunction selectors:\n"); 5170b57cec5SDimitry Andric m_set.function_selectors.Dump(&s); 5180b57cec5SDimitry Andric s.Printf("\nObjective-C class selectors:\n"); 5190b57cec5SDimitry Andric m_set.objc_class_selectors.Dump(&s); 5200b57cec5SDimitry Andric s.Printf("\nGlobals and statics:\n"); 5210b57cec5SDimitry Andric m_set.globals.Dump(&s); 5220b57cec5SDimitry Andric s.Printf("\nTypes:\n"); 5230b57cec5SDimitry Andric m_set.types.Dump(&s); 5240b57cec5SDimitry Andric s.Printf("\nNamespaces:\n"); 5250b57cec5SDimitry Andric m_set.namespaces.Dump(&s); 5260b57cec5SDimitry Andric } 52704eeddc0SDimitry Andric 52804eeddc0SDimitry Andric constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX"); 52904eeddc0SDimitry Andric // Define IDs for the different tables when encoding and decoding the 53004eeddc0SDimitry Andric // ManualDWARFIndex NameToDIE objects so we can avoid saving any empty maps. 53104eeddc0SDimitry Andric enum DataID { 53204eeddc0SDimitry Andric kDataIDFunctionBasenames = 1u, 53304eeddc0SDimitry Andric kDataIDFunctionFullnames, 53404eeddc0SDimitry Andric kDataIDFunctionMethods, 53504eeddc0SDimitry Andric kDataIDFunctionSelectors, 53604eeddc0SDimitry Andric kDataIDFunctionObjcClassSelectors, 53704eeddc0SDimitry Andric kDataIDGlobals, 53804eeddc0SDimitry Andric kDataIDTypes, 53904eeddc0SDimitry Andric kDataIDNamespaces, 54004eeddc0SDimitry Andric kDataIDEnd = 255u, 54104eeddc0SDimitry Andric 54204eeddc0SDimitry Andric }; 54306c3fb27SDimitry Andric 54406c3fb27SDimitry Andric // Version 2 changes the encoding of DIERef objects used in the DWARF manual 54506c3fb27SDimitry Andric // index name tables. See DIERef class for details. 54606c3fb27SDimitry Andric constexpr uint32_t CURRENT_CACHE_VERSION = 2; 54704eeddc0SDimitry Andric 54804eeddc0SDimitry Andric bool ManualDWARFIndex::IndexSet::Decode(const DataExtractor &data, 54904eeddc0SDimitry Andric lldb::offset_t *offset_ptr) { 55004eeddc0SDimitry Andric StringTableReader strtab; 55104eeddc0SDimitry Andric // We now decode the string table for all strings in the data cache file. 55204eeddc0SDimitry Andric if (!strtab.Decode(data, offset_ptr)) 55304eeddc0SDimitry Andric return false; 55404eeddc0SDimitry Andric 55504eeddc0SDimitry Andric llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); 55604eeddc0SDimitry Andric if (identifier != kIdentifierManualDWARFIndex) 55704eeddc0SDimitry Andric return false; 55804eeddc0SDimitry Andric const uint32_t version = data.GetU32(offset_ptr); 55904eeddc0SDimitry Andric if (version != CURRENT_CACHE_VERSION) 56004eeddc0SDimitry Andric return false; 56104eeddc0SDimitry Andric 56204eeddc0SDimitry Andric bool done = false; 56304eeddc0SDimitry Andric while (!done) { 56404eeddc0SDimitry Andric switch (data.GetU8(offset_ptr)) { 56504eeddc0SDimitry Andric default: 56604eeddc0SDimitry Andric // If we got here, this is not expected, we expect the data IDs to match 56704eeddc0SDimitry Andric // one of the values from the DataID enumeration. 56804eeddc0SDimitry Andric return false; 56904eeddc0SDimitry Andric case kDataIDFunctionBasenames: 57004eeddc0SDimitry Andric if (!function_basenames.Decode(data, offset_ptr, strtab)) 57104eeddc0SDimitry Andric return false; 57204eeddc0SDimitry Andric break; 57304eeddc0SDimitry Andric case kDataIDFunctionFullnames: 57404eeddc0SDimitry Andric if (!function_fullnames.Decode(data, offset_ptr, strtab)) 57504eeddc0SDimitry Andric return false; 57604eeddc0SDimitry Andric break; 57704eeddc0SDimitry Andric case kDataIDFunctionMethods: 57804eeddc0SDimitry Andric if (!function_methods.Decode(data, offset_ptr, strtab)) 57904eeddc0SDimitry Andric return false; 58004eeddc0SDimitry Andric break; 58104eeddc0SDimitry Andric case kDataIDFunctionSelectors: 58204eeddc0SDimitry Andric if (!function_selectors.Decode(data, offset_ptr, strtab)) 58304eeddc0SDimitry Andric return false; 58404eeddc0SDimitry Andric break; 58504eeddc0SDimitry Andric case kDataIDFunctionObjcClassSelectors: 58604eeddc0SDimitry Andric if (!objc_class_selectors.Decode(data, offset_ptr, strtab)) 58704eeddc0SDimitry Andric return false; 58804eeddc0SDimitry Andric break; 58904eeddc0SDimitry Andric case kDataIDGlobals: 59004eeddc0SDimitry Andric if (!globals.Decode(data, offset_ptr, strtab)) 59104eeddc0SDimitry Andric return false; 59204eeddc0SDimitry Andric break; 59304eeddc0SDimitry Andric case kDataIDTypes: 59404eeddc0SDimitry Andric if (!types.Decode(data, offset_ptr, strtab)) 59504eeddc0SDimitry Andric return false; 59604eeddc0SDimitry Andric break; 59704eeddc0SDimitry Andric case kDataIDNamespaces: 59804eeddc0SDimitry Andric if (!namespaces.Decode(data, offset_ptr, strtab)) 59904eeddc0SDimitry Andric return false; 60004eeddc0SDimitry Andric break; 60104eeddc0SDimitry Andric case kDataIDEnd: 60204eeddc0SDimitry Andric // We got to the end of our NameToDIE encodings. 60304eeddc0SDimitry Andric done = true; 60404eeddc0SDimitry Andric break; 60504eeddc0SDimitry Andric } 60604eeddc0SDimitry Andric } 60704eeddc0SDimitry Andric // Success! 60804eeddc0SDimitry Andric return true; 60904eeddc0SDimitry Andric } 61004eeddc0SDimitry Andric 61104eeddc0SDimitry Andric void ManualDWARFIndex::IndexSet::Encode(DataEncoder &encoder) const { 61204eeddc0SDimitry Andric ConstStringTable strtab; 61304eeddc0SDimitry Andric 61404eeddc0SDimitry Andric // Encoder the DWARF index into a separate encoder first. This allows us 61504eeddc0SDimitry Andric // gather all of the strings we willl need in "strtab" as we will need to 61604eeddc0SDimitry Andric // write the string table out before the symbol table. 61704eeddc0SDimitry Andric DataEncoder index_encoder(encoder.GetByteOrder(), 61804eeddc0SDimitry Andric encoder.GetAddressByteSize()); 61904eeddc0SDimitry Andric 62004eeddc0SDimitry Andric index_encoder.AppendData(kIdentifierManualDWARFIndex); 62104eeddc0SDimitry Andric // Encode the data version. 62204eeddc0SDimitry Andric index_encoder.AppendU32(CURRENT_CACHE_VERSION); 62304eeddc0SDimitry Andric 62404eeddc0SDimitry Andric if (!function_basenames.IsEmpty()) { 62504eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDFunctionBasenames); 62604eeddc0SDimitry Andric function_basenames.Encode(index_encoder, strtab); 62704eeddc0SDimitry Andric } 62804eeddc0SDimitry Andric if (!function_fullnames.IsEmpty()) { 62904eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDFunctionFullnames); 63004eeddc0SDimitry Andric function_fullnames.Encode(index_encoder, strtab); 63104eeddc0SDimitry Andric } 63204eeddc0SDimitry Andric if (!function_methods.IsEmpty()) { 63304eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDFunctionMethods); 63404eeddc0SDimitry Andric function_methods.Encode(index_encoder, strtab); 63504eeddc0SDimitry Andric } 63604eeddc0SDimitry Andric if (!function_selectors.IsEmpty()) { 63704eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDFunctionSelectors); 63804eeddc0SDimitry Andric function_selectors.Encode(index_encoder, strtab); 63904eeddc0SDimitry Andric } 64004eeddc0SDimitry Andric if (!objc_class_selectors.IsEmpty()) { 64104eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDFunctionObjcClassSelectors); 64204eeddc0SDimitry Andric objc_class_selectors.Encode(index_encoder, strtab); 64304eeddc0SDimitry Andric } 64404eeddc0SDimitry Andric if (!globals.IsEmpty()) { 64504eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDGlobals); 64604eeddc0SDimitry Andric globals.Encode(index_encoder, strtab); 64704eeddc0SDimitry Andric } 64804eeddc0SDimitry Andric if (!types.IsEmpty()) { 64904eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDTypes); 65004eeddc0SDimitry Andric types.Encode(index_encoder, strtab); 65104eeddc0SDimitry Andric } 65204eeddc0SDimitry Andric if (!namespaces.IsEmpty()) { 65304eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDNamespaces); 65404eeddc0SDimitry Andric namespaces.Encode(index_encoder, strtab); 65504eeddc0SDimitry Andric } 65604eeddc0SDimitry Andric index_encoder.AppendU8(kDataIDEnd); 65704eeddc0SDimitry Andric 65804eeddc0SDimitry Andric // Now that all strings have been gathered, we will emit the string table. 65904eeddc0SDimitry Andric strtab.Encode(encoder); 6605f757f3fSDimitry Andric // Followed by the symbol table data. 66104eeddc0SDimitry Andric encoder.AppendData(index_encoder.GetData()); 66204eeddc0SDimitry Andric } 66304eeddc0SDimitry Andric 66404eeddc0SDimitry Andric bool ManualDWARFIndex::Decode(const DataExtractor &data, 66504eeddc0SDimitry Andric lldb::offset_t *offset_ptr, 66604eeddc0SDimitry Andric bool &signature_mismatch) { 66704eeddc0SDimitry Andric signature_mismatch = false; 66804eeddc0SDimitry Andric CacheSignature signature; 66904eeddc0SDimitry Andric if (!signature.Decode(data, offset_ptr)) 67004eeddc0SDimitry Andric return false; 67104eeddc0SDimitry Andric if (CacheSignature(m_dwarf->GetObjectFile()) != signature) { 67204eeddc0SDimitry Andric signature_mismatch = true; 67304eeddc0SDimitry Andric return false; 67404eeddc0SDimitry Andric } 67504eeddc0SDimitry Andric IndexSet set; 67604eeddc0SDimitry Andric if (!set.Decode(data, offset_ptr)) 67704eeddc0SDimitry Andric return false; 67804eeddc0SDimitry Andric m_set = std::move(set); 67904eeddc0SDimitry Andric return true; 68004eeddc0SDimitry Andric } 68104eeddc0SDimitry Andric 68204eeddc0SDimitry Andric bool ManualDWARFIndex::Encode(DataEncoder &encoder) const { 68304eeddc0SDimitry Andric CacheSignature signature(m_dwarf->GetObjectFile()); 68404eeddc0SDimitry Andric if (!signature.Encode(encoder)) 68504eeddc0SDimitry Andric return false; 68604eeddc0SDimitry Andric m_set.Encode(encoder); 68704eeddc0SDimitry Andric return true; 68804eeddc0SDimitry Andric } 68904eeddc0SDimitry Andric 69004eeddc0SDimitry Andric std::string ManualDWARFIndex::GetCacheKey() { 69104eeddc0SDimitry Andric std::string key; 69204eeddc0SDimitry Andric llvm::raw_string_ostream strm(key); 69304eeddc0SDimitry Andric // DWARF Index can come from different object files for the same module. A 69404eeddc0SDimitry Andric // module can have one object file as the main executable and might have 69504eeddc0SDimitry Andric // another object file in a separate symbol file, or we might have a .dwo file 69604eeddc0SDimitry Andric // that claims its module is the main executable. 69704eeddc0SDimitry Andric ObjectFile *objfile = m_dwarf->GetObjectFile(); 69804eeddc0SDimitry Andric strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-" 69904eeddc0SDimitry Andric << llvm::format_hex(objfile->GetCacheHash(), 10); 70004eeddc0SDimitry Andric return strm.str(); 70104eeddc0SDimitry Andric } 70204eeddc0SDimitry Andric 70304eeddc0SDimitry Andric bool ManualDWARFIndex::LoadFromCache() { 70404eeddc0SDimitry Andric DataFileCache *cache = Module::GetIndexCache(); 70504eeddc0SDimitry Andric if (!cache) 70604eeddc0SDimitry Andric return false; 70704eeddc0SDimitry Andric ObjectFile *objfile = m_dwarf->GetObjectFile(); 70804eeddc0SDimitry Andric if (!objfile) 70904eeddc0SDimitry Andric return false; 71004eeddc0SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up = 71104eeddc0SDimitry Andric cache->GetCachedData(GetCacheKey()); 71204eeddc0SDimitry Andric if (!mem_buffer_up) 71304eeddc0SDimitry Andric return false; 71404eeddc0SDimitry Andric DataExtractor data(mem_buffer_up->getBufferStart(), 71504eeddc0SDimitry Andric mem_buffer_up->getBufferSize(), 71604eeddc0SDimitry Andric endian::InlHostByteOrder(), 71704eeddc0SDimitry Andric objfile->GetAddressByteSize()); 71804eeddc0SDimitry Andric bool signature_mismatch = false; 71904eeddc0SDimitry Andric lldb::offset_t offset = 0; 72004eeddc0SDimitry Andric const bool result = Decode(data, &offset, signature_mismatch); 72104eeddc0SDimitry Andric if (signature_mismatch) 72204eeddc0SDimitry Andric cache->RemoveCacheFile(GetCacheKey()); 72304eeddc0SDimitry Andric return result; 72404eeddc0SDimitry Andric } 72504eeddc0SDimitry Andric 72604eeddc0SDimitry Andric void ManualDWARFIndex::SaveToCache() { 72704eeddc0SDimitry Andric DataFileCache *cache = Module::GetIndexCache(); 72804eeddc0SDimitry Andric if (!cache) 72904eeddc0SDimitry Andric return; // Caching is not enabled. 73004eeddc0SDimitry Andric ObjectFile *objfile = m_dwarf->GetObjectFile(); 73104eeddc0SDimitry Andric if (!objfile) 73204eeddc0SDimitry Andric return; 73304eeddc0SDimitry Andric DataEncoder file(endian::InlHostByteOrder(), objfile->GetAddressByteSize()); 73404eeddc0SDimitry Andric // Encode will return false if the object file doesn't have anything to make 73504eeddc0SDimitry Andric // a signature from. 73604eeddc0SDimitry Andric if (Encode(file)) { 73704eeddc0SDimitry Andric if (cache->SetCachedData(GetCacheKey(), file.GetData())) 73804eeddc0SDimitry Andric m_dwarf->SetDebugInfoIndexWasSavedToCache(); 73904eeddc0SDimitry Andric } 74004eeddc0SDimitry Andric } 741