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 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 ®ex, 94 lldb::SymbolType symbol_type, 95 std::vector<uint32_t> &indexes); 96 uint32_t AppendSymbolIndexesMatchingRegExAndType( 97 const RegularExpression ®ex, 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 ®ex, 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 void CalculateSymbolSizes(); 123 124 void SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, 125 bool remove_duplicates) const; 126 127 static void DumpSymbolHeader(Stream *s); 128 129 void Finalize() { 130 // Shrink to fit the symbols so we don't waste memory 131 if (m_symbols.capacity() > m_symbols.size()) { 132 collection new_symbols(m_symbols.begin(), m_symbols.end()); 133 m_symbols.swap(new_symbols); 134 } 135 } 136 137 void AppendSymbolNamesToMap(const IndexCollection &indexes, 138 bool add_demangled, bool add_mangled, 139 NameToIndexMap &name_to_index_map) const; 140 141 ObjectFile *GetObjectFile() { return m_objfile; } 142 143 protected: 144 typedef std::vector<Symbol> collection; 145 typedef collection::iterator iterator; 146 typedef collection::const_iterator const_iterator; 147 class FileRangeToIndexMapCompare { 148 public: 149 FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {} 150 bool operator()(const uint32_t a_data, const uint32_t b_data) const { 151 return rank(a_data) > rank(b_data); 152 } 153 154 private: 155 // How much preferred is this symbol? 156 int rank(const uint32_t data) const { 157 const Symbol &symbol = *m_symtab.SymbolAtIndex(data); 158 if (symbol.IsExternal()) 159 return 3; 160 if (symbol.IsWeak()) 161 return 2; 162 if (symbol.IsDebug()) 163 return 0; 164 return 1; 165 } 166 const Symtab &m_symtab; 167 }; 168 typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0, 169 FileRangeToIndexMapCompare> 170 FileRangeToIndexMap; 171 void InitNameIndexes(); 172 void InitAddressIndexes(); 173 174 ObjectFile *m_objfile; 175 collection m_symbols; 176 FileRangeToIndexMap m_file_addr_to_index; 177 178 /// Maps function names to symbol indices (grouped by FunctionNameTypes) 179 std::map<lldb::FunctionNameType, UniqueCStringMap<uint32_t>> 180 m_name_to_symbol_indices; 181 mutable std::recursive_mutex 182 m_mutex; // Provide thread safety for this symbol table 183 bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1; 184 185 private: 186 UniqueCStringMap<uint32_t> & 187 GetNameToSymbolIndexMap(lldb::FunctionNameType type) { 188 auto map = m_name_to_symbol_indices.find(type); 189 assert(map != m_name_to_symbol_indices.end()); 190 return map->second; 191 } 192 bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type, 193 Visibility symbol_visibility) const { 194 switch (symbol_debug_type) { 195 case eDebugNo: 196 if (m_symbols[idx].IsDebug()) 197 return false; 198 break; 199 200 case eDebugYes: 201 if (!m_symbols[idx].IsDebug()) 202 return false; 203 break; 204 205 case eDebugAny: 206 break; 207 } 208 209 switch (symbol_visibility) { 210 case eVisibilityAny: 211 return true; 212 213 case eVisibilityExtern: 214 return m_symbols[idx].IsExternal(); 215 216 case eVisibilityPrivate: 217 return !m_symbols[idx].IsExternal(); 218 } 219 return false; 220 } 221 222 /// A helper function that looks up full function names. 223 /// 224 /// We generate unique names for synthetic symbols so that users can look 225 /// them up by name when needed. But because doing so is uncommon in normal 226 /// debugger use, we trade off some performance at lookup time for faster 227 /// symbol table building by detecting these symbols and generating their 228 /// names lazily, rather than adding them to the normal symbol indexes. This 229 /// function does the job of first consulting the name indexes, and if that 230 /// fails it extracts the information it needs from the synthetic name and 231 /// locates the symbol. 232 /// 233 /// @param[in] symbol_name The symbol name to search for. 234 /// 235 /// @param[out] indexes The vector if symbol indexes to update with results. 236 /// 237 /// @returns The number of indexes added to the index vector. Zero if no 238 /// matches were found. 239 uint32_t GetNameIndexes(ConstString symbol_name, 240 std::vector<uint32_t> &indexes); 241 242 void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes, 243 SymbolContextList &sc_list); 244 245 void RegisterMangledNameEntry( 246 uint32_t value, std::set<const char *> &class_contexts, 247 std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, 248 RichManglingContext &rmc); 249 250 void RegisterBacklogEntry(const NameToIndexMap::Entry &entry, 251 const char *decl_context, 252 const std::set<const char *> &class_contexts); 253 254 Symtab(const Symtab &) = delete; 255 const Symtab &operator=(const Symtab &) = delete; 256 }; 257 258 } // namespace lldb_private 259 260 #endif // LLDB_SYMBOL_SYMTAB_H 261