LLDB mainline
ManualDWARFIndex.cpp
Go to the documentation of this file.
1//===-- ManualDWARFIndex.cpp ----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
16#include "lldb/Core/Debugger.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/Progress.h"
22#include "lldb/Utility/Stream.h"
23#include "lldb/Utility/Timer.h"
24#include "llvm/Support/FormatVariadic.h"
25#include "llvm/Support/ThreadPool.h"
26#include <optional>
27
28using namespace lldb_private;
29using namespace lldb;
30using namespace lldb_private::dwarf;
31using namespace lldb_private::plugin::dwarf;
32
34 if (m_indexed)
35 return;
36 m_indexed = true;
37
39 LLDB_SCOPED_TIMERF("%p", static_cast<void *>(m_dwarf));
40 if (LoadFromCache()) {
42 return;
43 }
44
45 DWARFDebugInfo &main_info = m_dwarf->DebugInfo();
46 SymbolFileDWARFDwo *dwp_dwarf = m_dwarf->GetDwpSymbolFile().get();
47 DWARFDebugInfo *dwp_info = dwp_dwarf ? &dwp_dwarf->DebugInfo() : nullptr;
48
49 std::vector<DWARFUnit *> units_to_index;
50 units_to_index.reserve(main_info.GetNumUnits() +
51 (dwp_info ? dwp_info->GetNumUnits() : 0));
52
53 // Process all units in the main file, as well as any type units in the dwp
54 // file. Type units in dwo files are handled when we reach the dwo file in
55 // IndexUnit.
56 for (size_t U = 0; U < main_info.GetNumUnits(); ++U) {
57 DWARFUnit *unit = main_info.GetUnitAtIndex(U);
58 if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0)
59 units_to_index.push_back(unit);
60 }
61 if (dwp_info && dwp_info->ContainsTypeUnits()) {
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);
65 }
66 }
67
68 if (units_to_index.empty())
69 return;
70
71 StreamString module_desc;
74
75 // Include 2 passes per unit to index for extracting DIEs from the unit and
76 // indexing the unit, and then 8 extra entries for finalizing each index set.
77 const uint64_t total_progress = units_to_index.size() * 2 + 8;
78 Progress progress(
79 llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()),
80 total_progress);
81
82 std::vector<IndexSet> sets(units_to_index.size());
83
84 // Keep memory down by clearing DIEs for any units if indexing
85 // caused us to load the unit's DIEs.
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]);
90 progress.Increment();
91 };
92
93 auto extract_fn = [&](size_t cu_idx) {
94 clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
95 progress.Increment();
96 };
97
98 // Share one thread pool across operations to avoid the overhead of
99 // recreating the threads.
100 llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
101
102 // Create a task runner that extracts dies for each DWARF unit in a
103 // separate thread.
104 // First figure out which units didn't have their DIEs already
105 // parsed and remember this. If no DIEs were parsed prior to this index
106 // function call, we are going to want to clear the CU dies after we are
107 // done indexing to make sure we don't pull in all DWARF dies, but we need
108 // to wait until all units have been indexed in case a DIE in one
109 // unit refers to another and the indexes accesses those DIEs.
110 for (size_t i = 0; i < units_to_index.size(); ++i)
111 task_group.async(extract_fn, i);
112 task_group.wait();
113
114 // Now create a task runner that can index each DWARF unit in a
115 // separate thread so we can index quickly.
116 for (size_t i = 0; i < units_to_index.size(); ++i)
117 task_group.async(parser_fn, i);
118 task_group.wait();
119
120 auto finalize_fn = [this, &sets, &progress](NameToDIE(IndexSet::*index)) {
121 NameToDIE &result = m_set.*index;
122 for (auto &set : sets)
123 result.Append(set.*index);
124 result.Finalize();
125 progress.Increment();
126 };
127
128 task_group.async(finalize_fn, &IndexSet::function_basenames);
129 task_group.async(finalize_fn, &IndexSet::function_fullnames);
130 task_group.async(finalize_fn, &IndexSet::function_methods);
131 task_group.async(finalize_fn, &IndexSet::function_selectors);
132 task_group.async(finalize_fn, &IndexSet::objc_class_selectors);
133 task_group.async(finalize_fn, &IndexSet::globals);
134 task_group.async(finalize_fn, &IndexSet::types);
135 task_group.async(finalize_fn, &IndexSet::namespaces);
136 task_group.wait();
137
138 SaveToCache();
139}
140
142 IndexSet &set) {
144
145 if (log) {
147 log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]",
148 unit.GetOffset());
149 }
150
151 const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit);
152
153 // First check if the unit has a DWO ID. If it does then we only want to index
154 // the .dwo file or nothing at all. If we have a compile unit where we can't
155 // locate the .dwo/.dwp file we don't want to index anything from the skeleton
156 // compile unit because it is usally has no children unless
157 // -fsplit-dwarf-inlining was used at compile time. This option will add a
158 // copy of all DW_TAG_subprogram and any contained DW_TAG_inline_subroutine
159 // DIEs so that symbolication will still work in the absence of the .dwo/.dwp
160 // file, but the functions have no return types and all arguments and locals
161 // have been removed. So we don't want to index any of these hacked up
162 // function types. Types can still exist in the skeleton compile unit DWARF
163 // though as some functions have template parameter types and other things
164 // that cause extra copies of types to be included, but we should find these
165 // types in the .dwo file only as methods could have return types removed and
166 // we don't have to index incomplete types from the skeleton compile unit.
167 if (unit.GetDWOId()) {
168 // Index the .dwo or dwp instead of the skeleton unit.
169 if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) {
170 // Type units in a dwp file are indexed separately, so we just need to
171 // process the split unit here. However, if the split unit is in a dwo
172 // file, then we need to process type units here.
173 if (dwo_symbol_file == dwp) {
174 IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set);
175 } else {
176 DWARFDebugInfo &dwo_info = dwo_symbol_file->DebugInfo();
177 for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i)
178 IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set);
179 }
180 return;
181 }
182 // This was a DWARF5 skeleton CU and the .dwo file couldn't be located.
183 if (unit.GetVersion() >= 5 && unit.IsSkeletonUnit())
184 return;
185
186 // Either this is a DWARF 4 + fission CU with the .dwo file
187 // missing, or it's a -gmodules pch or pcm. Try to detect the
188 // latter by checking whether the first DIE is a DW_TAG_module.
189 // If it's a pch/pcm, continue indexing it.
190 if (unit.GetDIE(unit.GetFirstDIEOffset()).GetFirstChild().Tag() !=
191 llvm::dwarf::DW_TAG_module)
192 return;
193 }
194 // We have a normal compile unit which we want to index.
195 IndexUnitImpl(unit, cu_language, set);
196}
197
199 const LanguageType cu_language,
200 IndexSet &set) {
201 for (const DWARFDebugInfoEntry &die : unit.dies()) {
202 const dw_tag_t tag = die.Tag();
203
204 switch (tag) {
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:
217 case DW_TAG_typedef:
218 case DW_TAG_union_type:
219 case DW_TAG_unspecified_type:
220 case DW_TAG_variable:
221 break;
222
223 default:
224 continue;
225 }
226
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;
233
234 DWARFFormValue specification_die_form;
235 DWARFAttributes attributes = die.GetAttributes(&unit);
236 for (size_t i = 0; i < attributes.Size(); ++i) {
237 dw_attr_t attr = attributes.AttributeAtIndex(i);
238 DWARFFormValue form_value;
239 switch (attr) {
240 default:
241 break;
242 case DW_AT_name:
243 if (attributes.ExtractFormValueAtIndex(i, form_value))
244 name = form_value.AsCString();
245 break;
246
247 case DW_AT_declaration:
248 if (attributes.ExtractFormValueAtIndex(i, form_value))
249 is_declaration = form_value.Unsigned() != 0;
250 break;
251
252 case DW_AT_MIPS_linkage_name:
253 case DW_AT_linkage_name:
254 if (attributes.ExtractFormValueAtIndex(i, form_value))
255 mangled_cstr = form_value.AsCString();
256 break;
257
258 case DW_AT_low_pc:
259 case DW_AT_high_pc:
260 case DW_AT_ranges:
261 has_address = true;
262 break;
263
264 case DW_AT_entry_pc:
265 has_address = true;
266 break;
267
268 case DW_AT_location:
269 case DW_AT_const_value:
270 has_location_or_const_value = true;
271 is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable();
272
273 break;
274
275 case DW_AT_specification:
276 if (attributes.ExtractFormValueAtIndex(i, form_value))
277 specification_die_form = form_value;
278 break;
279 }
280 }
281
282 DIERef ref = *DWARFDIE(&unit, &die).GetDIERef();
283 switch (tag) {
284 case DW_TAG_inlined_subroutine:
285 case DW_TAG_subprogram:
286 if (has_address) {
287 if (name) {
288 bool is_objc_method = false;
289 if (cu_language == eLanguageTypeObjC ||
290 cu_language == eLanguageTypeObjC_plus_plus) {
291 std::optional<const ObjCLanguage::MethodName> objc_method =
293 if (objc_method) {
294 is_objc_method = true;
295 ConstString class_name_with_category(
296 objc_method->GetClassNameWithCategory());
297 ConstString objc_selector_name(objc_method->GetSelector());
298 ConstString objc_fullname_no_category_name(
299 objc_method->GetFullNameWithoutCategory().c_str());
300 ConstString class_name_no_category(objc_method->GetClassName());
301 set.function_fullnames.Insert(ConstString(name), ref);
302 if (class_name_with_category)
303 set.objc_class_selectors.Insert(class_name_with_category, ref);
304 if (class_name_no_category &&
305 class_name_no_category != class_name_with_category)
306 set.objc_class_selectors.Insert(class_name_no_category, ref);
307 if (objc_selector_name)
308 set.function_selectors.Insert(objc_selector_name, ref);
309 if (objc_fullname_no_category_name)
310 set.function_fullnames.Insert(objc_fullname_no_category_name,
311 ref);
312 }
313 }
314 // If we have a mangled name, then the DW_AT_name attribute is
315 // usually the method name without the class or any parameters
316 bool is_method = DWARFDIE(&unit, &die).IsMethod();
317
318 if (is_method)
319 set.function_methods.Insert(ConstString(name), ref);
320 else
321 set.function_basenames.Insert(ConstString(name), ref);
322
323 if (!is_method && !mangled_cstr && !is_objc_method)
324 set.function_fullnames.Insert(ConstString(name), ref);
325 }
326 if (mangled_cstr) {
327 // Make sure our mangled name isn't the same string table entry as
328 // our name. If it starts with '_', then it is ok, else compare the
329 // string to make sure it isn't the same and we don't end up with
330 // duplicate entries
331 if (name && name != mangled_cstr &&
332 ((mangled_cstr[0] == '_') ||
333 (::strcmp(name, mangled_cstr) != 0))) {
334 set.function_fullnames.Insert(ConstString(mangled_cstr), ref);
335 }
336 }
337 }
338 break;
339
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:
348 case DW_TAG_typedef:
349 case DW_TAG_union_type:
350 case DW_TAG_unspecified_type:
351 if (name && !is_declaration)
352 set.types.Insert(ConstString(name), ref);
353 if (mangled_cstr && !is_declaration)
354 set.types.Insert(ConstString(mangled_cstr), ref);
355 break;
356
357 case DW_TAG_namespace:
358 case DW_TAG_imported_declaration:
359 if (name)
360 set.namespaces.Insert(ConstString(name), ref);
361 break;
362
363 case DW_TAG_variable:
364 if (name && has_location_or_const_value && is_global_or_static_variable) {
365 set.globals.Insert(ConstString(name), ref);
366 // Be sure to include variables by their mangled and demangled names if
367 // they have any since a variable can have a basename "i", a mangled
368 // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
369 // "(anonymous namespace)::i"...
370
371 // Make sure our mangled name isn't the same string table entry as our
372 // name. If it starts with '_', then it is ok, else compare the string
373 // to make sure it isn't the same and we don't end up with duplicate
374 // entries
375 if (mangled_cstr && name != mangled_cstr &&
376 ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
377 set.globals.Insert(ConstString(mangled_cstr), ref);
378 }
379 }
380 break;
381
382 default:
383 continue;
384 }
385 }
386}
387
389 ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
390 Index();
391 m_set.globals.Find(basename,
392 DIERefCallback(callback, basename.GetStringRef()));
393}
394
396 const RegularExpression &regex,
397 llvm::function_ref<bool(DWARFDIE die)> callback) {
398 Index();
399 m_set.globals.Find(regex, DIERefCallback(callback, regex.GetText()));
400}
401
403 DWARFUnit &unit, llvm::function_ref<bool(DWARFDIE die)> callback) {
404 Index();
406}
407
409 ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
410 Index();
412 class_name, DIERefCallback(callback, class_name.GetStringRef()));
413}
414
416 ConstString class_name, bool must_be_implementation,
417 llvm::function_ref<bool(DWARFDIE die)> callback) {
418 Index();
419 m_set.types.Find(class_name,
420 DIERefCallback(callback, class_name.GetStringRef()));
421}
422
424 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
425 Index();
426 m_set.types.Find(name, DIERefCallback(callback, name.GetStringRef()));
427}
428
430 const DWARFDeclContext &context,
431 llvm::function_ref<bool(DWARFDIE die)> callback) {
432 Index();
433 auto name = context[0].name;
435 DIERefCallback(callback, llvm::StringRef(name)));
436}
437
439 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
440 Index();
441 m_set.namespaces.Find(name, DIERefCallback(callback, name.GetStringRef()));
442}
443
445 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
446 const CompilerDeclContext &parent_decl_ctx,
447 llvm::function_ref<bool(DWARFDIE die)> callback) {
448 Index();
449 ConstString name = lookup_info.GetLookupName();
450 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
451
452 if (name_type_mask & eFunctionNameTypeFull) {
454 name, DIERefCallback(
455 [&](DWARFDIE die) {
456 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
457 die))
458 return true;
459 return callback(die);
460 },
461 name.GetStringRef())))
462 return;
463 }
464 if (name_type_mask & eFunctionNameTypeBase) {
466 name, DIERefCallback(
467 [&](DWARFDIE die) {
468 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
469 die))
470 return true;
471 return callback(die);
472 },
473 name.GetStringRef())))
474 return;
475 }
476
477 if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) {
479 name, DIERefCallback(callback, name.GetStringRef())))
480 return;
481 }
482
483 if (name_type_mask & eFunctionNameTypeSelector &&
484 !parent_decl_ctx.IsValid()) {
486 name, DIERefCallback(callback, name.GetStringRef())))
487 return;
488 }
489}
490
492 const RegularExpression &regex,
493 llvm::function_ref<bool(DWARFDIE die)> callback) {
494 Index();
495
496 if (!m_set.function_basenames.Find(regex,
497 DIERefCallback(callback, regex.GetText())))
498 return;
499 if (!m_set.function_fullnames.Find(regex,
500 DIERefCallback(callback, regex.GetText())))
501 return;
502}
503
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");
519 m_set.globals.Dump(&s);
520 s.Printf("\nTypes:\n");
521 m_set.types.Dump(&s);
522 s.Printf("\nNamespaces:\n");
524}
525
526constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX");
527// Define IDs for the different tables when encoding and decoding the
528// ManualDWARFIndex NameToDIE objects so we can avoid saving any empty maps.
529enum DataID {
539
540};
541
542// Version 2 changes the encoding of DIERef objects used in the DWARF manual
543// index name tables. See DIERef class for details.
544constexpr uint32_t CURRENT_CACHE_VERSION = 2;
545
547 lldb::offset_t *offset_ptr) {
548 StringTableReader strtab;
549 // We now decode the string table for all strings in the data cache file.
550 if (!strtab.Decode(data, offset_ptr))
551 return false;
552
553 llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4);
554 if (identifier != kIdentifierManualDWARFIndex)
555 return false;
556 const uint32_t version = data.GetU32(offset_ptr);
557 if (version != CURRENT_CACHE_VERSION)
558 return false;
559
560 bool done = false;
561 while (!done) {
562 switch (data.GetU8(offset_ptr)) {
563 default:
564 // If we got here, this is not expected, we expect the data IDs to match
565 // one of the values from the DataID enumeration.
566 return false;
568 if (!function_basenames.Decode(data, offset_ptr, strtab))
569 return false;
570 break;
572 if (!function_fullnames.Decode(data, offset_ptr, strtab))
573 return false;
574 break;
576 if (!function_methods.Decode(data, offset_ptr, strtab))
577 return false;
578 break;
580 if (!function_selectors.Decode(data, offset_ptr, strtab))
581 return false;
582 break;
584 if (!objc_class_selectors.Decode(data, offset_ptr, strtab))
585 return false;
586 break;
587 case kDataIDGlobals:
588 if (!globals.Decode(data, offset_ptr, strtab))
589 return false;
590 break;
591 case kDataIDTypes:
592 if (!types.Decode(data, offset_ptr, strtab))
593 return false;
594 break;
596 if (!namespaces.Decode(data, offset_ptr, strtab))
597 return false;
598 break;
599 case kDataIDEnd:
600 // We got to the end of our NameToDIE encodings.
601 done = true;
602 break;
603 }
604 }
605 // Success!
606 return true;
607}
608
610 ConstStringTable strtab;
611
612 // Encoder the DWARF index into a separate encoder first. This allows us
613 // gather all of the strings we willl need in "strtab" as we will need to
614 // write the string table out before the symbol table.
615 DataEncoder index_encoder(encoder.GetByteOrder(),
616 encoder.GetAddressByteSize());
617
619 // Encode the data version.
620 index_encoder.AppendU32(CURRENT_CACHE_VERSION);
621
622 if (!function_basenames.IsEmpty()) {
623 index_encoder.AppendU8(kDataIDFunctionBasenames);
624 function_basenames.Encode(index_encoder, strtab);
625 }
626 if (!function_fullnames.IsEmpty()) {
627 index_encoder.AppendU8(kDataIDFunctionFullnames);
628 function_fullnames.Encode(index_encoder, strtab);
629 }
630 if (!function_methods.IsEmpty()) {
631 index_encoder.AppendU8(kDataIDFunctionMethods);
632 function_methods.Encode(index_encoder, strtab);
633 }
634 if (!function_selectors.IsEmpty()) {
635 index_encoder.AppendU8(kDataIDFunctionSelectors);
636 function_selectors.Encode(index_encoder, strtab);
637 }
638 if (!objc_class_selectors.IsEmpty()) {
640 objc_class_selectors.Encode(index_encoder, strtab);
641 }
642 if (!globals.IsEmpty()) {
643 index_encoder.AppendU8(kDataIDGlobals);
644 globals.Encode(index_encoder, strtab);
645 }
646 if (!types.IsEmpty()) {
647 index_encoder.AppendU8(kDataIDTypes);
648 types.Encode(index_encoder, strtab);
649 }
650 if (!namespaces.IsEmpty()) {
651 index_encoder.AppendU8(kDataIDNamespaces);
652 namespaces.Encode(index_encoder, strtab);
653 }
654 index_encoder.AppendU8(kDataIDEnd);
655
656 // Now that all strings have been gathered, we will emit the string table.
657 strtab.Encode(encoder);
658 // Followed by the symbol table data.
659 encoder.AppendData(index_encoder.GetData());
660}
661
663 lldb::offset_t *offset_ptr,
664 bool &signature_mismatch) {
665 signature_mismatch = false;
666 CacheSignature signature;
667 if (!signature.Decode(data, offset_ptr))
668 return false;
669 if (CacheSignature(m_dwarf->GetObjectFile()) != signature) {
670 signature_mismatch = true;
671 return false;
672 }
673 IndexSet set;
674 if (!set.Decode(data, offset_ptr))
675 return false;
676 m_set = std::move(set);
677 return true;
678}
679
682 if (!signature.Encode(encoder))
683 return false;
684 m_set.Encode(encoder);
685 return true;
686}
687
689 std::string key;
690 llvm::raw_string_ostream strm(key);
691 // DWARF Index can come from different object files for the same module. A
692 // module can have one object file as the main executable and might have
693 // another object file in a separate symbol file, or we might have a .dwo file
694 // that claims its module is the main executable.
695 ObjectFile *objfile = m_dwarf->GetObjectFile();
696 strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-"
697 << llvm::format_hex(objfile->GetCacheHash(), 10);
698 return strm.str();
699}
700
703 if (!cache)
704 return false;
705 ObjectFile *objfile = m_dwarf->GetObjectFile();
706 if (!objfile)
707 return false;
708 std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up =
709 cache->GetCachedData(GetCacheKey());
710 if (!mem_buffer_up)
711 return false;
712 DataExtractor data(mem_buffer_up->getBufferStart(),
713 mem_buffer_up->getBufferSize(),
715 objfile->GetAddressByteSize());
716 bool signature_mismatch = false;
717 lldb::offset_t offset = 0;
718 const bool result = Decode(data, &offset, signature_mismatch);
719 if (signature_mismatch)
721 return result;
722}
723
726 if (!cache)
727 return; // Caching is not enabled.
728 ObjectFile *objfile = m_dwarf->GetObjectFile();
729 if (!objfile)
730 return;
732 // Encode will return false if the object file doesn't have anything to make
733 // a signature from.
734 if (Encode(file)) {
735 if (cache->SetCachedData(GetCacheKey(), file.GetData()))
737 }
738}
constexpr uint32_t CURRENT_CACHE_VERSION
constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX")
@ kDataIDFunctionObjcClassSelectors
@ kDataIDGlobals
@ kDataIDFunctionMethods
@ kDataIDFunctionFullnames
@ kDataIDNamespaces
@ kDataIDFunctionSelectors
@ kDataIDTypes
@ kDataIDFunctionBasenames
@ kDataIDEnd
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:36
#define LLDB_SCOPED_TIMERF(...)
Definition: Timer.h:86
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:552
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.
Definition: ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:191
An binary data encoding class.
Definition: DataEncoder.h:42
lldb::ByteOrder GetByteOrder() const
Definition: DataEncoder.h:258
llvm::ArrayRef< uint8_t > GetData() const
Get a access to the bytes that this references.
Definition: DataEncoder.cpp:40
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.
Definition: DataEncoder.h:261
An data extractor class.
Definition: DataExtractor.h:48
const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
This class enables data to be cached into a directory using the llvm caching code.
Definition: DataFileCache.h:45
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.
Definition: Debugger.cpp:2181
A class that measures elapsed time in an exception safe way.
Definition: Statistics.h:68
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:24
A class that encapsulates name lookup information.
Definition: Module.h:949
lldb::FunctionNameType GetNameTypeMask() const
Definition: Module.h:964
ConstString GetLookupName() const
Definition: Module.h:960
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
Definition: Module.cpp:1255
static DataFileCache * GetIndexCache()
Get the global index file cache.
Definition: Module.cpp:1713
void LogMessage(Log *log, const char *format, Args &&...args)
Definition: Module.h:828
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1106
void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level=lldb::eDescriptionLevelFull)
Definition: Module.cpp:1118
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.
Definition: ObjectFile.h:44
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
Definition: ObjectFile.h:274
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.
Definition: ObjectFile.cpp:758
A Progress indicator helper class.
Definition: Progress.h:56
void Increment(uint64_t amount=1, std::string update={})
Increment the progress and send a notification to the intalled callback.
Definition: Progress.cpp:38
llvm::StringRef GetText() const
Access the regular expression text.
const char * GetData() const
Definition: StreamString.h:43
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void Format(const char *format, Args &&... args)
Definition: Stream.h:309
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:357
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
Many cache files require string tables to store data efficiently.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)
void SetDebugInfoIndexWasLoadedFromCache() override
Definition: SymbolFile.h:543
ObjectFile * GetObjectFile() override
Definition: SymbolFile.h:518
void SetDebugInfoIndexWasSavedToCache() override
Definition: SymbolFile.h:549
Identifies a DWARF debug info entry within a given Module.
Definition: DIERef.h:30
dw_attr_t AttributeAtIndex(uint32_t i) const
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const
std::optional< DIERef > GetDIERef() const
DWARFDebugInfoEntry objects assume that they are living in one big vector and do pointer arithmetic o...
DIERefCallbackImpl DIERefCallback(llvm::function_ref< bool(DWARFDIE die)> callback, llvm::StringRef name={}) const
Definition: DWARFIndex.h:99
SymbolFileDWARFDwo * GetDwoSymbolFile()
Definition: DWARFUnit.cpp:854
bool IsSkeletonUnit() const
Note that this check only works for DWARF5+.
Definition: DWARFUnit.h:233
dw_offset_t GetFirstDIEOffset() const
Definition: DWARFUnit.h:153
DWARFDIE GetDIE(dw_offset_t die_offset)
Definition: DWARFUnit.cpp:645
std::optional< uint64_t > GetDWOId()
Definition: DWARFUnit.cpp:369
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)
Definition: NameToDIE.cpp:87
void FindAllEntriesForUnit(DWARFUnit &unit, llvm::function_ref< bool(DIERef ref)> callback) const
unit must be the skeleton unit if possible, not GetNonSkeletonUnit().
Definition: NameToDIE.cpp:52
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, const StringTableReader &strtab)
Decode a serialized version of this object from data.
Definition: NameToDIE.cpp:97
bool Find(ConstString name, llvm::function_ref< bool(DIERef ref)> callback) const
Definition: NameToDIE.cpp:34
void Insert(ConstString name, const DIERef &die_ref)
Definition: NameToDIE.cpp:30
const std::shared_ptr< SymbolFileDWARFDwo > & GetDwpSymbolFile()
static lldb::LanguageType GetLanguage(DWARFUnit &unit)
static bool DIEInDeclContext(const CompilerDeclContext &parent_decl_ctx, const DWARFDIE &die, bool only_root_namespaces=false)
llvm::dwarf::Tag dw_tag_t
Definition: dwarf.h:26
llvm::dwarf::Attribute dw_attr_t
Definition: dwarf.h:24
lldb::ByteOrder InlHostByteOrder()
Definition: Endian.h:25
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:314
Definition: SBAddress.h:15
@ eDescriptionLevelBrief
uint64_t offset_t
Definition: lldb-types.h:83
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.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)