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 liblldb_Symtab_h_
10 #define liblldb_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 
19 namespace lldb_private {
20 
21 class Symtab {
22 public:
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 
142 protected:
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 
184 private:
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   DISALLOW_COPY_AND_ASSIGN(Symtab);
228 };
229 
230 } // namespace lldb_private
231 
232 #endif // liblldb_Symtab_h_
233