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