Coverage Report

Created: 2023-09-12 09:32

/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
115k
  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 AppendSymbolIndexesMatchingRegExAndType(
93
      const RegularExpression &regex, lldb::SymbolType symbol_type,
94
      std::vector<uint32_t> &indexes,
95
      Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
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
      Mangled::NamePreference name_preference =
101
          Mangled::NamePreference::ePreferDemangled);
102
  void FindAllSymbolsWithNameAndType(ConstString name,
103
                                     lldb::SymbolType symbol_type,
104
                                     std::vector<uint32_t> &symbol_indexes);
105
  void FindAllSymbolsWithNameAndType(ConstString name,
106
                                     lldb::SymbolType symbol_type,
107
                                     Debug symbol_debug_type,
108
                                     Visibility symbol_visibility,
109
                                     std::vector<uint32_t> &symbol_indexes);
110
  void FindAllSymbolsMatchingRexExAndType(
111
      const RegularExpression &regex, lldb::SymbolType symbol_type,
112
      Debug symbol_debug_type, Visibility symbol_visibility,
113
      std::vector<uint32_t> &symbol_indexes,
114
      Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
115
  Symbol *FindFirstSymbolWithNameAndType(ConstString name,
116
                                         lldb::SymbolType symbol_type,
117
                                         Debug symbol_debug_type,
118
                                         Visibility symbol_visibility);
119
  Symbol *FindSymbolAtFileAddress(lldb::addr_t file_addr);
120
  Symbol *FindSymbolContainingFileAddress(lldb::addr_t file_addr);
121
  void ForEachSymbolContainingFileAddress(
122
      lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback);
123
  void FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
124
                           SymbolContextList &sc_list);
125
126
  void SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
127
                                bool remove_duplicates) const;
128
129
  static void DumpSymbolHeader(Stream *s);
130
131
  void Finalize();
132
133
  void AppendSymbolNamesToMap(const IndexCollection &indexes,
134
                              bool add_demangled, bool add_mangled,
135
                              NameToIndexMap &name_to_index_map) const;
136
137
135
  ObjectFile *GetObjectFile() const { return m_objfile; }
138
139
  /// Decode a serialized version of this object from data.
140
  ///
141
  /// \param data
142
  ///   The decoder object that references the serialized data.
143
  ///
144
  /// \param offset_ptr
145
  ///   A pointer that contains the offset from which the data will be decoded
146
  ///   from that gets updated as data gets decoded.
147
  ///
148
  /// \param[out] uuid_mismatch
149
  ///   Set to true if a cache file exists but the UUID didn't match, false
150
  ///   otherwise.
151
  ///
152
  /// \return
153
  ///   True if the symbol table is successfully decoded and can be used,
154
  ///   false otherwise.
155
  bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
156
              bool &uuid_mismatch);
157
158
  /// Encode this object into a data encoder object.
159
  ///
160
  /// This allows this object to be serialized to disk. The object file must
161
  /// have a valid Signature in order to be serialized as it is used to make
162
  /// sure the cached information matches when cached data is loaded at a later
163
  /// time. If the object file doesn't have a valid signature false will be
164
  /// returned and it will indicate we should not cache this data.
165
  ///
166
  /// \param encoder
167
  ///   A data encoder object that serialized bytes will be encoded into.
168
  ///
169
  /// \return
170
  ///   True if the symbol table's object file can generate a valid signature
171
  ///   and all data for the symbol table was encoded, false otherwise.
172
  bool Encode(DataEncoder &encoder) const;
173
174
  /// Get the cache key string for this symbol table.
175
  ///
176
  /// The cache key must start with the module's cache key and is followed
177
  /// by information that indicates this key is for caching the symbol table
178
  /// contents and should also include the has of the object file. A module can
179
  /// be represented by an ObjectFile object for the main executable, but can
180
  /// also have a symbol file that is from the same or a different object file.
181
  /// This means we might have two symbol tables cached in the index cache, one
182
  /// for the main executable and one for the symbol file.
183
  ///
184
  /// \return
185
  ///   The unique cache key used to save and retrieve data from the index cache.
186
  std::string GetCacheKey();
187
188
  /// Save the symbol table data out into a cache.
189
  ///
190
  /// The symbol table will only be saved to a cache file if caching is enabled.
191
  ///
192
  /// We cache the contents of the symbol table since symbol tables in LLDB take
193
  /// some time to initialize. This is due to the many sources for data that are
194
  /// used to create a symbol table:
195
  /// - standard symbol table
196
  /// - dynamic symbol table (ELF)
197
  /// - compressed debug info sections
198
  /// - unwind information
199
  /// - function pointers found in runtimes for global constructor/destructors
200
  /// - other sources.
201
  /// All of the above sources are combined and one symbol table results after
202
  /// all sources have been considered.
203
  void SaveToCache();
204
205
  /// Load the symbol table from the index cache.
206
  ///
207
  /// Quickly load the finalized symbol table from the index cache. This saves
208
  /// time when the debugger starts up. The index cache file for the symbol
209
  /// table has the modification time set to the same time as the main module.
210
  /// If the cache file exists and the modification times match, we will load
211
  /// the symbol table from the serlized cache file.
212
  ///
213
  /// \return
214
  ///   True if the symbol table was successfully loaded from the index cache,
215
  ///   false if the symbol table wasn't cached or was out of date.
216
  bool LoadFromCache();
217
218
219
  /// Accessors for the bool that indicates if the debug info index was loaded
220
  /// from, or saved to the module index cache.
221
  ///
