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

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

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