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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%990.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    :  // Implements HeapProxy, a class that wraps Win32 heap allocations but adds
  16    :  // heap/tail redzones.
  17    :  
  18    :  #ifndef SYZYGY_AGENT_ASAN_ASAN_HEAP_H_
  19    :  #define SYZYGY_AGENT_ASAN_ASAN_HEAP_H_
  20    :  
  21    :  #include <windows.h>  // NOLINT
  22    :  
  23    :  #include "base/logging.h"
  24    :  #include "base/string_piece.h"
  25    :  #include "base/debug/stack_trace.h"
  26    :  #include "base/synchronization/lock.h"
  27    :  #include "syzygy/agent/asan/stack_capture_cache.h"
  28    :  #include "syzygy/agent/common/dlist.h"
  29    :  
  30    :  namespace agent {
  31    :  namespace asan {
  32    :  
  33    :  // Forward declaration.
  34    :  class AsanLogger;
  35    :  class StackCapture;
  36    :  class StackCaptureCache;
  37    :  
  38    :  // An helper function to send a command to Windbg. Windbg should first receive
  39    :  // the ".ocommand ASAN" command to treat those messages as commands.
  40    :  // TODO(sebmarchand): Move this function and the following one to the
  41    :  //     AsanRuntime class once it's ready.
  42    :  void ASANDbgCmd(const wchar_t* fmt, ...);
  43    :  
  44    :  // An helper function to print a message to Windbg's console.
  45    :  void ASANDbgMessage(const wchar_t* fmt, ...);
  46    :  
  47    :  // Makes like a Win32 heap manager heap, but adds a redzone before and after
  48    :  // each allocation and maintains a quarantine list of freed blocks.
  49    :  class HeapProxy {
  50    :   public:
  51    :    // The different memory access modes that we can encounter.
  52    :    enum AccessMode {
  53    :      ASAN_READ_ACCESS,
  54    :      ASAN_WRITE_ACCESS,
  55    :      ASAN_UNKNOWN_ACCESS
  56    :    };
  57    :  
  58    :    HeapProxy(StackCaptureCache* cache, AsanLogger* logger);
  59    :    ~HeapProxy();
  60    :  
  61    :    // @name Cast to/from HANDLE.
  62    :    // @{
  63    :    static HANDLE ToHandle(HeapProxy* proxy);
  64    :    static HeapProxy* FromHandle(HANDLE heap);
  65    :    // @}
  66    :  
  67    :    // @name Heap interface.
  68    :    // @{
  69    :    bool Create(DWORD options,
  70    :                size_t initial_size,
  71    :                size_t maximum_size);
  72    :    bool Destroy();
  73    :    void* Alloc(DWORD flags, size_t bytes);
  74    :    void* ReAlloc(DWORD flags, void* mem, size_t bytes);
  75    :    bool Free(DWORD flags, void* mem);
  76    :    size_t Size(DWORD flags, const void* mem);
  77    :    bool Validate(DWORD flags, const void* mem);
  78    :    size_t Compact(DWORD flags);
  79    :    bool Lock();
  80    :    bool Unlock();
  81    :    bool Walk(PROCESS_HEAP_ENTRY* entry);
  82    :    bool SetInformation(HEAP_INFORMATION_CLASS info_class,
  83    :                        void* info,
  84    :                        size_t info_length);
  85    :    bool QueryInformation(HEAP_INFORMATION_CLASS info_class,
  86    :                          void* info,
  87    :                          size_t info_length,
  88    :                          unsigned long* return_length);
  89    :    // @}
  90    :  
  91    :    // Report a bad access to the heap.
  92    :    // @param addr The red-zoned address causing a bad access.
  93    :    // @param context The context at which the access occurred.
  94    :    // @param stack The stack capture at the point of error.
  95    :    // @param access_mode The kind of the access (read or write).
  96    :    // @param access_size The size of the access (in bytes).
  97    :    // @returns true if the address belongs to a memory block, false otherwise.
  98    :    bool OnBadAccess(const void* addr,
  99    :                     const CONTEXT& context,
 100    :                     const StackCapture& stack,
 101    :                     AccessMode access_mode,
 102    :                     size_t access_size);
 103    :  
 104    :    // Report an unknown error while attempting to access a red-zoned heap
 105    :    // address.
 106    :    // @param addr The address causing an error.
 107    :    // @param context The context at which the access occurred.
 108    :    // @param stack The stack capture at the point of error.
 109    :    // @param access_mode The kind of the access (read or write).
 110    :    // @param access_size The size of the access (in bytes).
 111    :    void ReportUnknownError(const void* addr,
 112    :                            const CONTEXT& context,
 113    :                            const StackCapture& stack,
 114    :                            AccessMode access_mode,
 115    :                            size_t access_size);
 116    :  
 117    :    // @name Cast to/from HANDLE.
 118    :    // @{
 119    :    static LIST_ENTRY* ToListEntry(HeapProxy* proxy);
 120    :    static HeapProxy* FromListEntry(LIST_ENTRY* list_entry);
 121    :    // @}
 122    :  
 123    :    // Set the default max size of the quarantine of a heap proxy.
 124    :    // @param quarantine_max_size The maximum size of the quarantine list, in
 125    :    //     bytes.
 126  E :    static void set_default_quarantine_max_size(size_t quarantine_max_size) {
 127  E :      default_quarantine_max_size_ = quarantine_max_size;
 128  E :    }
 129    :  
 130    :    // Get the default max size of the quarantine of a heap proxy.
 131  E :    static size_t default_quarantine_max_size() {
 132  E :      return default_quarantine_max_size_;
 133  E :    }
 134    :  
 135    :    // Set the max size of the quarantine of a heap proxy. If the current size of
 136    :    // the quarantine is greater than this new max size then the extra blocks are
 137    :    // removed from the quarantine.
 138    :    // @param quarantine_max_size The maximum size of the quarantine list, in
 139    :    //     bytes.
 140    :    void set_quarantine_max_size(size_t quarantine_max_size);
 141    :  
 142    :    // Get the max size of the quarantine of a heap proxy.
 143  E :    size_t quarantine_max_size() {
 144  E :      return quarantine_max_size_;
 145  E :    }
 146    :  
 147    :   protected:
 148    :    // Enumeration of the different kind of bad heap access that we can encounter.
 149    :    enum BadAccessKind {
 150    :      UNKNOWN_BAD_ACCESS,
 151    :      USE_AFTER_FREE,
 152    :      HEAP_BUFFER_OVERFLOW,
 153    :      HEAP_BUFFER_UNDERFLOW,
 154    :    };
 155    :  
 156    :    enum BlockState {
 157    :      ALLOCATED,
 158    :      FREED,
 159    :      QUARANTINED,
 160    :    };
 161    :  
 162    :    // Every allocated block starts with a BlockHeader.
 163    :    struct BlockHeader {
 164    :      size_t magic_number;
 165    :      size_t size;
 166    :      BlockState state;
 167    :      const StackCapture* alloc_stack;
 168    :      const StackCapture* free_stack;
 169    :    };
 170    :  
 171    :    // Free blocks are linked together.
 172    :    struct FreeBlockHeader : public BlockHeader {
 173    :      FreeBlockHeader* next;
 174    :    };
 175    :  
 176    :    // Magic number to identify the beginning of a block header.
 177    :    static const size_t kBlockHeaderSignature = 0x03CA80E7;
 178    :  
 179    :    // Returns a string describing a bad access kind.
 180    :    static const char* AccessTypeToStr(BadAccessKind bad_access_kind);
 181    :  
 182    :    // Returns the block header for an alloc.
 183    :    BlockHeader* ToBlock(const void* alloc);
 184    :  
 185    :    // Returns alloc for a block.
 186    :    uint8* ToAlloc(BlockHeader* block);
 187    :  
 188    :    // Find the memory block containing @p addr.
 189    :    // @returns a pointer to this memory block in case of success, NULL otherwise.
 190    :    BlockHeader* FindAddressBlock(const void* addr);
 191    :  
 192    :    // Give the type of a bad heap access corresponding to an address.
 193    :    // @param addr The address causing a bad heap access.
 194    :    // @param header The header of the block containing this address.
 195    :    BadAccessKind GetBadAccessKind(const void* addr, BlockHeader* header);
 196    :  
 197    :    // Calculates the underlying allocation size for a requested
 198    :    // allocation of @p bytes.
 199    :    static size_t GetAllocSize(size_t bytes);
 200    :  
 201    :    // Quarantines @p block and flushes quarantine overage.
 202    :    void QuarantineBlock(BlockHeader* block);
 203    :  
 204    :    // Free and remove the first block of the quarantine. lock_ must be held.
 205    :    void PopQuarantineUnlocked();
 206    :  
 207    :    // Get the information about an address belonging to a memory block. This
 208    :    // function will output the relative position of this address inside a block
 209    :    // and the bounds of this block.
 210    :    // @param addr The address for which we want information.
 211    :    // @param header The block containing the address.
 212    :    // @param bad_access_kind The kind of bad access corresponding to this
 213    :    //     address.
 214    :    void ReportAddressInformation(const void* addr,
 215    :                                  BlockHeader* header,
 216    :                                  BadAccessKind bad_access_kind);
 217    :  
 218    :    // Low-level ASAN reporting function. This function dumps the stack,
 219    :    // optionally including an extra (free-form) description of the address
 220    :    // being accessed when the error occurred.
 221    :    // @param bug_descr The description of the error.
 222    :    // @param addr The address causing an error.
 223    :    // @param context The context at which the access occurred.
 224    :    // @param stack The stack capture at the point of error.
 225    :    // @param bad_access_kind The kind of error.
 226    :    // @param access_mode The mode of the access (read or write).
 227    :    // @param access_size The size of the access (in bytes).
 228    :    void ReportAsanErrorBase(const char* bug_descr,
 229    :                             const void* addr,
 230    :                             const CONTEXT& context,
 231    :                             const StackCapture& stack,
 232    :                             BadAccessKind bad_access_kind,
 233    :                             AccessMode access_mode,
 234    :                             size_t access_size);
 235    :  
 236    :    // Report an ASAN error, automatically including information about the
 237    :    // address being accessed when the error occurred.
 238    :    // @param bug_descr The description of the error.
 239    :    // @param addr The address causing an error.
 240    :    // @param context The context at which the access occurred.
 241    :    // @param stack The stack capture at the point of error.
 242    :    // @param bad_access_kind The kind of error.
 243    :    // @param header The header of the block containing this address.
 244    :    // @param access_mode The kind of the access (read or write).
 245    :    // @param access_size The size of the access (in bytes).
 246    :    void ReportAsanError(const char* bug_descr,
 247    :                         const void* addr,
 248    :                         const CONTEXT& context,
 249    :                         const StackCapture& stack,
 250    :                         BadAccessKind bad_access_kind,
 251    :                         BlockHeader* header,
 252    :                         AccessMode access_mode,
 253    :                         size_t access_size);
 254    :  
 255    :    // Default max size of blocks in quarantine (in bytes).
 256    :    static size_t default_quarantine_max_size_;
 257    :  
 258    :    // The underlying heap we delegate to.
 259    :    HANDLE heap_;
 260    :  
 261    :    // A repository of unique stack captures recorded on alloc and free.
 262    :    StackCaptureCache* const stack_cache_;
 263    :  
 264    :    // The logger to use when an error occurs.
 265    :    AsanLogger* const logger_;
 266    :  
 267    :    // Protects concurrent access to HeapProxy internals.
 268    :    base::Lock lock_;
 269    :  
 270    :    // Points to the head of the quarantine queue.
 271    :    FreeBlockHeader* head_;  // Under lock_.
 272    :  
 273    :    // Points to the tail of the quarantine queue.
 274    :    FreeBlockHeader* tail_;  // Under lock_.
 275    :  
 276    :    // Total size of blocks in quarantine.
 277    :    size_t quarantine_size_;  // Under lock_.
 278    :  
 279    :    // Max size of blocks in quarantine.
 280    :    size_t quarantine_max_size_;  // Under lock_.
 281    :  
 282    :    // The entry linking to us.
 283    :    LIST_ENTRY list_entry_;
 284    :  };
 285    :  
 286    :  }  // namespace asan
 287    :  }  // namespace agent
 288    :  
 289    :  #endif  // SYZYGY_AGENT_ASAN_ASAN_HEAP_H_

Coverage information generated Thu Mar 14 11:53:36 2013.