222
  /// In statistics it is handy to know if a module's debug info was loaded from
223
  /// or saved to the cache. When the debug info index is loaded from the cache
224
  /// startup times can be faster. When the cache is enabled and the debug info
225
  /// index is saved to the cache, debug sessions can be slower. These accessors
226
  /// can be accessed by the statistics and emitted to help track these costs.
227
  /// \{
228
735
  bool GetWasLoadedFromCache() const {
229
735
    return m_loaded_from_cache;
230
735
  }
231
0
  void SetWasLoadedFromCache() {
232
0
    m_loaded_from_cache = true;
233
0
  }
234
735
  bool GetWasSavedToCache() const {
235
735
    return m_saved_to_cache;
236
735
  }
237
6
  void SetWasSavedToCache() {
238
6
    m_saved_to_cache = true;
239
6
  }
240
  /// \}
241
242
protected:
243
  typedef std::vector<Symbol> collection;
244
  typedef collection::iterator iterator;
245
  typedef collection::const_iterator const_iterator;
246
  class FileRangeToIndexMapCompare {
247
  public:
248
115k
    FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {}
249
5.67M
    bool operator()(const uint32_t a_data, const uint32_t b_data) const {
250
5.67M
      return rank(a_data) > rank(b_data);
251
5.67M
    }
252
253
  private:
254
    // How much preferred is this symbol?
255
11.3M
    int rank(const uint32_t data) const {
256
11.3M
      const Symbol &symbol = *m_symtab.SymbolAtIndex(data);
257
11.3M
      if (symbol.IsExternal())
258
10.1M
        return 3;
259
1.17M
      if (symbol.IsWeak())
260
148
        return 2;
261
1.17M
      if (symbol.IsDebug())
262
3.16k
        return 0;
263
1.16M
      return 1;
264
1.17M
    }
265
    const Symtab &m_symtab;
266
  };
267
  typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0,
268
                          FileRangeToIndexMapCompare>
269
      FileRangeToIndexMap;
270
  void InitNameIndexes();
271
  void InitAddressIndexes();
272
273
  ObjectFile *m_objfile;
274
  collection m_symbols;
275
  FileRangeToIndexMap m_file_addr_to_index;
276
277
  /// Maps function names to symbol indices (grouped by FunctionNameTypes)
278
  std::map<lldb::FunctionNameType, UniqueCStringMap<uint32_t>>
279
      m_name_to_symbol_indices;
280
  mutable std::recursive_mutex
281
      m_mutex; // Provide thread safety for this symbol table
282
  bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1,
283
    m_loaded_from_cache : 1, m_saved_to_cache : 1;
284
285
private:
286
  UniqueCStringMap<uint32_t> &
287
43.1M
  GetNameToSymbolIndexMap(lldb::FunctionNameType type) {
288
43.1M
    auto map = m_name_to_symbol_indices.find(type);
289
43.1M
    assert(map != m_name_to_symbol_indices.end());
290
43.1M
    return map->second;
291
43.1M
  }
292
  bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type,
293
168M
                          Visibility symbol_visibility) const {
294
168M
    switch (symbol_debug_type) {
295
82.4M
    case eDebugNo:
296
82.4M
      if (m_symbols[idx].IsDebug())
297
0
        return false;
298
82.4M
      break;
299
300
85.3M
    case eDebugYes:
301
85.3M
      if (!m_symbols[idx].IsDebug())
302
85.2M
        return false;
303
38.9k
      break;
304
305
259k
    case eDebugAny:
306
259k
      break;
307
168M
    }
308
309
82.7M
    switch (symbol_visibility) {
310
82.7M
    case eVisibilityAny:
311
82.7M
      return true;
312
313
1
    case eVisibilityExtern:
314
1
      return m_symbols[idx].IsExternal();
315
316
0
    case eVisibilityPrivate:
317
0
      return !m_symbols[idx].IsExternal();
318
82.7M
    }
319
0
    return false;
320
82.7M
  }
321
322
  /// A helper function that looks up full function names.
323
  ///
324
  /// We generate unique names for synthetic symbols so that users can look
325
  /// them up by name when needed. But because doing so is uncommon in normal
326
  /// debugger use, we trade off some performance at lookup time for faster
327
  /// symbol table building by detecting these symbols and generating their
328
  /// names lazily, rather than adding them to the normal symbol indexes. This
329
  /// function does the job of first consulting the name indexes, and if that
330
  /// fails it extracts the information it needs from the synthetic name and
331
  /// locates the symbol.
332
  ///
333
  /// @param[in] symbol_name The symbol name to search for.
334
  ///
335
  /// @param[out] indexes The vector if symbol indexes to update with results.
336
  ///
337
  /// @returns The number of indexes added to the index vector. Zero if no
338
  /// matches were found.
339
  uint32_t GetNameIndexes(ConstString symbol_name,
340
                          std::vector<uint32_t> &indexes);
341
342
  void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
343
                                        SymbolContextList &sc_list);
344
345
  void RegisterMangledNameEntry(
346
      uint32_t value, std::set<const char *> &class_contexts,
347
      std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
348
      RichManglingContext &rmc);
349
350
  void RegisterBacklogEntry(const NameToIndexMap::Entry &entry,
351
                            const char *decl_context,
352
                            const std::set<const char *> &class_contexts);
353
354
  Symtab(const Symtab &) = delete;
355
  const Symtab &operator=(const Symtab &) = delete;
356
};
357
358
} // namespace lldb_private
359
360
#endif // LLDB_SYMBOL_SYMTAB_H