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