Coverage for /Syzygy/agent/asan/registry_cache.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%0045.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // This class allows us to save, in the Windows registry, the relative IDs of
  16    :  // allocation stack traces for the current module & version. Module refers to
  17    :  // the filename of the module containing the code (usually an executable or a
  18    :  // DLL). The version is determined by various methods (see implementation of
  19    :  // InitModuleInfo). Note that there is no standard naming convention for the
  20    :  // version as it's used as is.
  21    :  //
  22    :  // Values are stored in a base key that depends on the name provided to the
  23    :  // constructor. Each module gets its own registry key under the base key and
  24    :  // that key's name is the same as the module base name. Inside each module key
  25    :  // is a second level of keys, corresponding to the versions (same name as the
  26    :  // version). An example of the key hierarchy is presented in the following
  27    :  // diagram:
  28    :  //
  29    :  // Base key +---> chrome.exe  +---> 39.0.2171.95
  30    :  //          |                 +---> 39.0.2171.99
  31    :  //          |
  32    :  //          +---> program.dll +---> Version 1
  33    :  //          |
  34    :  //          +---> program.exe +---> 1
  35    :  //                            +---> 2
  36    :  //                            +---> 3
  37    :  //
  38    :  // Finally, inside each version key are the entries. Each entry corresponds to
  39    :  // an allocation stack trace. The name of the entry corresponds to its timestamp
  40    :  // (return value of ToInternalValue) and its value corresponds to the stack ID.
  41    :  //
  42    :  // At every initialization, the entries of all modules/versions are purged
  43    :  // (regardless of the current module/version). This is done by removing all
  44    :  // entries older than |kMaxDaysInRegistry| as well as limiting the total number
  45    :  // of entries inside each version to |kMaxEntriesPerVersion| and by deleting
  46    :  // empty module and version keys.
  47    :  
  48    :  #ifndef SYZYGY_AGENT_ASAN_REGISTRY_CACHE_H_
  49    :  #define SYZYGY_AGENT_ASAN_REGISTRY_CACHE_H_
  50    :  
  51    :  #include <unordered_set>
  52    :  
  53    :  #include "base/macros.h"
  54    :  #include "base/files/file_path.h"
  55    :  #include "base/strings/string_number_conversions.h"
  56    :  #include "base/time/time.h"
  57    :  #include "base/win/registry.h"
  58    :  #include "syzygy/agent/asan/heap_checker.h"
  59    :  #include "syzygy/agent/common/stack_capture.h"
  60    :  
  61  m :  namespace agent {
  62  m :  namespace asan {
  63    :  
  64  m :  class RegistryCache {
  65  m :   public:
  66    :    // Default value for |max_days_in_registry_|.
  67  m :    static const size_t kDefaultMaxDaysInRegistry;
  68    :  
  69    :    // Default value for |max_entries_per_version_|.
  70  m :    static const size_t kDefaultMaxEntriesPerVersion;
  71    :  
  72    :    // Default value for |max_modules_|.
  73  m :    static const size_t kDefaultMaxModules;
  74    :  
  75    :    // Default value for |max_versions_|.
  76  m :    static const size_t kDefaultMaxVersions;
  77    :  
  78    :    // Root of the path in the registry (values that make sense are HCU and HLM).
  79  m :    static const HKEY kRegistryRootKey;
  80    :  
  81    :    // The base path that will contain the module keys (under |kRoot|). This gets
  82    :    // completed with the registry name that gets passed to the constructor to
  83    :    // form |registry_key_|.
  84  m :    static const wchar_t kRegistryBaseKey[];
  85    :    // Constructors.
  86    :    // @param registry_name The base name that is used for storing in the
  87    :    //     registry.
  88    :    // @param max_days_in_registry Value of max_days_in_registry_.
  89    :    // @param max_entries_per_version Value of max_entries_per_version_.
  90    :    // @param max_modules Value of max_modules_.
  91    :    // @param max_versions Value of max_versions_.
  92  m :    explicit RegistryCache(const wchar_t* registry_name);
  93  m :    RegistryCache(const wchar_t* registry_name,
  94  m :                  size_t max_days_in_registry,
  95  m :                  size_t max_entries_per_version,
  96  m :                  size_t max_modules,
  97  m :                  size_t max_versions);
  98    :  
  99    :    // Initializes the registry cache and prunes old values in the registry. This
 100    :    // must be called once, before any other method. Note that this function is
 101    :    // not thread-safe.
 102    :    // @returns false if an error occured.
 103  m :    bool Init();
 104    :  
 105    :    // Adds a new |allocation_stack_id|, if it was not existent. Otherwise,
 106    :    // updates it by removing corresponding registry value and inserting a new
 107    :    // one. note that the ID must be a relative one. Will not do anything if the
 108    :    // module has not been initialized properly.
 109    :    // @pre is_init_ is true.
 110    :    // @param allocation_stack_id The relative stack ID to add.
 111  m :    void AddOrUpdateStackId(common::StackCapture::StackId allocation_stack_id);
 112    :  
 113    :    // Checks if |allocation_stack_id| has been loaded from the registry. Will
 114    :    // always return false if the module has not been initialized properly.
 115    :    // @pre is_init_ is true.
 116    :    // @param allocation_stack_id The relative stack ID to lookup.
 117    :    // @returns true if the ID has been found, false otherwise or if not
 118    :    //     initialized.
 119  m :    bool DoesIdExist(common::StackCapture::StackId allocation_stack_id) const;
 120    :  
 121    :    // Removes|allocation_stack_id| from the registry. Will always return false
 122    :    // if the module has not been initialized properly.
 123    :    // @pre is_init_ is true.
 124    :    // @param allocation_stack_id The relative stack ID to remove.
 125    :    // @returns true if the ID has been found, false otherwise or if not
 126    :    //     initialized.
 127  m :    bool RemoveStackId(common::StackCapture::StackId allocation_stack_id);
 128    :  
 129    :    // Deletes the registry key corresponding to |registry_name|, including
 130    :    // everything below it. Use carefully!
 131    :    // @param registry_name  The base name whose key will be deleted from the
 132    :    //     registry.
 133  m :    static void DeleteRegistryTree(const wchar_t* registry_name);
 134    :  
 135  m :   protected:
 136    :    // For convenience (also used in unittests).
 137  m :    typedef base::win::RegistryValueIterator RegValueIter;
 138  m :    typedef base::win::RegistryKeyIterator RegKeyIter;
 139  m :    typedef common::StackCapture::StackId StackId;
 140    :  
 141    :    // Maximum age allowed for an entry (in days). Any entry older than this value
 142    :    // will be purged during cleaning.
 143  m :    size_t max_days_in_registry_;
 144    :  
 145    :    // Maximum number of entries allowed per module version. The cleaning process
 146    :    // will ensure that the number of entries in a module version does not exceed
 147    :    // this threshold by purging the oldest ones.
 148  m :    size_t max_entries_per_version_;
 149    :  
 150    :    // Maximum number of modules allowed. The cleaning process will ensure that
 151    :    // the number of modules does not exceed this threshold by purging the oldest
 152    :    // ones.
 153  m :    size_t max_modules_;
 154    :  
 155    :    // Maximum number of versions allowed per module. The cleaning process will
 156    :    // ensure that the number of versions for a module does not exceed this
 157    :    // threshold by purging the oldest ones.
 158  m :    size_t max_versions_;
 159    :  
 160    :    // The base path that will contain the module keys (under |kRoot|).
 161  m :    std::wstring registry_cache_key_;
 162    :  
 163    :    // Contains the name of the module.
 164  m :    base::FilePath::StringType module_name_;
 165    :    // Contains the module version.
 166  m :    std::wstring module_version_;
 167    :    // Contains the path of the module key in the registry.
 168  m :    std::wstring module_key_name_;
 169    :  
 170  m :   private:
 171    :    // Initializes the module name and version. This can fail if we are not able
 172    :    // to succesfully identify both.
 173    :    // @returns false if an error occured.
 174  m :    bool InitModuleInfo();
 175    :  
 176    :    // Function that starts the cleanup of old entries in the registry by going
 177    :    // through each top-level key (corresponding to a module name) and calling
 178    :    // CleanUpModule on each entry. It will also delete module keys that become
 179    :    // empty after the operation. Finally, it limits the number of modules to
 180    :    // |kMaxModules| by deleting the oldest ones, if necessary.
 181  m :    void CleanUp();
 182    :  
 183    :    // Function that cleans up a module key by going through each of its version
 184    :    // keys and calling CleanUpVersion on each entry. It will also delete version
 185    :    // keys that become empty after the operation. Finally, it limits the number
 186    :    // of versions to |kMaxVersions| by deleting the oldest ones, if necessary.
 187    :    // @param base_key The path of the registry key to clean up.
 188    :    // @param newest If not NULL, will be set to the timestamp of the newest
 189    :    //     entry. If no entries are valid/existent, will be set to UnixEpoch.
 190  m :    void CleanUpModule(const std::wstring& base_key, base::Time* newest);
 191    :  
 192    :    // Purges old values and limits the total number of entries in a version key
 193    :    // to |kMaxEntriesPerVersion|.
 194    :    // @param src The registry key to clean up.
 195    :    // @param newest If not NULL, will be set to the timestamp of the newest
 196    :    //     entry. If no entries are valid/existent, will be set to UnixEpoch.
 197  m :    void CleanUpVersion(base::win::RegKey* src, base::Time* newest);
 198    :  
 199    :    // Loads the entries from the registry for the current module.
 200  m :    void LoadEntries();
 201    :  
 202    :    // True if Init() has been called successfully.
 203  m :    bool is_init_;
 204    :  
 205    :    // The relative stack IDs that are loaded from the registry.
 206  m :    std::unordered_set<common::StackCapture::StackId> entries_;
 207    :  
 208  m :    DISALLOW_COPY_AND_ASSIGN(RegistryCache);
 209  m :  };
 210    :  
 211  m :  }  // namespace asan
 212  m :  }  // namespace agent
 213    :  
 214    :  #endif  // SYZYGY_AGENT_ASAN_REGISTRY_CACHE_H_

Coverage information generated Thu Jan 14 17:40:38 2016.