Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===-- DataFileCache.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_CORE_DATAFILECACHE_H
0010 #define LLDB_CORE_DATAFILECACHE_H
0011 
0012 #include "lldb/Utility/FileSpec.h"
0013 #include "lldb/Utility/Status.h"
0014 #include "lldb/Utility/UUID.h"
0015 #include "lldb/lldb-forward.h"
0016 #include "llvm/ADT/DenseMap.h"
0017 #include "llvm/Support/CachePruning.h"
0018 #include "llvm/Support/Caching.h"
0019 #include "llvm/Support/MemoryBuffer.h"
0020 
0021 #include <mutex>
0022 #include <optional>
0023 
0024 namespace lldb_private {
0025 
0026 /// This class enables data to be cached into a directory using the llvm
0027 /// caching code. Data can be stored and accessed using a unique string key.
0028 /// The data will be stored in the directory that is specified in the
0029 /// DataFileCache constructor. The data will be stored in files that start with
0030 /// "llvmcache-<key>" where <key> is the key name specified when getting to
0031 /// setting cached data.
0032 ///
0033 /// Sample code for how to use the cache:
0034 ///
0035 ///   DataFileCache cache("/tmp/lldb-test-cache");
0036 ///   StringRef key("Key1");
0037 ///   auto mem_buffer_up = cache.GetCachedData(key);
0038 ///   if (mem_buffer_up) {
0039 ///     printf("cached data:\n%s", mem_buffer_up->getBufferStart());
0040 ///   } else {
0041 ///     std::vector<uint8_t> data = { 'h', 'e', 'l', 'l', 'o', '\n' };
0042 ///     cache.SetCachedData(key, data);
0043 ///   }
0044 
0045 class DataFileCache {
0046 public:
0047   /// Create a data file cache in the directory path that is specified, using
0048   /// the specified policy.
0049   ///
0050   /// Data will be cached in files created in this directory when clients call
0051   /// DataFileCache::SetCacheData.
0052   DataFileCache(llvm::StringRef path,
0053                 llvm::CachePruningPolicy policy =
0054                     DataFileCache::GetLLDBIndexCachePolicy());
0055 
0056   /// Gets the default LLDB index cache policy, which is controlled by the
0057   /// "LLDBIndexCache" family of settings.
0058   static llvm::CachePruningPolicy GetLLDBIndexCachePolicy();
0059 
0060   /// Get cached data from the cache directory for the specified key.
0061   ///
0062   /// Keys must be unique for any given data. This function attempts to see if
0063   /// the data is available for the specified key and will return a valid memory
0064   /// buffer is data is available.
0065   ///
0066   /// \param key
0067   ///   The unique string key that identifies data being cached.
0068   ///
0069   /// \return
0070   ///   A valid unique pointer to a memory buffer if the data is available, or
0071   ///   a unique pointer that contains NULL if the data is not available.
0072   std::unique_ptr<llvm::MemoryBuffer> GetCachedData(llvm::StringRef key);
0073 
0074   /// Set cached data for the specified key.
0075   ///
0076   /// Setting the cached data will save a file in the cache directory to contain
0077   /// the specified data.
0078   ///
0079   /// \param key
0080   ///   The unique string key that identifies data being cached.
0081   ///
0082   /// \return
0083   ///   True if the data was successfully cached, false otherwise.
0084   bool SetCachedData(llvm::StringRef key, llvm::ArrayRef<uint8_t> data);
0085 
0086   /// Remove the cache file associated with the key.
0087   Status RemoveCacheFile(llvm::StringRef key);
0088 
0089 private:
0090   /// Return the cache file that is associated with the key.
0091   FileSpec GetCacheFilePath(llvm::StringRef key);
0092 
0093   llvm::FileCache m_cache_callback;
0094   FileSpec m_cache_dir;
0095   std::mutex m_mutex;
0096   std::unique_ptr<llvm::MemoryBuffer> m_mem_buff_up;
0097   bool m_take_ownership = false;
0098 };
0099 
0100 /// A signature for a given file on disk.
0101 ///
0102 /// Any files that are cached in the LLDB index cached need some data that
0103 /// uniquely identifies a file on disk and this information should be written
0104 /// into each cache file so we can validate if the cache file still matches
0105 /// the file we are trying to load cached data for. Objects can fill out this
0106 /// signature and then encode and decode them to validate the signatures
0107 /// match. If they do not match, the cache file on disk should be removed as
0108 /// it is out of date.
0109 struct CacheSignature {
0110   /// UUID of object file or module.
0111   std::optional<UUID> m_uuid;
0112   /// Modification time of file on disk.
0113   std::optional<std::time_t> m_mod_time;
0114   /// If this describes a .o file with a BSD archive, the BSD archive's
0115   /// modification time will be in m_mod_time, and the .o file's modification
0116   /// time will be in this m_obj_mod_time.
0117   std::optional<std::time_t> m_obj_mod_time;
0118 
0119   CacheSignature() = default;
0120 
0121   /// Create a signature from a module.
0122   CacheSignature(lldb_private::Module *module);
0123 
0124   /// Create a signature from an object file.
0125   CacheSignature(lldb_private::ObjectFile *objfile);
0126 
0127   void Clear() {
0128     m_uuid = std::nullopt;
0129     m_mod_time = std::nullopt;
0130     m_obj_mod_time = std::nullopt;
0131   }
0132 
0133   /// Return true only if the CacheSignature is valid.
0134   ///
0135   /// Cache signatures are considered valid only if there is a UUID in the file
0136   /// that can uniquely identify the file. Some build systems play with
0137   /// modification times of file so we can not trust them without using valid
0138   /// unique idenifier like the UUID being valid.
0139   bool IsValid() const { return m_uuid.has_value(); }
0140 
0141   /// Check if two signatures are the same.
0142   bool operator==(const CacheSignature &rhs) const {
0143     return m_uuid == rhs.m_uuid && m_mod_time == rhs.m_mod_time &&
0144            m_obj_mod_time == rhs.m_obj_mod_time;
0145   }
0146 
0147   /// Check if two signatures differ.
0148   bool operator!=(const CacheSignature &rhs) const { return !(*this == rhs); }
0149   /// Encode this object into a data encoder object.
0150   ///
0151   /// This allows this object to be serialized to disk. The CacheSignature
0152   /// object must have at least one member variable that has a value in order to
0153   /// be serialized so that we can match this data to when the cached file is
0154   /// loaded at a later time.
0155   ///
0156   /// \param encoder
0157   ///   A data encoder object that serialized bytes will be encoded into.
0158   ///
0159   /// \return
0160   ///   True if a signature was encoded, and false if there were no member
0161   ///   variables that had value. False indicates this data should not be
0162   ///   cached to disk because we were unable to encode a valid signature.
0163   bool Encode(DataEncoder &encoder) const;
0164 
0165   /// Decode a serialized version of this object from data.
0166   ///
0167   /// \param data
0168   ///   The decoder object that references the serialized data.
0169   ///
0170   /// \param offset_ptr
0171   ///   A pointer that contains the offset from which the data will be decoded
0172   ///   from that gets updated as data gets decoded.
0173   ///
0174   /// \return
0175   ///   True if the signature was successfully decoded, false otherwise.
0176   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr);
0177 };
0178 
0179 /// Many cache files require string tables to store data efficiently. This
0180 /// class helps create string tables.
0181 class ConstStringTable {
0182 public:
0183   ConstStringTable() = default;
0184   /// Add a string into the string table.
0185   ///
0186   /// Add a string to the string table will only add the same string one time
0187   /// and will return the offset in the string table buffer to that string.
0188   /// String tables are easy to build with ConstString objects since most LLDB
0189   /// classes for symbol or debug info use them already and they provide
0190   /// permanent storage for the string.
0191   ///
0192   /// \param s
0193   ///   The string to insert into the string table.
0194   ///
0195   /// \return
0196   ///   The byte offset from the start of the string table for the inserted
0197   ///   string. Duplicate strings that get inserted will return the same
0198   ///   byte offset.
0199   uint32_t Add(ConstString s);
0200 
0201   bool Encode(DataEncoder &encoder);
0202 
0203 private:
0204   std::vector<ConstString> m_strings;
0205   llvm::DenseMap<ConstString, uint32_t> m_string_to_offset;
0206   /// Skip one byte to start the string table off with an empty string.
0207   uint32_t m_next_offset = 1;
0208 };
0209 
0210 /// Many cache files require string tables to store data efficiently. This
0211 /// class helps give out strings from a string table that was read from a
0212 /// cache file.
0213 class StringTableReader {
0214 public:
0215   StringTableReader() = default;
0216 
0217   llvm::StringRef Get(uint32_t offset) const;
0218 
0219   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr);
0220 
0221 protected:
0222   /// All of the strings in the string table are contained in m_data.
0223   llvm::StringRef m_data;
0224 };
0225 
0226 } // namespace lldb_private
0227 
0228 #endif // LLDB_CORE_DATAFILECACHE_H