Coverage Report

Created: 2022-01-15 10:30

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Symbol/Symtab.h
Line
Count
Source (jump to first uncovered line)
1
//===-- Symtab.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_SYMBOL_SYMTAB_H
10
#define LLDB_SYMBOL_SYMTAB_H
11
12
#include "lldb/Core/UniqueCStringMap.h"
13
#include "lldb/Symbol/Symbol.h"
14
#include "lldb/Utility/RangeMap.h"
15
#include "lldb/lldb-private.h"
16
#include <map>
17
#include <mutex>
18
#include <vector>
19
20
namespace lldb_private {
21
22
class Symtab {
23
public:
24
  typedef std::vector<uint32_t> IndexCollection;
25
  typedef UniqueCStringMap<uint32_t> NameToIndexMap;
26
27
  enum Debug {
28
    eDebugNo,  // Not a debug symbol
29
    eDebugYes, // A debug symbol
30
    eDebugAny
31
  };
32
33
  enum Visibility { eVisibilityAny, eVisibilityExtern, eVisibilityPrivate };
34
35
  Symtab(ObjectFile *objfile);
36
  ~Symtab();
37
38
  void PreloadSymbols();
39
  void Reserve(size_t count);
40
  Symbol *Resize(size_t count);
41
  uint32_t AddSymbol(const Symbol &symbol);
42
  size_t GetNumSymbols() const;
43
  void SectionFileAddressesChanged();
44
  void
45
  Dump(Stream *s, Target *target, SortOrder sort_type,
46
       Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
47
  void Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
48
            Mangled::NamePreference name_preference =
49
                Mangled::ePreferDemangled) const;
50
  uint32_t GetIndexForSymbol(const Symbol *symbol) const;
51
140k
  std::recursive_mutex &GetMutex() { return m_mutex; }
52
  Symbol *FindSymbolByID(lldb::user_id_t uid) const;
53
  Symbol *SymbolAtIndex(size_t idx);
54
  const Symbol *SymbolAtIndex(size_t idx) const;
55
  Symbol *FindSymbolWithType(lldb::SymbolType symbol_type,
56
                             Debug symbol_debug_type,
57
                             Visibility symbol_visibility, uint32_t &start_idx);
58
  /// Get the parent symbol for the given symbol.
59
  ///
60
  /// Many symbols in symbol tables are scoped by other symbols that
61
  /// contain one or more symbol. This function will look for such a
62
  /// containing symbol and return it if there is one.
63
  const Symbol *GetParent(Symbol *symbol) const;
64
  uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
65
                                       std::vector<uint32_t> &indexes,
66
                                       uint32_t start_idx = 0,
67
                                       uint32_t end_index = UINT32_MAX) const;
68
  uint32_t AppendSymbolIndexesWithTypeAndFlagsValue(
69
      lldb::SymbolType symbol_type, uint32_t flags_value,
70
      std::vector<uint32_t> &indexes, uint32_t start_idx = 0,
71
      uint32_t end_index = UINT32_MAX) const;
72
  uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
73
                                       Debug symbol_debug_type,
74
                                       Visibility symbol_visibility,
75
                                       std::vector<uint32_t> &matches,
76
                                       uint32_t start_idx = 0,
77
                                       uint32_t end_index = UINT32_MAX) const;
78
  uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
79
                                       std::vector<uint32_t> &matches);
80
  uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
81
                                       Debug symbol_debug_type,
82
                                       Visibility symbol_visibility,
83
                                       std::vector<uint32_t> &matches);
84
  uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
85
                                              lldb::SymbolType symbol_type,
86
                                              std::vector<uint32_t> &matches);
87
  uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
88
                                              lldb::SymbolType symbol_type,
89
                                              Debug symbol_debug_type,
90
                                              Visibility symbol_visibility,
91
                                              std::vector<uint32_t> &matches);
92
  uint32_t
93
  AppendSymbolIndexesMatchingRegExAndType(const RegularExpression &regex,
94
                                          lldb::SymbolType symbol_type,
95
                                          std::vector<uint32_t> &indexes);
96
  uint32_t AppendSymbolIndexesMatchingRegExAndType(
97
      const RegularExpression &regex, lldb::SymbolType symbol_type,
98
      Debug symbol_debug_type, Visibility symbol_visibility,
99
      std::vector<uint32_t> &indexes);
100
  void FindAllSymbolsWithNameAndType(ConstString name,
101
                                     lldb::SymbolType symbol_type,
102
                                     std::vector<uint32_t> &symbol_indexes);
103
  void FindAllSymbolsWithNameAndType(ConstString name,
104
                                     lldb::SymbolType symbol_type,
105
                                     Debug symbol_debug_type,
106
                                     Visibility symbol_visibility,
107
                                     std::vector<uint32_t> &symbol_indexes);
108
  void FindAllSymbolsMatchingRexExAndType(
109
      const RegularExpression &regex, lldb::SymbolType symbol_type,
110
      Debug symbol_debug_type, Visibility symbol_visibility,
111
      std::vector<uint32_t> &symbol_indexes);
