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 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 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 bool GetWasLoadedFromCache() const { 226 return m_loaded_from_cache; 227 } 228 void SetWasLoadedFromCache() { 229 m_loaded_from_cache = true; 230 } 231 bool GetWasSavedToCache() const { 232 return m_saved_to_cache; 233 } 234 void SetWasSavedToCache() { 235 m_saved_to_cache = true; 236 } 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 FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {} 246 bool operator()(const uint32_t a_data, const uint32_t b_data) const { 247 return rank(a_data) > rank(b_data); 248 } 249 250 private: 251 // How much preferred is this symbol? 252 int rank(const uint32_t data) const { 253 const Symbol &symbol = *m_symtab.SymbolAtIndex(data); 254 if (symbol.IsExternal()) 255 return 3; 256 if (symbol.IsWeak()) 257 return 2; 258 if (symbol.IsDebug()) 259 return 0; 260 return 1; 261 } 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 GetNameToSymbolIndexMap(lldb::FunctionNameType type) { 285 auto map = m_name_to_symbol_indices.find(type); 286 assert(map != m_name_to_symbol_indices.end()); 287 return map->second; 288 } 289 bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type, 290 Visibility symbol_visibility) const { 291 switch (symbol_debug_type) { 292 case eDebugNo: 293 if (m_symbols[idx].IsDebug()) 294 return false; 295 break; 296 297 case eDebugYes: 298 if (!m_symbols[idx].IsDebug()) 299 return false; 300 break; 301 302 case eDebugAny: 303 break; 304 } 305 306 switch (symbol_visibility) { 307 case eVisibilityAny: 308 return true; 309 310 case eVisibilityExtern: 311 return m_symbols[idx].IsExternal(); 312 313 case eVisibilityPrivate: 314 return !m_symbols[idx].IsExternal(); 315 } 316 return false; 317 } 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 358