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

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

Coverage information generated Thu Mar 26 16:15:41 2015.