112
  Symbol *FindFirstSymbolWithNameAndType(ConstString name,
113
                                         lldb::SymbolType symbol_type,
114
                                         Debug symbol_debug_type,
115
                                         Visibility symbol_visibility);
116
  Symbol *FindSymbolAtFileAddress(lldb::addr_t file_addr);
117
  Symbol *FindSymbolContainingFileAddress(lldb::addr_t file_addr);
118
  void ForEachSymbolContainingFileAddress(
119
      lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback);
120
  void FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
121
                           SymbolContextList &sc_list);
122
123
  void SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
124
                                bool remove_duplicates) const;
125
126
  static void DumpSymbolHeader(Stream *s);
127
128
  void Finalize();
129
130
  void AppendSymbolNamesToMap(const IndexCollection &indexes,
131
                              bool add_demangled, bool add_mangled,
132
                              NameToIndexMap &name_to_index_map) const;
133
134
193
  ObjectFile *GetObjectFile() const { return m_objfile; }
135
136
  /// Decode a serialized version of this object from data.
137
  ///
138
  /// \param data
139
  ///   The decoder object that references the serialized data.
140
  ///
141
  /// \param offset_ptr
142
  ///   A pointer that contains the offset from which the data will be decoded
143
  ///   from that gets updated as data gets decoded.
144
  ///
145
  /// \param[out] uuid_mismatch
146
  ///   Set to true if a cache file exists but the UUID didn't match, false
147
  ///   otherwise.
148
  ///
149
  /// \return
150
  ///   True if the symbol table is successfully decoded and can be used,
151
  ///   false otherwise.
152
  bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
153
              bool &uuid_mismatch);
154
155
  /// Encode this object into a data encoder object.
156
  ///
157
  /// This allows this object to be serialized to disk. The object file must
158
  /// have a valid Signature in order to be serialized as it is used to make
159
  /// sure the cached information matches when cached data is loaded at a later
160
  /// time. If the object file doesn't have a valid signature false will be
161
  /// returned and it will indicate we should not cache this data.
162
  ///
163
  /// \param encoder
164
  ///   A data encoder object that serialized bytes will be encoded into.
165
  ///
166
  /// \return
167
  ///   True if the symbol table's object file can generate a valid signature
168
  ///   and all data for the symbol table was encoded, false otherwise.
169
  bool Encode(DataEncoder &encoder) const;
170
171
  /// Get the cache key string for this symbol table.
172
  ///
173
  /// The cache key must start with the module's cache key and is followed
174
  /// by information that indicates this key is for caching the symbol table
175
  /// contents and should also include the has of the object file. A module can
176
  /// be represented by an ObjectFile object for the main executable, but can
177
  /// also have a symbol file that is from the same or a different object file.
178
  /// This means we might have two symbol tables cached in the index cache, one
179
  /// for the main executable and one for the symbol file.
180
  ///
181
  /// \return
182
  ///   The unique cache key used to save and retrieve data from the index cache.
183
  std::string GetCacheKey();
184
185
  /// Save the symbol table data out into a cache.
186
  ///
187
  /// The symbol table will only be saved to a cache file if caching is enabled.
188
  ///
189
  /// We cache the contents of the symbol table since symbol tables in LLDB take
190
  /// some time to initialize. This is due to the many sources for data that are
191
  /// used to create a symbol table:
192
  /// - standard symbol table
193
  /// - dynamic symbol table (ELF)
194
  /// - compressed debug info sections
195
  /// - unwind information
196
  /// - function pointers found in runtimes for global constructor/destructors
197
  /// - other sources.
198
  /// All of the above sources are combined and one symbol table results after
199
  /// all sources have been considered.
200
  void SaveToCache();
201
202
  /// Load the symbol table from the index cache.
203
  ///
204
  /// Quickly load the finalized symbol table from the index cache. This saves
205
  /// time when the debugger starts up. The index cache file for the symbol
206
  /// table has the modification time set to the same time as the main module.
207
  /// If the cache file exists and the modification times match, we will load
208
  /// the symbol table from the serlized cache file.
209
  ///
210
  /// \return
211
  ///   True if the symbol table was successfully loaded from the index cache,
212
  ///   false if the symbol table wasn't cached or was out of date.
213
  bool LoadFromCache();
214
215
216
  /// Accessors for the bool that indicates if the debug info index was loaded
217
  /// from, or saved to the module index cache.
218
  ///
219
  /// In statistics it is handy to know if a module's debug info was loaded from
220
  /// or saved to the cache. When the debug info index is loaded from the cache
221
  /// startup times can be faster. When the cache is enabled and the debug info
222
  /// index is saved to the cache, debug sessions can be slower. These accessors
223
  /// can be accessed by the statistics and emitted to help track these costs.
224
  /// \{
225
456
  bool GetWasLoadedFromCache() const {
226
456
    return m_loaded_from_cache;
227
456
  }
