Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:52

0001 //===-- Symtab.h ------------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_SYMBOL_SYMTAB_H
0010 #define LLDB_SYMBOL_SYMTAB_H
0011 
0012 #include "lldb/Core/UniqueCStringMap.h"
0013 #include "lldb/Symbol/Symbol.h"
0014 #include "lldb/Utility/RangeMap.h"
0015 #include "lldb/lldb-private.h"
0016 #include <map>
0017 #include <mutex>
0018 #include <vector>
0019 
0020 namespace lldb_private {
0021 
0022 class Symtab {
0023 public:
0024   typedef std::vector<uint32_t> IndexCollection;
0025   typedef UniqueCStringMap<uint32_t> NameToIndexMap;
0026 
0027   enum Debug {
0028     eDebugNo,  // Not a debug symbol
0029     eDebugYes, // A debug symbol
0030     eDebugAny
0031   };
0032 
0033   enum Visibility { eVisibilityAny, eVisibilityExtern, eVisibilityPrivate };
0034 
0035   Symtab(ObjectFile *objfile);
0036   ~Symtab();
0037 
0038   void PreloadSymbols();
0039   void Reserve(size_t count);
0040   Symbol *Resize(size_t count);
0041   uint32_t AddSymbol(const Symbol &symbol);
0042   size_t GetNumSymbols() const;
0043   void SectionFileAddressesChanged();
0044   void
0045   Dump(Stream *s, Target *target, SortOrder sort_type,
0046        Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
0047   void Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
0048             Mangled::NamePreference name_preference =
0049                 Mangled::ePreferDemangled) const;
0050   uint32_t GetIndexForSymbol(const Symbol *symbol) const;
0051   std::recursive_mutex &GetMutex() { return m_mutex; }
0052   Symbol *FindSymbolByID(lldb::user_id_t uid) const;
0053   Symbol *SymbolAtIndex(size_t idx);
0054   const Symbol *SymbolAtIndex(size_t idx) const;
0055   Symbol *FindSymbolWithType(lldb::SymbolType symbol_type,
0056                              Debug symbol_debug_type,
0057                              Visibility symbol_visibility, uint32_t &start_idx);
0058   /// Get the parent symbol for the given symbol.
0059   ///
0060   /// Many symbols in symbol tables are scoped by other symbols that
0061   /// contain one or more symbol. This function will look for such a
0062   /// containing symbol and return it if there is one.
0063   const Symbol *GetParent(Symbol *symbol) const;
0064   uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
0065                                        std::vector<uint32_t> &indexes,
0066                                        uint32_t start_idx = 0,
0067                                        uint32_t end_index = UINT32_MAX) const;
0068   uint32_t AppendSymbolIndexesWithTypeAndFlagsValue(
0069       lldb::SymbolType symbol_type, uint32_t flags_value,
0070       std::vector<uint32_t> &indexes, uint32_t start_idx = 0,
0071       uint32_t end_index = UINT32_MAX) const;
0072   uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type,
0073                                        Debug symbol_debug_type,
0074                                        Visibility symbol_visibility,
0075                                        std::vector<uint32_t> &matches,
0076                                        uint32_t start_idx = 0,
0077                                        uint32_t end_index = UINT32_MAX) const;
0078   uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
0079                                        std::vector<uint32_t> &matches);
0080   uint32_t AppendSymbolIndexesWithName(ConstString symbol_name,
0081                                        Debug symbol_debug_type,
0082                                        Visibility symbol_visibility,
0083                                        std::vector<uint32_t> &matches);
0084   uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
0085                                               lldb::SymbolType symbol_type,
0086                                               std::vector<uint32_t> &matches);
0087   uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
0088                                               lldb::SymbolType symbol_type,
0089                                               Debug symbol_debug_type,
0090                                               Visibility symbol_visibility,
0091                                               std::vector<uint32_t> &matches);
0092   uint32_t AppendSymbolIndexesMatchingRegExAndType(
0093       const RegularExpression &regex, lldb::SymbolType symbol_type,
0094       std::vector<uint32_t> &indexes,
0095       Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
0096   uint32_t AppendSymbolIndexesMatchingRegExAndType(
0097       const RegularExpression &regex, lldb::SymbolType symbol_type,
0098       Debug symbol_debug_type, Visibility symbol_visibility,
0099       std::vector<uint32_t> &indexes,
0100       Mangled::NamePreference name_preference =
0101           Mangled::NamePreference::ePreferDemangled);
0102   void FindAllSymbolsWithNameAndType(ConstString name,
0103                                      lldb::SymbolType symbol_type,
0104                                      std::vector<uint32_t> &symbol_indexes);
0105   void FindAllSymbolsWithNameAndType(ConstString name,
0106                                      lldb::SymbolType symbol_type,
0107                                      Debug symbol_debug_type,
0108                                      Visibility symbol_visibility,
0109                                      std::vector<uint32_t> &symbol_indexes);
0110   void FindAllSymbolsMatchingRexExAndType(
0111       const RegularExpression &regex, lldb::SymbolType symbol_type,
0112       Debug symbol_debug_type, Visibility symbol_visibility,
0113       std::vector<uint32_t> &symbol_indexes,
0114       Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
0115   Symbol *FindFirstSymbolWithNameAndType(ConstString name,
0116                                          lldb::SymbolType symbol_type,
0117                                          Debug symbol_debug_type,
0118                                          Visibility symbol_visibility);
0119   Symbol *FindSymbolAtFileAddress(lldb::addr_t file_addr);
0120   Symbol *FindSymbolContainingFileAddress(lldb::addr_t file_addr);
0121   void ForEachSymbolContainingFileAddress(
0122       lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback);
0123   void FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
0124                            SymbolContextList &sc_list);
0125 
0126   void SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
0127                                 bool remove_duplicates) const;
0128 
0129   static void DumpSymbolHeader(Stream *s);
0130 
0131   void Finalize();
0132 
0133   void AppendSymbolNamesToMap(const IndexCollection &indexes,
0134                               bool add_demangled, bool add_mangled,
0135                               NameToIndexMap &name_to_index_map) const;
0136 
0137   ObjectFile *GetObjectFile() const { return m_objfile; }
0138 
0139   /// Decode a serialized version of this object from data.
0140   ///
0141   /// \param data
0142   ///   The decoder object that references the serialized data.
0143   ///
0144   /// \param offset_ptr
0145   ///   A pointer that contains the offset from which the data will be decoded
0146   ///   from that gets updated as data gets decoded.
0147   ///
0148   /// \param[out] uuid_mismatch
0149   ///   Set to true if a cache file exists but the UUID didn't match, false
0150   ///   otherwise.
0151   ///
0152   /// \return
0153   ///   True if the symbol table is successfully decoded and can be used,
0154   ///   false otherwise.
0155   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
0156               bool &uuid_mismatch);
0157 
0158   /// Encode this object into a data encoder object.
0159   ///
0160   /// This allows this object to be serialized to disk. The object file must
0161   /// have a valid Signature in order to be serialized as it is used to make
0162   /// sure the cached information matches when cached data is loaded at a later
0163   /// time. If the object file doesn't have a valid signature false will be
0164   /// returned and it will indicate we should not cache this data.
0165   ///
0166   /// \param encoder
0167   ///   A data encoder object that serialized bytes will be encoded into.
0168   ///
0169   /// \return
0170   ///   True if the symbol table's object file can generate a valid signature
0171   ///   and all data for the symbol table was encoded, false otherwise.
0172   bool Encode(DataEncoder &encoder) const;
0173 
0174   /// Get the cache key string for this symbol table.
0175   ///
0176   /// The cache key must start with the module's cache key and is followed
0177   /// by information that indicates this key is for caching the symbol table
0178   /// contents and should also include the has of the object file. A module can
0179   /// be represented by an ObjectFile object for the main executable, but can
0180   /// also have a symbol file that is from the same or a different object file.
0181   /// This means we might have two symbol tables cached in the index cache, one
0182   /// for the main executable and one for the symbol file.
0183   ///
0184   /// \return
0185   ///   The unique cache key used to save and retrieve data from the index cache.
0186   std::string GetCacheKey();
0187 
0188   /// Save the symbol table data out into a cache.
0189   ///
0190   /// The symbol table will only be saved to a cache file if caching is enabled.
0191   ///
0192   /// We cache the contents of the symbol table since symbol tables in LLDB take
0193   /// some time to initialize. This is due to the many sources for data that are
0194   /// used to create a symbol table:
0195   /// - standard symbol table
0196   /// - dynamic symbol table (ELF)
0197   /// - compressed debug info sections
0198   /// - unwind information
0199   /// - function pointers found in runtimes for global constructor/destructors
0200   /// - other sources.
0201   /// All of the above sources are combined and one symbol table results after
0202   /// all sources have been considered.
0203   void SaveToCache();
0204 
0205   /// Load the symbol table from the index cache.
0206   ///
0207   /// Quickly load the finalized symbol table from the index cache. This saves
0208   /// time when the debugger starts up. The index cache file for the symbol
0209   /// table has the modification time set to the same time as the main module.
0210   /// If the cache file exists and the modification times match, we will load
0211   /// the symbol table from the serlized cache file.
0212   ///
0213   /// \return
0214   ///   True if the symbol table was successfully loaded from the index cache,
0215   ///   false if the symbol table wasn't cached or was out of date.
0216   bool LoadFromCache();
0217 
0218 
0219   /// Accessors for the bool that indicates if the debug info index was loaded
0220   /// from, or saved to the module index cache.
0221   ///
0222   /// In statistics it is handy to know if a module's debug info was loaded from
0223   /// or saved to the cache. When the debug info index is loaded from the cache
0224   /// startup times can be faster. When the cache is enabled and the debug info
0225   /// index is saved to the cache, debug sessions can be slower. These accessors
0226   /// can be accessed by the statistics and emitted to help track these costs.
0227   /// \{
0228   bool GetWasLoadedFromCache() const {
0229     return m_loaded_from_cache;
0230   }
0231   void SetWasLoadedFromCache() {
0232     m_loaded_from_cache = true;
0233   }
0234   bool GetWasSavedToCache() const {
0235     return m_saved_to_cache;
0236   }
0237   void SetWasSavedToCache() {
0238     m_saved_to_cache = true;
0239   }
0240   /// \}
0241 
0242 protected:
0243   typedef std::vector<Symbol> collection;
0244   typedef collection::iterator iterator;
0245   typedef collection::const_iterator const_iterator;
0246   class FileRangeToIndexMapCompare {
0247   public:
0248     FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {}
0249     bool operator()(const uint32_t a_data, const uint32_t b_data) const {
0250       return rank(a_data) > rank(b_data);
0251     }
0252 
0253   private:
0254     // How much preferred is this symbol?
0255     int rank(const uint32_t data) const {
0256       const Symbol &symbol = *m_symtab.SymbolAtIndex(data);
0257       if (symbol.IsExternal())
0258         return 3;
0259       if (symbol.IsWeak())
0260         return 2;
0261       if (symbol.IsDebug())
0262         return 0;
0263       return 1;
0264     }
0265     const Symtab &m_symtab;
0266   };
0267   typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0,
0268                           FileRangeToIndexMapCompare>
0269       FileRangeToIndexMap;
0270   void InitNameIndexes();
0271   void InitAddressIndexes();
0272 
0273   ObjectFile *m_objfile;
0274   collection m_symbols;
0275   FileRangeToIndexMap m_file_addr_to_index;
0276 
0277   /// Maps function names to symbol indices (grouped by FunctionNameTypes)
0278   std::map<lldb::FunctionNameType, UniqueCStringMap<uint32_t>>
0279       m_name_to_symbol_indices;
0280   mutable std::recursive_mutex
0281       m_mutex; // Provide thread safety for this symbol table
0282   bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1,
0283     m_loaded_from_cache : 1, m_saved_to_cache : 1;
0284 
0285 private:
0286   UniqueCStringMap<uint32_t> &
0287   GetNameToSymbolIndexMap(lldb::FunctionNameType type) {
0288     auto map = m_name_to_symbol_indices.find(type);
0289     assert(map != m_name_to_symbol_indices.end());
0290     return map->second;
0291   }
0292   bool CheckSymbolAtIndex(size_t idx, Debug symbol_debug_type,
0293                           Visibility symbol_visibility) const {
0294     switch (symbol_debug_type) {
0295     case eDebugNo:
0296       if (m_symbols[idx].IsDebug())
0297         return false;
0298       break;
0299 
0300     case eDebugYes:
0301       if (!m_symbols[idx].IsDebug())
0302         return false;
0303       break;
0304 
0305     case eDebugAny:
0306       break;
0307     }
0308 
0309     switch (symbol_visibility) {
0310     case eVisibilityAny:
0311       return true;
0312 
0313     case eVisibilityExtern:
0314       return m_symbols[idx].IsExternal();
0315 
0316     case eVisibilityPrivate:
0317       return !m_symbols[idx].IsExternal();
0318     }
0319     return false;
0320   }
0321 
0322   /// A helper function that looks up full function names.
0323   ///
0324   /// We generate unique names for synthetic symbols so that users can look
0325   /// them up by name when needed. But because doing so is uncommon in normal
0326   /// debugger use, we trade off some performance at lookup time for faster
0327   /// symbol table building by detecting these symbols and generating their
0328   /// names lazily, rather than adding them to the normal symbol indexes. This
0329   /// function does the job of first consulting the name indexes, and if that
0330   /// fails it extracts the information it needs from the synthetic name and
0331   /// locates the symbol.
0332   ///
0333   /// @param[in] symbol_name The symbol name to search for.
0334   ///
0335   /// @param[out] indexes The vector if symbol indexes to update with results.
0336   ///
0337   /// @returns The number of indexes added to the index vector. Zero if no
0338   /// matches were found.
0339   uint32_t GetNameIndexes(ConstString symbol_name,
0340                           std::vector<uint32_t> &indexes);
0341 
0342   void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
0343                                         SymbolContextList &sc_list);
0344 
0345   void RegisterMangledNameEntry(
0346       uint32_t value, std::set<const char *> &class_contexts,
0347       std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
0348       RichManglingContext &rmc);
0349 
0350   void RegisterBacklogEntry(const NameToIndexMap::Entry &entry,
0351                             const char *decl_context,
0352                             const std::set<const char *> &class_contexts);
0353 
0354   Symtab(const Symtab &) = delete;
0355   const Symtab &operator=(const Symtab &) = delete;
0356 };
0357 
0358 } // namespace lldb_private
0359 
0360 #endif // LLDB_SYMBOL_SYMTAB_H