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"
25#include "llvm/Support/ThreadPool.h"
26#include <atomic>
27#include <optional>
28
29using namespace lldb_private;
30using namespace lldb;
31using namespace lldb_private::plugin::dwarf;
32using namespace llvm::dwarf;
33
35 std::call_once(m_indexed_flag, [this]() { IndexImpl(); });
36}
37
40 LLDB_SCOPED_TIMERF("%p", static_cast<void *>(m_dwarf));
41 if (LoadFromCache()) {
42 m_dwarf->SetDebugInfoIndexWasLoadedFromCache();
43 return;
44 }
45
46 DWARFDebugInfo &main_info = m_dwarf->DebugInfo();
47 SymbolFileDWARFDwo *dwp_dwarf = m_dwarf->GetDwpSymbolFile().get();
48 DWARFDebugInfo *dwp_info = dwp_dwarf ? &dwp_dwarf->DebugInfo() : nullptr;
49
50 std::vector<DWARFUnit *> units_to_index;
51 units_to_index.reserve(main_info.GetNumUnits() +
52 (dwp_info ? dwp_info->GetNumUnits() : 0));
53
54 // Process all units in the main file, as well as any type units in the dwp
55 // file. Type units in dwo files are handled when we reach the dwo file in
56 // IndexUnit.
57 for (size_t U = 0; U < main_info.GetNumUnits(); ++U) {
58 DWARFUnit *unit = main_info.GetUnitAtIndex(U);
59 if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0)
60 units_to_index.push_back(unit);
61 }
62 if (dwp_info && dwp_info->ContainsTypeUnits()) {
63 for (size_t U = 0; U < dwp_info->GetNumUnits(); ++U) {
64 if (auto *tu =
65 llvm::dyn_cast<DWARFTypeUnit>(dwp_info->GetUnitAtIndex(U))) {
66 if (!m_type_sigs_to_avoid.contains(tu->GetTypeHash()))
67 units_to_index.push_back(tu);
68 }
69 }
70 }
71
72 if (units_to_index.empty())
73 return;
74
75 StreamString module_desc;
76 m_module.GetDescription(module_desc.AsRawOstream(),
78
79 // Include 2 passes per unit to index for extracting DIEs from the unit and
80 // indexing the unit, and then extra entries for finalizing each index in the
81 // set.
82 const auto indices = IndexSet<NameToDIE>::Indices();
83 const uint64_t total_progress = units_to_index.size() * 2 + indices.size();
84 Progress progress("Manually indexing DWARF", module_desc.GetData(),
85 total_progress, /*debugger=*/nullptr,
87
88 // Share one thread pool across operations to avoid the overhead of
89 // recreating the threads.
90 llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
91 const size_t num_threads = Debugger::GetThreadPool().getMaxConcurrency();
92
93 // Run a function for each compile unit in parallel using as many threads as
94 // are available. This is significantly faster than submiting a new task for
95 // each unit.
96 auto for_each_unit = [&](auto &&fn) {
97 std::atomic<size_t> next_cu_idx = 0;
98 auto wrapper = [&fn, &next_cu_idx, &units_to_index,
99 &progress](size_t worker_id) {
100 size_t cu_idx;
101 while ((cu_idx = next_cu_idx.fetch_add(1, std::memory_order_relaxed)) <
102 units_to_index.size()) {
103 fn(worker_id, cu_idx, units_to_index[cu_idx]);
104 progress.Increment();
105 }
106 };
107
108 for (size_t i = 0; i < num_threads; ++i)
109 task_group.async(wrapper, i);
110
111 task_group.wait();
112 };
113
114 // Extract dies for all DWARFs unit in parallel. Figure out which units
115 // didn't have their DIEs already parsed and remember this. If no DIEs were
116 // parsed prior to this index function call, we are going to want to clear the
117 // CU dies after we are done indexing to make sure we don't pull in all DWARF
118 // dies, but we need to wait until all units have been indexed in case a DIE
119 // in one unit refers to another and the indexes accesses those DIEs.
120 std::vector<std::optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
121 units_to_index.size());
122 for_each_unit([&clear_cu_dies](size_t, size_t idx, DWARFUnit *unit) {
123 clear_cu_dies[idx] = unit->ExtractDIEsScoped();
124 });
125
126 // Now index all DWARF unit in parallel.
127 std::vector<IndexSet<NameToDIE>> sets(num_threads);
128 for_each_unit(
129 [this, dwp_dwarf, &sets](size_t worker_id, size_t, DWARFUnit *unit) {
130 IndexUnit(*unit, dwp_dwarf, sets[worker_id]);
131 });
132
133 // Merge partial indexes into a single index. Process each index in a set in
134 // parallel.
135 for (NameToDIE IndexSet<NameToDIE>::*index : indices) {
136 task_group.async([this, &sets, index, &progress]() {
137 NameToDIE &result = m_set.*index;
138 for (auto &set : sets)
139 result.Append(set.*index);
140 result.Finalize();
141 progress.Increment();
142 });
143 }
144 task_group.wait();
145
146 SaveToCache();
147}
148
150 IndexSet<NameToDIE> &set) {
152
153 if (log) {
154 m_module.LogMessage(
155 log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]",
156 unit.GetOffset());
157 }
158
159 const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit);
160
161 // First check if the unit has a DWO ID. If it does then we only want to index
162 // the .dwo file or nothing at all. If we have a compile unit where we can't
163 // locate the .dwo/.dwp file we don't want to index anything from the skeleton
164 // compile unit because it is usally has no children unless
165 // -fsplit-dwarf-inlining was used at compile time. This option will add a
166 // copy of all DW_TAG_subprogram and any contained DW_TAG_inline_subroutine
167 // DIEs so that symbolication will still work in the absence of the .dwo/.dwp
168 // file, but the functions have no return types and all arguments and locals
169 // have been removed. So we don't want to index any of these hacked up
170 // function types. Types can still exist in the skeleton compile unit DWARF
171 // though as some functions have template parameter types and other things
172 // that cause extra copies of types to be included, but we should find these
173 // types in the .dwo file only as methods could have return types removed and
174 // we don't have to index incomplete types from the skeleton compile unit.
175 if (unit.GetDWOId()) {
176 // Index the .dwo or dwp instead of the skeleton unit.
177 if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) {
178 // Type units in a dwp file are indexed separately, so we just need to
179 // process the split unit here. However, if the split unit is in a dwo
180 // file, then we need to process type units here.
181 if (dwo_symbol_file == dwp) {
182 IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set);
183 } else {
184 DWARFDebugInfo &dwo_info = dwo_symbol_file->DebugInfo();
185 for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i)
186 IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set);
187 }
188 return;
189 }
190 // This was a DWARF5 skeleton CU and the .dwo file couldn't be located.
191 if (unit.GetVersion() >= 5 && unit.IsSkeletonUnit())
192 return;
193
194 // Either this is a DWARF 4 + fission CU with the .dwo file
195 // missing, or it's a -gmodules pch or pcm. Try to detect the
196 // latter by checking whether the first DIE is a DW_TAG_module.
197 // If it's a pch/pcm, continue indexing it.
198 if (unit.GetDIE(unit.GetFirstDIEOffset()).GetFirstChild().Tag() !=
199 llvm::dwarf::DW_TAG_module)
200 return;
201 }
202 // We have a normal compile unit which we want to index.
203 IndexUnitImpl(unit, cu_language, set);
204}
205
207 const LanguageType cu_language,
208 IndexSet<NameToDIE> &set) {
209 for (const DWARFDebugInfoEntry &die : unit.dies()) {
210 const dw_tag_t tag = die.Tag();
211
212 switch (tag) {
213 case DW_TAG_array_type:
214 case DW_TAG_base_type:
215 case DW_TAG_class_type:
216 case DW_TAG_constant:
217 case DW_TAG_enumeration_type:
218 case DW_TAG_inlined_subroutine:
219 case DW_TAG_namespace:
220 case DW_TAG_imported_declaration:
221 case DW_TAG_string_type:
222 case DW_TAG_structure_type:
223 case DW_TAG_subprogram:
224 case DW_TAG_subroutine_type:
225 case DW_TAG_typedef:
226 case DW_TAG_union_type:
227 case DW_TAG_unspecified_type:
228 case DW_TAG_variable:
229 break;
230
231 case DW_TAG_member:
232 // Only in DWARF 4 and earlier `static const` members of a struct, a class
233 // or a union have an entry tag `DW_TAG_member`
234 if (unit.GetVersion() >= 5)
235 continue;
236 break;
237
238 default:
239 continue;
240 }
241
242 const char *name = nullptr;
243 const char *mangled_cstr = nullptr;
244 bool is_declaration = false;
245 bool has_address = false;
246 bool has_location_or_const_value = false;
247 bool is_global_or_static_variable = false;
248
249 DWARFFormValue specification_die_form;
250 DWARFAttributes attributes = die.GetAttributes(&unit);
251 for (size_t i = 0; i < attributes.Size(); ++i) {
252 dw_attr_t attr = attributes.AttributeAtIndex(i);
253 DWARFFormValue form_value;
254 switch (attr) {
255 default:
256 break;
257 case DW_AT_name:
258 if (attributes.ExtractFormValueAtIndex(i, form_value))
259 name = form_value.AsCString();
260 break;
261
262 case DW_AT_declaration:
263 if (attributes.ExtractFormValueAtIndex(i, form_value))
264 is_declaration = form_value.Unsigned() != 0;
265 break;
266
267 case DW_AT_MIPS_linkage_name:
268 case DW_AT_linkage_name:
269 if (attributes.ExtractFormValueAtIndex(i, form_value))
270 mangled_cstr = form_value.AsCString();
271 break;
272
273 case DW_AT_low_pc:
274 case DW_AT_high_pc:
275 case DW_AT_ranges:
276 has_address = true;
277 break;
278
279 case DW_AT_entry_pc:
280 has_address = true;
281 break;
282
283 case DW_AT_location:
284 case DW_AT_const_value:
285 has_location_or_const_value = true;
286 is_global_or_static_variable = die.IsGlobalOrStaticScopeVariable();
287
288 break;
289
290 case DW_AT_specification:
291 if (attributes.ExtractFormValueAtIndex(i, form_value))
292 specification_die_form = form_value;
293 break;
294 }
295 }
296
297 DIERef ref = *DWARFDIE(&unit, &die).GetDIERef();
298 switch (tag) {
299 case DW_TAG_inlined_subroutine:
300 case DW_TAG_subprogram:
301 if (has_address) {
302 if (name) {
303 bool is_objc_method = false;
304 if (cu_language == eLanguageTypeObjC ||
305 cu_language == eLanguageTypeObjC_plus_plus) {
306 std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
308 if (objc_method) {
309 is_objc_method = true;
310 ConstString class_name_with_category(
311 objc_method->GetClassNameWithCategory());
312 ConstString objc_selector_name(objc_method->GetSelector());
313 ConstString objc_fullname_no_category_name(
314 objc_method->GetFullNameWithoutCategory().c_str());
315 ConstString class_name_no_category(objc_method->GetClassName());
316 set.function_fullnames.Insert(ConstString(name), ref);
317 if (class_name_with_category)
318 set.objc_class_selectors.Insert(class_name_with_category, ref);
319 if (class_name_no_category &&
320 class_name_no_category != class_name_with_category)
321 set.objc_class_selectors.Insert(class_name_no_category, ref);
322 if (objc_selector_name)
323 set.function_selectors.Insert(objc_selector_name, ref);
324 if (objc_fullname_no_category_name)
325 set.function_fullnames.Insert(objc_fullname_no_category_name,
326 ref);
327 }
328 }
329 // If we have a mangled name, then the DW_AT_name attribute is
330 // usually the method name without the class or any parameters
331 bool is_method = DWARFDIE(&unit, &die).IsMethod();
332
333 if (is_method)
334 set.function_methods.Insert(ConstString(name), ref);
335 else
336 set.function_basenames.Insert(ConstString(name), ref);
337
338 if (!is_method && !mangled_cstr && !is_objc_method)
339 set.function_fullnames.Insert(ConstString(name), ref);
340 }
341 if (mangled_cstr) {
342 // Make sure our mangled name isn't the same string table entry as
343 // our name. If it starts with '_', then it is ok, else compare the
344 // string to make sure it isn't the same and we don't end up with
345 // duplicate entries
346 if (name && name != mangled_cstr &&
347 ((mangled_cstr[0] == '_') ||
348 (::strcmp(name, mangled_cstr) != 0))) {
349 set.function_fullnames.Insert(ConstString(mangled_cstr), ref);
350 }
351 }
352 }
353 break;
354
355 case DW_TAG_array_type:
356 case DW_TAG_base_type:
357 case DW_TAG_class_type:
358 case DW_TAG_constant:
359 case DW_TAG_enumeration_type:
360 case DW_TAG_string_type:
361 case DW_TAG_structure_type:
362 case DW_TAG_subroutine_type:
363 case DW_TAG_typedef:
364 case DW_TAG_union_type:
365 case DW_TAG_unspecified_type:
366 if (name && !is_declaration)
367 set.types.Insert(ConstString(name), ref);
368 if (mangled_cstr && !is_declaration)
369 set.types.Insert(ConstString(mangled_cstr), ref);
370 break;
371
372 case DW_TAG_namespace:
373 case DW_TAG_imported_declaration:
374 if (name)
375 set.namespaces.Insert(ConstString(name), ref);
376 break;
377
378 case DW_TAG_member: {
379 // In DWARF 4 and earlier `static const` members of a struct, a class or a
380 // union have an entry tag `DW_TAG_member`, and are also tagged as
381 // `DW_AT_declaration`, but otherwise follow the same rules as
382 // `DW_TAG_variable`.
383 bool parent_is_class_type = false;
384 if (auto parent = die.GetParent())
385 parent_is_class_type = DWARFDIE(&unit, parent).IsStructUnionOrClass();
386 if (!parent_is_class_type || !is_declaration)
387 break;
388 [[fallthrough]];
389 }
390 case DW_TAG_variable:
391 if (name && has_location_or_const_value && is_global_or_static_variable) {
392 set.globals.Insert(ConstString(name), ref);
393 // Be sure to include variables by their mangled and demangled names if
394 // they have any since a variable can have a basename "i", a mangled
395 // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
396 // "(anonymous namespace)::i"...
397
398 // Make sure our mangled name isn't the same string table entry as our
399 // name. If it starts with '_', then it is ok, else compare the string
400 // to make sure it isn't the same and we don't end up with duplicate
401 // entries
402 if (mangled_cstr && name != mangled_cstr &&
403 ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
404 set.globals.Insert(ConstString(mangled_cstr), ref);
405 }
406 }
407 break;
408
409 default:
410 continue;
411 }
412 }
413}
414
416 ConstString basename,
417 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
418 Index();
419 m_set.globals.Find(basename,
420 DIERefCallback(callback, basename.GetStringRef()));
421}
422
424 const RegularExpression &regex,
425 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
426 Index();
427 m_set.globals.Find(regex, DIERefCallback(callback, regex.GetText()));
428}
429
431 DWARFUnit &unit,
432 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
433 Index();
434 m_set.globals.FindAllEntriesForUnit(unit, DIERefCallback(callback));
435}
436
438 ConstString class_name,
439 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
440 Index();
441 m_set.objc_class_selectors.Find(
442 class_name, DIERefCallback(callback, class_name.GetStringRef()));
443}
444
446 ConstString class_name, bool must_be_implementation,
447 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
448 Index();
449 m_set.types.Find(class_name,
450 DIERefCallback(callback, class_name.GetStringRef()));
451}
452
454 ConstString name,
455 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
456 Index();
457 m_set.types.Find(name, DIERefCallback(callback, name.GetStringRef()));
458}
459
461 const DWARFDeclContext &context,
462 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
463 Index();
464 auto name = context[0].name;
465 m_set.types.Find(ConstString(name),
466 DIERefCallback(callback, llvm::StringRef(name)));
467}
468
470 ConstString name,
471 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
472 Index();
473 m_set.namespaces.Find(name, DIERefCallback(callback, name.GetStringRef()));
474}
475
477 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
478 const CompilerDeclContext &parent_decl_ctx,
479 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
480 Index();
481 ConstString name = lookup_info.GetLookupName();
482 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
483
484 if (name_type_mask & eFunctionNameTypeFull) {
485 if (!m_set.function_fullnames.Find(
486 name, DIERefCallback(
487 [&](DWARFDIE die) {
488 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
489 die))
491 return callback(die);
492 },
493 name.GetStringRef())))
494 return;
495 }
496 if (name_type_mask & eFunctionNameTypeBase) {
497 if (!m_set.function_basenames.Find(
498 name, DIERefCallback(
499 [&](DWARFDIE die) {
500 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
501 die))
503 return callback(die);
504 },
505 name.GetStringRef())))
506 return;
507 }
508
509 if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) {
510 if (!m_set.function_methods.Find(
511 name, DIERefCallback(callback, name.GetStringRef())))
512 return;
513 }
514
515 if (name_type_mask & eFunctionNameTypeSelector &&
516 !parent_decl_ctx.IsValid()) {
517 if (!m_set.function_selectors.Find(
518 name, DIERefCallback(callback, name.GetStringRef())))
519 return;
520 }
521}
522
524 const RegularExpression &regex,
525 llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
526 Index();
527
528 if (!m_set.function_basenames.Find(regex,
529 DIERefCallback(callback, regex.GetText())))
530 return;
531 if (!m_set.function_fullnames.Find(regex,
532 DIERefCallback(callback, regex.GetText())))
533 return;
534}
535
537 s.Format("Manual DWARF index for ({0}) '{1:F}':",
538 m_module.GetArchitecture().GetArchitectureName(),
539 m_module.GetObjectFile()->GetFileSpec());
540 s.Printf("\nFunction basenames:\n");
541 m_set.function_basenames.Dump(&s);
542 s.Printf("\nFunction fullnames:\n");
543 m_set.function_fullnames.Dump(&s);
544 s.Printf("\nFunction methods:\n");
545 m_set.function_methods.Dump(&s);
546 s.Printf("\nFunction selectors:\n");
547 m_set.function_selectors.Dump(&s);
548 s.Printf("\nObjective-C class selectors:\n");
549 m_set.objc_class_selectors.Dump(&s);
550 s.Printf("\nGlobals and statics:\n");
551 m_set.globals.Dump(&s);
552 s.Printf("\nTypes:\n");
553 m_set.types.Dump(&s);
554 s.Printf("\nNamespaces:\n");
555 m_set.namespaces.Dump(&s);
556}
557
559 lldb::offset_t *offset_ptr,
560 bool &signature_mismatch) {
561 signature_mismatch = false;
562 CacheSignature signature;
563 if (!signature.Decode(data, offset_ptr))
564 return false;
565 if (CacheSignature(m_dwarf->GetObjectFile()) != signature) {
566 signature_mismatch = true;
567 return false;
568 }
569 std::optional<IndexSet<NameToDIE>> set = DecodeIndexSet(data, offset_ptr);
570 if (!set)
571 return false;
572 m_set = std::move(*set);
573 return true;
574}
575
577 CacheSignature signature(m_dwarf->GetObjectFile());
578 if (!signature.Encode(encoder))
579 return false;
580 EncodeIndexSet(m_set, encoder);
581 return true;
582}
583
585 // If we have units or type units to skip, then this index is partial.
586 return !m_units_to_avoid.empty() || !m_type_sigs_to_avoid.empty();
587}
588
590 std::string key;
591 llvm::raw_string_ostream strm(key);
592 // DWARF Index can come from different object files for the same module. A
593 // module can have one object file as the main executable and might have
594 // another object file in a separate symbol file, or we might have a .dwo file
595 // that claims its module is the main executable.
596
597 // This class can be used to index all of the DWARF, or part of the DWARF
598 // when there is a .debug_names index where some compile or type units were
599 // built without .debug_names. So we need to know when we have a full manual
600 // DWARF index or a partial manual DWARF index and save them to different
601 // cache files. Before this fix we might end up debugging a binary with
602 // .debug_names where some of the compile or type units weren't indexed, and
603 // find an issue with the .debug_names tables (bugs or being incomplete), and
604 // then we disable loading the .debug_names by setting a setting in LLDB by
605 // running "settings set plugin.symbol-file.dwarf.ignore-file-indexes 0" in
606 // another LLDB instance. The problem arose when there was an index cache from
607 // a previous run where .debug_names was enabled and it had saved a cache file
608 // that only covered the missing compile and type units from the .debug_names,
609 // and with the setting that disables the loading of the cache files we would
610 // load partial cache index cache. So we need to pick a unique cache suffix
611 // name that indicates if the cache is partial or full to avoid this problem.
612 llvm::StringRef dwarf_index_suffix(IsPartial() ? "partial-" : "full-");
613 ObjectFile *objfile = m_dwarf->GetObjectFile();
614 strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-"
615 << dwarf_index_suffix << llvm::format_hex(objfile->GetCacheHash(), 10);
616 return key;
617}
618
621 if (!cache)
622 return false;
623 ObjectFile *objfile = m_dwarf->GetObjectFile();
624 if (!objfile)
625 return false;
626 std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up =
627 cache->GetCachedData(GetCacheKey());
628 if (!mem_buffer_up)
629 return false;
630 DataExtractor data(mem_buffer_up->getBufferStart(),
631 mem_buffer_up->getBufferSize(),
633 objfile->GetAddressByteSize());
634 bool signature_mismatch = false;
635 lldb::offset_t offset = 0;
636 const bool result = Decode(data, &offset, signature_mismatch);
637 if (signature_mismatch)
639 return result;
640}
641
644 if (!cache)
645 return; // Caching is not enabled.
646 ObjectFile *objfile = m_dwarf->GetObjectFile();
647 if (!objfile)
648 return;
650 // Encode will return false if the object file doesn't have anything to make
651 // a signature from.
652 if (Encode(file)) {
653 if (cache->SetCachedData(GetCacheKey(), file.GetData()))
654 m_dwarf->SetDebugInfoIndexWasSavedToCache();
655 }
656}
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
#define LLDB_SCOPED_TIMERF(...)
Definition Timer.h:86
Represents a generic declaration context in a program.
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
An binary data encoding class.
Definition DataEncoder.h:42
llvm::ArrayRef< uint8_t > GetData() const
Get a access to the bytes that this references.
An data extractor class.
This class enables data to be cached into a directory using the llvm caching code.
std::unique_ptr< llvm::MemoryBuffer > GetCachedData(llvm::StringRef key)
Get cached data from the cache directory for the specified key.
bool SetCachedData(llvm::StringRef key, llvm::ArrayRef< uint8_t > data)
Set cached data for the specified key.
Status RemoveCacheFile(llvm::StringRef key)
Remove the cache file associated with the key.
static llvm::ThreadPoolInterface & GetThreadPool()
Shared thread pool. Use only with ThreadPoolTaskGroup.
A class that measures elapsed time in an exception safe way.
Definition Statistics.h:76
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
A class that encapsulates name lookup information.
Definition Module.h:916
lldb::FunctionNameType GetNameTypeMask() const
Definition Module.h:931
ConstString GetLookupName() const
Definition Module.h:927
static DataFileCache * GetIndexCache()
Get the global index file cache.
Definition Module.cpp:1639
static std::optional< const ObjCMethodName > Create(llvm::StringRef name, bool strict)
The static factory method for creating a ObjCMethodName.
A plug-in interface definition class for object file parsers.
Definition ObjectFile.h:45
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.
Definition Progress.h:60
void Increment(uint64_t amount=1, std::optional< std::string > updated_detail={})
Increment the progress and send a notification to the installed callback.
Definition Progress.cpp:62
static constexpr std::chrono::milliseconds kDefaultHighFrequencyReportTime
The default report time for high frequency progress reports.
Definition Progress.h:119
llvm::StringRef GetText() const
Access the regular expression text.
const char * GetData() const
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:344
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:392
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
Identifies a DWARF debug info entry within a given Module.
Definition DIERef.h:31
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< IterationAction(DWARFDIE die)> callback, llvm::StringRef name={}) const
Definition DWARFIndex.h:128
bool IsSkeletonUnit() const
Note that this check only works for DWARF5+.
Definition DWARFUnit.h:227
dw_offset_t GetFirstDIEOffset() const
Definition DWARFUnit.h:113
DWARFDIE GetDIE(dw_offset_t die_offset)
SymbolFileDWARFDwo * GetDwoSymbolFile(bool load_all_debug_info=true)
uint16_t GetVersion() const override
Definition DWARFUnit.h:121
std::optional< uint64_t > GetDWOId()
Get the DWO ID from the DWARFUnitHeader for DWARF5, or from the unit DIE's DW_AT_dwo_id or DW_AT_GNU_...
void IndexImpl()
Call ManualDWARFIndex::Index() instead.
SymbolFileDWARF * m_dwarf
The DWARF file which we are indexing.
void IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, IndexSet< NameToDIE > &set)
bool IsPartial() const
Return true if this manual DWARF index is covering only part of the DWARF.
bool Encode(DataEncoder &encoder) const
Encode this object into a data encoder object.
void GetGlobalVariables(ConstString basename, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
Finds global variables with the given base name.
void Index()
Reads the DWARF debug info to build the index once.
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
llvm::DenseSet< dw_offset_t > m_units_to_avoid
Which dwarf units should we skip while building the index.
std::string GetCacheKey()
Get the cache key string for this symbol table.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, bool &signature_mismatch)
Decode a serialized version of this object from data.
bool LoadFromCache()
Load the symbol table from the index cache.
void GetObjCMethods(ConstString class_name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
static void IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language, IndexSet< NameToDIE > &set)
void SaveToCache()
Save the symbol table data out into a cache.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void GetTypes(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void GetNamespaces(ConstString name, llvm::function_ref< IterationAction(DWARFDIE die)> callback) override
void Append(const NameToDIE &other)
Definition NameToDIE.cpp:91
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:19
llvm::dwarf::Attribute dw_attr_t
Definition dwarf.h:17
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
std::optional< IndexSet< NameToDIE > > DecodeIndexSet(const DataExtractor &data, lldb::offset_t *offset_ptr)
void EncodeIndexSet(const IndexSet< NameToDIE > &set, DataEncoder &encoder)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
IterationAction
Useful for callbacks whose return type indicates whether to continue iteration or short-circuit.
@ eDescriptionLevelBrief
uint64_t offset_t
Definition lldb-types.h:85
LanguageType
Programming language type.
@ eLanguageTypeObjC_plus_plus
Objective-C++.
@ eLanguageTypeObjC
Objective-C.
A signature for a given file on disk.
bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr)
Decode a serialized version of this object from data.
bool Encode(DataEncoder &encoder) const
Encode this object into a data encoder object.
static std::array< T(IndexSet::*), 8 > Indices()