228
0
  void SetWasLoadedFromCache() {
229
0
    m_loaded_from_cache = true;
230
0
  }
231
456
  bool GetWasSavedToCache() const {
232
456
    return m_saved_to_cache;
233
456
  }
234
9
  void SetWasSavedToCache() {
235
9
    m_saved_to_cache = true;
236
9
  }
237
  /// \}
238
239
protected:
240
  typedef std::vector<Symbol> collection;
241
  typedef collection::iterator iterator;
242
  typedef collection::const_iterator const_iterator;
243
  class FileRangeToIndexMapCompare {
244
  public:
245
140k
    FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {}
246
7.56M
    bool operator()(const uint32_t a_data, const uint32_t b_data) const {
247
7.56M
      return rank(a_data) > rank(b_data);
248
7.56M
    }
249
250
  private:
251
    // How much preferred is this symbol?
252
15.1M
    int rank(const uint32_t data) const {
253
15.1M
      const Symbol &symbol = *m_symtab.SymbolAtIndex(data);
254
15.1M
      if (symbol.IsExternal())
255
13.6M
        return 3;
256
1.47M
      if (symbol.IsWeak())
257
128
        return 2;
258
1.47M
      if (symbol.IsDebug())
259
4.70k
        return 0;
260
1.47M
      return 1;
261
1.47M
    }
262
    const Symtab &m_symtab;
263
  };
264
  typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0,
265
                          FileRangeToIndexMapCompare>
266
      FileRangeToIndexMap;
267
  void InitNameIndexes();
268
  void InitAddressIndexes();
269
270
  ObjectFile *m_objfile;
271
  collection m_symbols;
272
  FileRangeToIndexMap m_file_addr_to_index;
273
274
  /// Maps function names to symbol indices (grouped by FunctionNameTypes)
275
  std::map<lldb::FunctionNameType, UniqueCStringMap<uint32_t>>
276
      m_name_to_symbol_indices;
277
  mutable std::recursive_mutex
278
      m_mutex; // Provide thread safety for this symbol table
279
  bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1,
280
    m_loaded_from_cache : 1, m_saved_to_cache : 1;
281
282
private:
283
  UniqueCStringMap<uint32_t> &
284
44.2M
  GetNameToSymbolIndexMap(lldb::FunctionNameType type) {
285
44.2M
    auto map = m_name_to_symbol_indices.find(type);
286
44.2M
    assert(map != m_name_to_symbol_indices.end());
287
0
    return map->second;
288
44.2M
  }
289
  bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type,
290
214M
                          Visibility symbol_visibility) const {
291
214M
    switch (symbol_debug_type) {
292
100M
    case eDebugNo:
293
100M
      if (m_symbols[idx].IsDebug())
294
0
        return false;
295
100M
      break;
296
297
112M
    case eDebugYes:
298
112M
      if (!m_symbols[idx].IsDebug())
299
112M
        return false;
300
46.5k
      break;
301
302
1.00M
    case eDebugAny:
303
1.00M
      break;
304
214M
    }
305
306
101M
    switch (symbol_visibility) {
307
101M
    case eVisibilityAny:
308
101M
      return true;
309
310
2
    case eVisibilityExtern:
311
2
      return m_symbols[idx].IsExternal();
312
313
0
    case eVisibilityPrivate:
314
0
      return !m_symbols[idx].IsExternal();
315
101M
    }
316
0
    return false;
317
101M
  }
318
319
  /// A helper function that looks up full function names.
320
  ///
321
  /// We generate unique names for synthetic symbols so that users can look
322
  /// them up by name when needed. But because doing so is uncommon in normal
323
  /// debugger use, we trade off some performance at lookup time for faster
324
  /// symbol table building by detecting these symbols and generating their
325
  /// names lazily, rather than adding them to the normal symbol indexes. This
326
  /// function does the job of first consulting the name indexes, and if that
327
  /// fails it extracts the information it needs from the synthetic name and
328
  /// locates the symbol.
329
  ///
330
  /// @param[in] symbol_name The symbol name to search for.
331
  ///
332
  /// @param[out] indexes The vector if symbol indexes to update with results.
333
  ///
334
  /// @returns The number of indexes added to the index vector. Zero if no
335
  /// matches were found.
336
  uint32_t GetNameIndexes(ConstString symbol_name,
337
                          std::vector<uint32_t> &indexes);
338
339
  void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
340
                                        SymbolContextList &sc_list);
341
342
  void RegisterMangledNameEntry(
343
      uint32_t value, std::set<const char *> &class_contexts,
344
      std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
345
      RichManglingContext &rmc);
346
347
  void RegisterBacklogEntry(const NameToIndexMap::Entry &entry,
348
                            const char *decl_context,
349
                            const std::set<const char *> &class_contexts);
350
351
  Symtab(const Symtab &) = delete;
352
  const Symtab &operator=(const Symtab &) = delete;
353
};
354
355
} // namespace lldb_private
356
357
#endif // LLDB_SYMBOL_SYMTAB_H