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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
93.8%15160.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 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    :  // A class that take care of initializing asan run-time library.
  16    :  
  17    :  #ifndef SYZYGY_AGENT_ASAN_RUNTIME_H_
  18    :  #define SYZYGY_AGENT_ASAN_RUNTIME_H_
  19    :  
  20    :  #include <set>
  21    :  #include <string>
  22    :  
  23    :  #include "base/callback.h"
  24    :  #include "base/logging.h"
  25    :  #include "base/memory/scoped_ptr.h"
  26    :  #include "base/synchronization/lock.h"
  27    :  #include "syzygy/agent/asan/error_info.h"
  28    :  #include "syzygy/agent/asan/heap_checker.h"
  29    :  #include "syzygy/agent/asan/memory_notifier.h"
  30    :  #include "syzygy/agent/asan/heap_managers/block_heap_manager.h"
  31    :  #include "syzygy/agent/common/stack_capture.h"
  32    :  #include "syzygy/common/asan_parameters.h"
  33    :  
  34    :  namespace agent {
  35    :  namespace asan {
  36    :  
  37    :  // Forward declarations.
  38    :  class AsanLogger;
  39    :  
  40    :  // An Asan Runtime manager.
  41    :  // This class takes care of initializing the different modules (stack cache,
  42    :  // logger...) and provide the functions to report an error.
  43    :  // Basic usage:
  44    :  //     AsanRuntime* asan_runtime = new AsanRuntime();
  45    :  //     std::wstring asan_flags_str;
  46    :  //     AsanRuntime::GetAsanFlagsEnvVar(&asan_flags_str);
  47    :  //     asan_runtime->SetUp(asan_flags_str);  // Initialize the modules.
  48    :  //     ...
  49    :  //     AsanErrorInfo bad_access_info = {};
  50    :  //     ::RtlCaptureContext(&bad_access_info.context);
  51    :  //     StackCapture stack;
  52    :  //     stack.InitFromStack();
  53    :  //     stack.set_stack_id(stack.ComputeRelativeStackId());
  54    :  //     bad_access_info.crash_stack_id = stack.stack_id();
  55    :  //     asan_runtime->OnError(&bad_access_info);
  56    :  //     asan_runtime->TearDown();  // Release the modules.
  57    :  //     delete asan_runtime;
  58    :  class AsanRuntime {
  59    :   public:
  60    :    typedef std::set<common::StackCapture::StackId> StackIdSet;
  61    :  
  62    :    // The type of callback used by the OnError function.
  63    :    typedef base::Callback<void(AsanErrorInfo*)> AsanOnErrorCallBack;
  64    :  
  65    :    AsanRuntime();
  66    :    ~AsanRuntime();
  67    :  
  68    :    // @name Accessors.
  69    :    // @{
  70  E :    MemoryNotifierInterface* memory_notifier() const {
  71  E :      return memory_notifier_.get();
  72  E :    }
  73    :    AsanLogger* logger() const { return logger_.get(); }
  74  E :    Shadow* shadow() const { return shadow_.get(); }
  75  E :    StackCaptureCache* stack_cache() const { return stack_cache_.get(); }
  76    :    // @}
  77    :  
  78    :    // Initialize asan runtime library.
  79    :    // @param flags_command_line The parameters string.
  80    :    // @returns true on success, false otherwise.
  81    :    bool SetUp(const std::wstring& flags_command_line);
  82    :  
  83    :    // Release asan runtime library.
  84    :    void TearDown();
  85    :  
  86    :    // The body of the OnError functions, minus the error handler callback.
  87    :    // Factored out for reuse by OnError and unfiltered exception handling.
  88    :    // @param error_info The information about this error.
  89    :    void OnErrorImpl(AsanErrorInfo* error_info);
  90    :  
  91    :    // The error handler.
  92    :    // @param error_info The information about this error.
  93    :    void OnError(AsanErrorInfo* error_info);
  94    :  
  95    :    // Set the callback called on error.
  96    :    // TODO(sebmarchand): Move the signature of this callback to an header file
  97    :    //     so it'll be easier to update it.
  98    :    void SetErrorCallBack(const AsanOnErrorCallBack& callback);
  99    :  
 100    :    // Try to read the Asan environment variable.
 101    :    // @param env_var_wstr The wstring where to store the environment variable.
 102    :    // returns true on success, false otherwise.
 103    :    static bool GetAsanFlagsEnvVar(std::wstring* env_var_wstr);
 104    :  
 105    :    // Returns true if we should ignore the given @p stack_id, false
 106    :    // otherwise.
 107  E :    bool ShouldIgnoreError(::common::AsanStackId stack_id) const {
 108    :      // TODO(sebmarchand): Keep a list of the stack ids that have already been
 109    :      //     reported so we can avoid reporting the same error multiple times.
 110    :      return params_.ignored_stack_ids_set.find(stack_id) !=
 111  E :          params_.ignored_stack_ids_set.end();
 112  E :    }
 113    :  
 114    :    // Get information about a bad access.
 115    :    // @param bad_access_info Will receive the information about this access.
 116    :    void GetBadAccessInformation(AsanErrorInfo* error_info);
 117    :  
 118    :    // TODO(chrisha): Make this a proper singleton.
 119    :    // @returns the singleton runtime.
 120  E :    static AsanRuntime* runtime() { return runtime_; }
 121    :  
 122    :    // Accessors for runtime parameters.
 123  E :    ::common::InflatedAsanParameters& params() { return params_; }
 124    :    const ::common::InflatedAsanParameters& params() const { return params_; }
 125    :  
 126    :    // @returns the value of the tick counter when the runtime was created.
 127  E :    uint32 starting_ticks() const { return starting_ticks_; }
 128    :  
 129    :    // Retrieves the process's heap.
 130    :    // @returns The ID of the process's heap.
 131  E :    HeapManagerInterface::HeapId GetProcessHeap() {
 132  E :      return heap_manager_->process_heap();
 133  E :    }
 134    :  
 135    :    // Returns the allocation-filter flag value.
 136    :    // @returns the allocation-filter flag value.
 137    :    // @note The flag is stored per-thread using TLS. Multiple threads do not
 138    :    //     share the same flag.
 139    :    bool allocation_filter_flag();
 140    :  
 141    :    // Sets the allocation-filter flag to the specified value.
 142    :    // @param value the new value for the flag.
 143    :    // @note The flag is stored per-thread using TLS. Multiple threads do not
 144    :    //     share the same flag.
 145    :    void set_allocation_filter_flag(bool value);
 146    :  
 147    :    // @names Accessors.
 148    :    // {
 149  i :    AsanFeatureSet enabled_features() const { return enabled_features_; }
 150  E :    uint64_t random_key() const { return random_key_; }
 151    :    // @}
 152    :  
 153    :    // Observes a given thread ID, adding it to thread ID set.
 154    :    // @param thread_id The thread ID that has been observed.
 155    :    void AddThreadId(uint32 thread_id);
 156    :  
 157    :    // Determines if a thread ID has already been seen.
 158    :    // @param thread_id The thread ID to be queried.
 159    :    // @returns true if a given thread ID is valid for this process.
 160    :    bool ThreadIdIsValid(uint32 thread_id);
 161    :  
 162    :    // @name Introspection entry points into the block heap manager. These
 163    :    //    are only meant to be run when the block heap manager lock is already
 164    :    //    held, like during crash processing. If used in unittests care must be
 165    :    //    taken to ensure the access is synchronous if the lock isn't otherwise
 166    :    //    held.
 167    :    // @{
 168    :    // Determines if a given heap ID is valid.
 169    :    // @param uint32 heap_id The heap ID to check.
 170    :    // @returns true if valid, false otherwise.
 171    :    bool HeapIdIsValid(HeapManagerInterface::HeapId heap_id);
 172    :  
 173    :    // Returns the type of a given heap.
 174    :    // @param uint32 heap_id The heap ID to check.
 175    :    // @returns the heap type, or kUnknownHeapType if the heap is invalid.
 176    :    HeapType GetHeapType(HeapManagerInterface::HeapId heap_id);
 177    :    // @}
 178    :  
 179    :    // Processes an exception and determines if an Asan error has occurred,
 180    :    // updating the exception if so. If Breakpad is enabled, passes the
 181    :    // exception to it, otherwise lets the exception continue unhandled.
 182    :    // @note This is basically a Windows SEH exception filter.
 183    :    // @param exception The exception to be processed.
 184    :    // @returns EXCEPTION_CONTINUE_SEARCH or EXCEPTION_EXECUTE_HANDLER.
 185    :    static int CrashForException(EXCEPTION_POINTERS* exception);
 186    :  
 187    :   protected:
 188    :    // Propagate the values of the flags to the target modules.
 189    :    void PropagateParams();
 190    :  
 191    :    // @returns the space required to write the provided corrupt heap info.
 192    :    // @param corrupt_ranges The corrupt range info.
 193    :    size_t CalculateCorruptHeapInfoSize(
 194    :        const HeapChecker::CorruptRangesVector& corrupt_ranges);
 195    :  
 196    :    // Writes corrupt heap information to the provided buffer. This will write
 197    :    // as much of the information as possible in the space provided.
 198    :    // @param corrupt_ranges The corrupt range info.
 199    :    // @param buffer_size The size of the buffer to be written to. May be zero.
 200    :    // @param buffer The location where data will be written. May be null.
 201    :    // @param error_info The written heap metadata will be wired up to the
 202    :    //     provided error_info.
 203    :    void WriteCorruptHeapInfo(
 204    :        const HeapChecker::CorruptRangesVector& corrupt_ranges,
 205    :        size_t buffer_size,
 206    :        void* buffer,
 207    :        AsanErrorInfo* error_info);
 208    :  
 209    :    // Logs information about an Asan error.
 210    :    void LogAsanErrorInfo(AsanErrorInfo* error_info);
 211    :  
 212    :    // Randomly enable some features.
 213    :    // @returns a value describing the state of the features that can be randomly
 214    :    //     enabled or disabled.
 215    :    AsanFeatureSet GenerateRandomFeatureSet();
 216    :  
 217    :    // The heap manager.
 218    :    scoped_ptr<heap_managers::BlockHeapManager> heap_manager_;  // Under lock_.
 219    :  
 220    :    // Contains the state of the features that can be randomly enabled or
 221    :    // disabled.
 222    :    // TODO(sebmarchand): This variable should be deduced from an investigation of
 223    :    // the |params_| variable but is temporarily kept here to make it easier
 224    :    // to investigate on the current heap corruption bug, it should be removed
 225    :    // once the problem gets fixed.
 226    :    AsanFeatureSet enabled_features_;
 227    :  
 228    :    // Indicates if Kasko is enabled.
 229    :    bool enable_kasko_;
 230    :  
 231    :   private:
 232    :    // Sets up the shadow memory.
 233    :    // @returns true on success, false otherwise.
 234    :    bool SetUpShadow();
 235    :  
 236    :    // Tears down the shadow memory.
 237    :    void TearDownShadow();
 238    :  
 239    :    // Set up the memory notifier.
 240    :    // @returns true on success, false otherwise.
 241    :    bool SetUpMemoryNotifier();
 242    :  
 243    :    // Tear down the memory notifier.
 244    :    void TearDownMemoryNotifier();
 245    :  
 246    :    // Set up the logger.
 247    :    // @returns true on success, false otherwise.
 248    :    bool SetUpLogger();
 249    :  
 250    :    // Tear down the logger.
 251    :    void TearDownLogger();
 252    :  
 253    :    // Set up the stack cache.
 254    :    // @returns true on success, false otherwise.
 255    :    bool SetUpStackCache();
 256    :  
 257    :    // Tear down the stack cache.
 258    :    void TearDownStackCache();
 259    :  
 260    :    // Set up the heap manager.
 261    :    // @returns true on success, false otherwise.
 262    :    bool SetUpHeapManager();
 263    :  
 264    :    // Tear down the heap manager.
 265    :    void TearDownHeapManager();
 266    :  
 267    :    // The unhandled exception filter registered by this runtime. This is used
 268    :    // to catch unhandled exceptions so we can augment them with information
 269    :    // about the corrupt heap.
 270    :    static LONG WINAPI UnhandledExceptionFilter(
 271    :        struct _EXCEPTION_POINTERS* exception);
 272    :  
 273    :    // The implementation of the Asan exception handler. This has two flavours:
 274    :    // in the context of an unhandled exception filter, and in the context of
 275    :    // an exception handler. If |is_unhandled| is true then this will pass the
 276    :    // exception along to the next unfiltered exception handler. Otherwise, it'll
 277    :    // pass it along to Breakpad, if present. Finally, it'll let the exception
 278    :    // processing continue unhandled.
 279    :    static LONG ExceptionFilterImpl(bool is_unhandled,
 280    :                                    EXCEPTION_POINTERS* exception);
 281    :  
 282    :    // @name Static variables related to unhandled exception filtering (UEF).
 283    :    // @{
 284    :    static base::Lock lock_;  // Lock for all runtimes.
 285    :    static AsanRuntime* runtime_;  // Singleton. Under lock_.
 286    :    static LPTOP_LEVEL_EXCEPTION_FILTER previous_uef_;  // Under lock_.
 287    :    static bool uef_installed_;  // Under lock_.
 288    :    // @}
 289    :  
 290    :    // The shadow memory used by this runtime.
 291    :    scoped_ptr<Shadow> shadow_;
 292    :  
 293    :    // The shared memory notifier that will be used to update the shadow memory
 294    :    // with redzones for internally allocated memory.
 295    :    scoped_ptr<MemoryNotifierInterface> memory_notifier_;
 296    :  
 297    :    // The shared logger instance that will be used to report errors and runtime
 298    :    // information.
 299    :    scoped_ptr<AsanLogger> logger_;
 300    :  
 301    :    // The shared stack cache instance that will be used by all the heaps.
 302    :    scoped_ptr<StackCaptureCache> stack_cache_;
 303    :  
 304    :    // The asan error callback functor.
 305    :    AsanOnErrorCallBack asan_error_callback_;
 306    :  
 307    :    // The runtime parameters.
 308    :    ::common::InflatedAsanParameters params_;
 309    :  
 310    :    // The tick counter when the runtime was created. This is used for
 311    :    // bracketing valid alloc and free ticks values.
 312    :    uint32 starting_ticks_;
 313    :  
 314    :    // The set of thread IDs that have been seen in the current process.
 315    :    // This is used to validate thread IDs in a block trailer.
 316    :    base::Lock thread_ids_lock_;
 317    :    base::hash_set<uint32> thread_ids_;  // Under thread_ids_lock_.
 318    :  
 319    :    // A random key that is generated on object creation. This is used for
 320    :    // correlating duplicate crash reports on the back-end.
 321    :    const uint64_t random_key_;
 322    :  
 323    :    DISALLOW_COPY_AND_ASSIGN(AsanRuntime);
 324    :  };
 325    :  
 326    :  }  // namespace asan
 327    :  }  // namespace agent
 328    :  
 329    :  #endif  // SYZYGY_AGENT_ASAN_RUNTIME_H_

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