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