1 | //===-- ManualDWARFIndex.h --------------------------------------*- C++ -*-===// |
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 | |
9 | #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_MANUALDWARFINDEX_H |
10 | #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_MANUALDWARFINDEX_H |
11 | |
12 | #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" |
13 | #include "Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.h" |
14 | #include "Plugins/SymbolFile/DWARF/NameToDIE.h" |
15 | #include "llvm/ADT/DenseSet.h" |
16 | |
17 | namespace lldb_private::plugin { |
18 | namespace dwarf { |
19 | class DWARFDebugInfo; |
20 | class SymbolFileDWARFDwo; |
21 | |
22 | class ManualDWARFIndex : public DWARFIndex { |
23 | public: |
24 | ManualDWARFIndex(Module &module, SymbolFileDWARF &dwarf, |
25 | llvm::DenseSet<dw_offset_t> units_to_avoid = {}, |
26 | llvm::DenseSet<uint64_t> type_sigs_to_avoid = {}) |
27 | : DWARFIndex(module), m_dwarf(&dwarf), |
28 | m_units_to_avoid(std::move(units_to_avoid)), |
29 | m_type_sigs_to_avoid(std::move(type_sigs_to_avoid)) {} |
30 | |
31 | void Preload() override { Index(); } |
32 | |
33 | void |
34 | GetGlobalVariables(ConstString basename, |
35 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
36 | void |
37 | GetGlobalVariables(const RegularExpression ®ex, |
38 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
39 | void |
40 | GetGlobalVariables(DWARFUnit &unit, |
41 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
42 | void GetObjCMethods(ConstString class_name, |
43 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
44 | void GetCompleteObjCClass( |
45 | ConstString class_name, bool must_be_implementation, |
46 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
47 | void GetTypes(ConstString name, |
48 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
49 | void GetTypes(const DWARFDeclContext &context, |
50 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
51 | void GetNamespaces(ConstString name, |
52 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
53 | void GetFunctions(const Module::LookupInfo &lookup_info, |
54 | SymbolFileDWARF &dwarf, |
55 | const CompilerDeclContext &parent_decl_ctx, |
56 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
57 | void GetFunctions(const RegularExpression ®ex, |
58 | llvm::function_ref<bool(DWARFDIE die)> callback) override; |
59 | |
60 | void Dump(Stream &s) override; |
61 | |
62 | private: |
63 | void Index(); |
64 | |
65 | /// Decode a serialized version of this object from data. |
66 | /// |
67 | /// \param data |
68 | /// The decoder object that references the serialized data. |
69 | /// |
70 | /// \param offset_ptr |
71 | /// A pointer that contains the offset from which the data will be decoded |
72 | /// from that gets updated as data gets decoded. |
73 | /// |
74 | /// \param strtab |
75 | /// All strings in cache files are put into string tables for efficiency |
76 | /// and cache file size reduction. Strings are stored as uint32_t string |
77 | /// table offsets in the cache data. |
78 | bool (const DataExtractor &data, lldb::offset_t *offset_ptr, |
79 | bool &signature_mismatch); |
80 | |
81 | /// Encode this object into a data encoder object. |
82 | /// |
83 | /// This allows this object to be serialized to disk. |
84 | /// |
85 | /// \param encoder |
86 | /// A data encoder object that serialized bytes will be encoded into. |
87 | /// |
88 | /// \param strtab |
89 | /// All strings in cache files are put into string tables for efficiency |
90 | /// and cache file size reduction. Strings are stored as uint32_t string |
91 | /// table offsets in the cache data. |
92 | /// |
93 | /// \return |
94 | /// True if the symbol table's object file can generate a valid signature |
95 | /// and all data for the symbol table was encoded, false otherwise. |
96 | bool Encode(DataEncoder &encoder) const; |
97 | |
98 | /// Get the cache key string for this symbol table. |
99 | /// |
100 | /// The cache key must start with the module's cache key and is followed |
101 | /// by information that indicates this key is for caching the symbol table |
102 | /// contents and should also include the has of the object file. A module can |
103 | /// be represented by an ObjectFile object for the main executable, but can |
104 | /// also have a symbol file that is from the same or a different object file. |
105 | /// This means we might have two symbol tables cached in the index cache, one |
106 | /// for the main executable and one for the symbol file. |
107 | /// |
108 | /// \return |
109 | /// The unique cache key used to save and retrieve data from the index |
110 | /// cache. |
111 | std::string GetCacheKey(); |
112 | |
113 | /// Save the symbol table data out into a cache. |
114 | /// |
115 | /// The symbol table will only be saved to a cache file if caching is enabled. |
116 | /// |
117 | /// We cache the contents of the symbol table since symbol tables in LLDB take |
118 | /// some time to initialize. This is due to the many sources for data that are |
119 | /// used to create a symbol table: |
120 | /// - standard symbol table |
121 | /// - dynamic symbol table (ELF) |
122 | /// - compressed debug info sections |
123 | /// - unwind information |
124 | /// - function pointers found in runtimes for global constructor/destructors |
125 | /// - other sources. |
126 | /// All of the above sources are combined and one symbol table results after |
127 | /// all sources have been considered. |
128 | void SaveToCache(); |
129 | |
130 | /// Load the symbol table from the index cache. |
131 | /// |
132 | /// Quickly load the finalized symbol table from the index cache. This saves |
133 | /// time when the debugger starts up. The index cache file for the symbol |
134 | /// table has the modification time set to the same time as the main module. |
135 | /// If the cache file exists and the modification times match, we will load |
136 | /// the symbol table from the serlized cache file. |
137 | /// |
138 | /// \return |
139 | /// True if the symbol table was successfully loaded from the index cache, |
140 | /// false if the symbol table wasn't cached or was out of date. |
141 | bool LoadFromCache(); |
142 | |
143 | void IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, |
144 | IndexSet<NameToDIE> &set); |
145 | |
146 | static void IndexUnitImpl(DWARFUnit &unit, |
147 | const lldb::LanguageType cu_language, |
148 | IndexSet<NameToDIE> &set); |
149 | |
150 | /// Return true if this manual DWARF index is covering only part of the DWARF. |
151 | /// |
152 | /// An instance of this class will be used to index all of the DWARF, but also |
153 | /// when we have .debug_names we will use one to index any compile or type |
154 | /// units that are not covered by the .debug_names table. |
155 | /// |
156 | /// \return |
157 | /// True if this index is a partial index, false otherwise. |
158 | bool IsPartial() const; |
159 | |
160 | /// The DWARF file which we are indexing. |
161 | SymbolFileDWARF *m_dwarf; |
162 | /// Which dwarf units should we skip while building the index. |
163 | llvm::DenseSet<dw_offset_t> m_units_to_avoid; |
164 | llvm::DenseSet<uint64_t> m_type_sigs_to_avoid; |
165 | |
166 | IndexSet<NameToDIE> m_set; |
167 | bool m_indexed = false; |
168 | }; |
169 | } // namespace dwarf |
170 | } // namespace lldb_private::plugin |
171 | |
172 | #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_MANUALDWARFINDEX_H |
173 | |