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 <mutex>
17#include <vector>
18
19namespace lldb_private {
20
21class Symtab {
22public:
23  typedef std::vector<uint32_t> IndexCollection;
24  typedef UniqueCStringMap<uint32_t> NameToIndexMap;
25
26  enum Debug {
27    eDebugNo,  // Not a debug symbol
28    eDebugYes, // A debug symbol
29    eDebugAny
30  };
31
32  enum Visibility { eVisibilityAny, eVisibilityExtern, eVisibilityPrivate };
33
34  Symtab(ObjectFile *objfile);
35  ~Symtab();
36
37  void PreloadSymbols();
38  void Reserve(size_t count);
39  Symbol *Resize(size_t count);
40  uint32_t AddSymbol(const Symbol &symbol);
41  size_t GetNumSymbols() const;
42  void SectionFileAddressesChanged();
43  void
44  Dump(Stream *s, Target *target, SortOrder sort_type,
45       Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
46  void Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
47            Mangled::NamePreference name_preference =
48                Mangled::ePreferDemangled) const;
49  uint32_t GetIndexForSymbol(const Symbol *symbol) const;
50  std::recursive_mutex &GetMutex() { return m_mutex; }
51  Symbol *FindSymbolByID(lldb::user_id_t uid) const;
52  Symbol *SymbolAtIndex(size_t idx);
53  const Symbol *SymbolAtIndex(size_t idx) const;
54  Symbol *FindSymbolWithType(lldb::SymbolType symbol_type,
55                             Debug symbol_debug_type,
56                             Visibility symbol_visibility, uint32_t &start_idx);
57  /// Get the parent symbol for the given symbol.
58  ///
59  /// Many symbols in symbol tables are scoped by other symbols that
60  /// contain one or more symbol. This function will look for such a
61  /// containing symbol and return it if there is one.
62  const Symbol *GetParent(Symbol *symbol) const;
63  uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
64                                       std::vector<uint32_t> &indexes,
65                                       uint32_t start_idx = 0,
66                                       uint32_t end_index = UINT32_MAX) const;
67  uint32_t AppendSymbolIndexesWithTypeAndFlagsValue(
68      lldb::SymbolType symbol_type, uint32_t flags_value,
69      std::vector<uint32_t> &indexes, uint32_t start_idx = 0,
70      uint32_t end_index = UINT32_MAX) const;
71  uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
72                                       Debug symbol_debug_type,
73                                       Visibility symbol_visibility,
74                                       std::vector<uint32_t> &matches,
75                                       uint32_t start_idx = 0,
76                                       uint32_t end_index = UINT32_MAX) const;
77  uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
78                                       std::vector<uint32_t> &matches);
79  uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
80                                       Debug symbol_debug_type,
81                                       Visibility symbol_visibility,
82                                       std::vector<uint32_t> &matches);
83  uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
84                                              lldb::SymbolType symbol_type,
85                                              std::vector<uint32_t> &matches);
86  uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
87                                              lldb::SymbolType symbol_type,
88                                              Debug symbol_debug_type,
89                                              Visibility symbol_visibility,
90                                              std::vector<uint32_t> &matches);
91  uint32_t
92  AppendSymbolIndexesMatchingRegExAndType(const RegularExpression &regex,
93                                          lldb::SymbolType symbol_type,
94                                          std::vector<uint32_t> &indexes);
95  uint32_t AppendSymbolIndexesMatchingRegExAndType(
96      const RegularExpression &regex, lldb::SymbolType symbol_type,
97      Debug symbol_debug_type, Visibility symbol_visibility,
98      std::vector<uint32_t> &indexes);
99  void FindAllSymbolsWithNameAndType(ConstString name,
100                                     lldb::SymbolType symbol_type,
101                                     std::vector<uint32_t> &symbol_indexes);
102  void FindAllSymbolsWithNameAndType(ConstString name,
103                                     lldb::SymbolType symbol_type,
104                                     Debug symbol_debug_type,
105                                     Visibility symbol_visibility,
106                                     std::vector<uint32_t> &symbol_indexes);
107  void FindAllSymbolsMatchingRexExAndType(
108      const RegularExpression &regex, lldb::SymbolType symbol_type,
109      Debug symbol_debug_type, Visibility symbol_visibility,
110      std::vector<uint32_t> &symbol_indexes);
111  Symbol *FindFirstSymbolWithNameAndType(ConstString name,
112                                         lldb::SymbolType symbol_type,
113                                         Debug symbol_debug_type,
114                                         Visibility symbol_visibility);
115  Symbol *FindSymbolAtFileAddress(lldb::addr_t file_addr);
116  Symbol *FindSymbolContainingFileAddress(lldb::addr_t file_addr);
117  void ForEachSymbolContainingFileAddress(
118      lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback);
119  void FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
120                           SymbolContextList &sc_list);
121  void CalculateSymbolSizes();
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    // Shrink to fit the symbols so we don't waste memory
130    if (m_symbols.capacity() > m_symbols.size()) {
131      collection new_symbols(m_symbols.begin(), m_symbols.end());
132      m_symbols.swap(new_symbols);
133    }
134  }
135
136  void AppendSymbolNamesToMap(const IndexCollection &indexes,
137                              bool add_demangled, bool add_mangled,
138                              NameToIndexMap &name_to_index_map) const;
139
140  ObjectFile *GetObjectFile() { return m_objfile; }
141
142protected:
143  typedef std::vector<Symbol> collection;
144  typedef collection::iterator iterator;
145  typedef collection::const_iterator const_iterator;
146  class FileRangeToIndexMapCompare {
147  public:
148    FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {}
149    bool operator()(const uint32_t a_data, const uint32_t b_data) const {
150      return rank(a_data) > rank(b_data);
151    }
152
153  private:
154    // How much preferred is this symbol?
155    int rank(const uint32_t data) const {
156      const Symbol &symbol = *m_symtab.SymbolAtIndex(data);
157      if (symbol.IsExternal())
158        return 3;
159      if (symbol.IsWeak())
160        return 2;
161      if (symbol.IsDebug())
162        return 0;
163      return 1;
164    }
165    const Symtab &m_symtab;
166  };
167  typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0,
168                          FileRangeToIndexMapCompare>
169      FileRangeToIndexMap;
170  void InitNameIndexes();
171  void InitAddressIndexes();
172
173  ObjectFile *m_objfile;
174  collection m_symbols;
175  FileRangeToIndexMap m_file_addr_to_index;
176  UniqueCStringMap<uint32_t> m_name_to_index;
177  UniqueCStringMap<uint32_t> m_basename_to_index;
178  UniqueCStringMap<uint32_t> m_method_to_index;
179  UniqueCStringMap<uint32_t> m_selector_to_index;
180  mutable std::recursive_mutex
181      m_mutex; // Provide thread safety for this symbol table
182  bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1;
183
184private:
185  bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type,
186                          Visibility symbol_visibility) const {
187    switch (symbol_debug_type) {
188    case eDebugNo:
189      if (m_symbols[idx].IsDebug())
190        return false;
191      break;
192
193    case eDebugYes:
194      if (!m_symbols[idx].IsDebug())
195        return false;
196      break;
197
198    case eDebugAny:
199      break;
200    }
201
202    switch (symbol_visibility) {
203    case eVisibilityAny:
204      return true;
205
206    case eVisibilityExtern:
207      return m_symbols[idx].IsExternal();
208
209    case eVisibilityPrivate:
210      return !m_symbols[idx].IsExternal();
211    }
212    return false;
213  }
214
215  void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
216                                        SymbolContextList &sc_list);
217
218  void RegisterMangledNameEntry(
219      uint32_t value, std::set<const char *> &class_contexts,
220      std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
221      RichManglingContext &rmc);
222
223  void RegisterBacklogEntry(const NameToIndexMap::Entry &entry,
224                            const char *decl_context,
225                            const std::set<const char *> &class_contexts);
226
227  Symtab(const Symtab &) = delete;
228  const Symtab &operator=(const Symtab &) = delete;
229};
230
231} // namespace lldb_private
232
233#endif // LLDB_SYMBOL_SYMTAB_H
234