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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%11110.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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    :  // Declares a quarantine, which is used to temporarily house allocations after
  16    :  // they've been freed, permitting use-after-frees to be detected.
  17    :  
  18    :  #ifndef SYZYGY_AGENT_ASAN_QUARANTINE_H_
  19    :  #define SYZYGY_AGENT_ASAN_QUARANTINE_H_
  20    :  
  21    :  #include <vector>
  22    :  
  23    :  #include "base/logging.h"
  24    :  
  25    :  namespace agent {
  26    :  namespace asan {
  27    :  
  28    :  // Specifies the color of the quarantine, depending on its size. YELLOW means
  29    :  // that we are below the maximum size whereas BLACK means we are way overbudget.
  30    :  // We also have two other colors, GREEN and RED, that are used to add
  31    :  // hysteresis. Basically, the color order is as follows:
  32    :  //     GREEN -> YELLOW -> RED -> BLACK
  33    :  // Having these multiple colors allows for trimming the quarantine at different
  34    :  // paces, depending on urgency (urgent trimming is done synchronously on the
  35    :  // critical path whereas non-urgent is done asynchronously in a background
  36    :  // thread). For more information about the colors, see implementation of
  37    :  // GetQuarantineColor.
  38    :  enum TrimColor { GREEN, YELLOW, RED, BLACK };
  39    :  
  40    :  // Used to indicate whether the quarantine must be trimmed synchronously, be
  41    :  // scheduled for trimming by the background thread (asynchronously) or both.
  42    :  using TrimStatus = uint32_t;
  43    :  enum TrimStatusBits : uint32_t {
  44    :    TRIM_NOT_REQUIRED = 0,
  45    :    ASYNC_TRIM_REQUIRED = 1 << 0,
  46    :    SYNC_TRIM_REQUIRED = 1 << 1
  47    :  };
  48    :  
  49    :  // Type returned by Push. It returns whether the push was successful or not and
  50    :  // whether the quarantine requires trimming (either sync and/or async).
  51    :  struct PushResult {
  52    :    bool push_successful;
  53    :    TrimStatus trim_status;
  54    :  };
  55    :  
  56    :  // Type returned by Pop. It returns whether the pop was successful or not and
  57    :  // the color of the quarantine post-pop.
  58    :  struct PopResult {
  59    :    bool pop_successful;
  60    :    TrimColor trim_color;
  61    :  };
  62    :  
  63    :  // The interface that quarantines must satisfy. They store literal copies of
  64    :  // objects of type |ObjectType|.
  65    :  //
  66    :  // Placing objects in the quarantine and removing them from it are factored
  67    :  // out as two separate steps. Thus it is possible for a quarantine invariant
  68    :  // to be invalidated by a call to 'Push', which won't be restored until
  69    :  // sufficient calls to 'Pop' have been made.
  70    :  //
  71    :  // This has been templated on the object type to allow easier unittesting.
  72    :  //
  73    :  // @tparam ObjectType The type of object stored by the quarantine.
  74    :  template<typename ObjectType>
  75    :  class QuarantineInterface {
  76    :   public:
  77    :    typedef ObjectType Object;
  78    :    typedef std::vector<Object> ObjectVector;
  79    :  
  80    :    // Constructor.
  81  E :    QuarantineInterface() { }
  82    :  
  83    :    // Virtual destructor.
  84  E :    virtual ~QuarantineInterface() { }
  85    :  
  86    :    // Places an allocation in the quarantine. This routine must be called under
  87    :    // Lock.
  88    :    // @param The object to place in the quarantine.
  89    :    // @returns a PushResult.
  90    :    virtual PushResult Push(const Object& object) = 0;
  91    :  
  92    :    // Potentially removes an object from the quarantine to maintain the
  93    :    // invariant. This routine must be thread-safe, and implement its own locking.
  94    :    // @param object Is filled in with a copy of the removed object.
  95    :    // @returns a PopResult.
  96    :    virtual PopResult Pop(Object* object) = 0;
  97    :  
  98    :    // Removes all objects from the quarantine, placing them in the provided
  99    :    // vector. This routine must be thread-safe, and implement its own locking.
 100    :    virtual void Empty(ObjectVector* objects) = 0;
 101    :  
 102    :    // The number of objects currently in the quarantine. Only used in testing, as
 103    :    // the implementation is racy.
 104    :    // @returns the number of objects in the quarantine.
 105    :    virtual size_t GetCountForTesting() = 0;
 106    :  
 107    :    // An automatic quarantine lock.
 108    :    //
 109    :    // This class is nested into the QuarantineInterface class to avoid a
 110    :    // complicated template definition. It also avoids exposing the Lock/Unlock
 111    :    // functions.
 112    :    class AutoQuarantineLock {
 113    :     public:
 114    :      // Constructor. Automatically lock the quarantine.
 115  E :      AutoQuarantineLock(QuarantineInterface* quarantine,
 116    :                         const ObjectType& object)
 117  E :          : quarantine_(quarantine) {
 118  E :        DCHECK_NE(reinterpret_cast<QuarantineInterface*>(NULL), quarantine_);
 119  E :        lock_index_ = quarantine_->GetLockId(object);
 120  E :        quarantine_->Lock(lock_index_);
 121  E :      }
 122    :  
 123    :      // Destructor. Automatically unlock the quarantine.
 124  E :      ~AutoQuarantineLock() {
 125  E :        quarantine_->Unlock(lock_index_);
 126  E :      }
 127    :  
 128    :     private:
 129    :      // The bucket to lock in the quarantine.
 130    :      size_t lock_index_;
 131    :  
 132    :      // The quarantine to lock.
 133    :      QuarantineInterface* quarantine_;
 134    :  
 135    :      DISALLOW_COPY_AND_ASSIGN(AutoQuarantineLock);
 136    :    };
 137    :  
 138    :   private:
 139    :    // Get the lock ID associated with a given object in the quarantine. This is
 140    :    // useful in the case where there's several buckets in the quarantine.
 141    :    // @param object The object for which we want to retrieve the lock ID
 142    :    //     associated with it.
 143    :    // @returns the lock ID associated with this object.
 144    :    virtual size_t GetLockId(const Object& object) = 0;
 145    :  
 146    :    // Lock the quarantine.
 147    :    // @param id The bucket to lock, ignored if the quarantine isn't sharded.
 148    :    virtual void Lock(size_t id) = 0;
 149    :  
 150    :    // Unlock the quarantine.
 151    :    // @param id The bucket to lock, ignored if the quarantine isn't sharded.
 152    :    virtual void Unlock(size_t id) = 0;
 153    :  
 154    :    DISALLOW_COPY_AND_ASSIGN(QuarantineInterface);
 155    :  };
 156    :  
 157    :  // Quarantines in Asan are typically storing blocks. Here they are represented
 158    :  // by a CompactBlockInfo, which contains information that the quarantine
 159    :  // frequently accesses.
 160    :  struct CompactBlockInfo;  // Forward declaration.
 161    :  typedef QuarantineInterface<CompactBlockInfo> BlockQuarantineInterface;
 162    :  
 163    :  }  // namespace asan
 164    :  }  // namespace agent
 165    :  
 166    :  #endif  // SYZYGY_AGENT_ASAN_QUARANTINE_H_

Coverage information generated Fri Jul 29 11:00:21 2016.