1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // Static class for hooking Win32 API routines. For now, 6 // we only add one watcher at a time. 7 // 8 // TODO(mbelshe): Support multiple watchers. 9 10 #ifndef MEMORY_WATCHER_MEMORY_HOOK_ 11 #define MEMORY_WATCHER_MEMORY_HOOK_ 12 13 #include "base/logging.h" 14 15 // When allocating memory for internal use with the MemoryHook, 16 // we must always use the MemoryHook's heap; otherwise, the memory 17 // gets tracked, and it becomes an infinite loop (allocation() calls 18 // MemoryHook() which calls allocation(), etc). 19 // 20 // PrivateHookAllocator is an STL-friendly Allocator so that STL lists, 21 // maps, etc can be used on the global MemoryHook's heap. 22 template <class T> 23 class PrivateHookAllocator { 24 public: 25 // These type definitions are needed for stl allocators. 26 typedef size_t size_type; 27 typedef ptrdiff_t difference_type; 28 typedef T* pointer; 29 typedef const T* const_pointer; 30 typedef T& reference; 31 typedef const T& const_reference; 32 typedef T value_type; 33 PrivateHookAllocator()34 PrivateHookAllocator() {} 35 36 // Allocate memory for STL. 37 pointer allocate(size_type n, const void * = 0) { 38 return reinterpret_cast<T*>(MemoryHook::Alloc(n * sizeof(T))); 39 } 40 41 // Deallocate memory for STL. deallocate(void * p,size_type)42 void deallocate(void* p, size_type) { 43 if (p) 44 MemoryHook::Free(p); 45 } 46 47 // Construct the object construct(pointer p,const T & val)48 void construct(pointer p, const T& val) { 49 new (reinterpret_cast<T*>(p))T(val); 50 } 51 52 // Destruct an object destroy(pointer p)53 void destroy(pointer p) { p->~T(); } 54 max_size()55 size_type max_size() const { return size_t(-1); } 56 57 template <class U> 58 struct rebind { typedef PrivateHookAllocator<U> other; }; 59 60 template <class U> PrivateHookAllocator(const PrivateHookAllocator<U> &)61 PrivateHookAllocator(const PrivateHookAllocator<U>&) {} 62 }; 63 64 template<class T, class U> inline 65 bool operator==(const PrivateHookAllocator<T>&, 66 const PrivateHookAllocator<U>&) { 67 return (true); 68 } 69 70 template<class T, class U> inline 71 bool operator!=(const PrivateHookAllocator<T>& left, 72 const PrivateHookAllocator<U>& right) { 73 return (!(left == right)); 74 } 75 76 77 // Classes which monitor memory from these hooks implement 78 // the MemoryObserver interface. 79 class MemoryObserver { 80 public: ~MemoryObserver()81 virtual ~MemoryObserver() {} 82 83 // Track a pointer. Will capture the current StackTrace. 84 virtual void OnTrack(HANDLE heap, int32 id, int32 size) = 0; 85 86 // Untrack a pointer, removing it from our list. 87 virtual void OnUntrack(HANDLE heap, int32 id, int32 size) = 0; 88 }; 89 90 class MemoryHook : MemoryObserver { 91 public: 92 // Initialize the MemoryHook. Must be called before 93 // registering watchers. This can be called repeatedly, 94 // but is not thread safe. 95 static bool Initialize(); 96 97 // Returns true is memory allocations and deallocations 98 // are being traced. hooked()99 static bool hooked() { return hooked_ != NULL; } 100 101 // Register a class to receive memory allocation & deallocation 102 // callbacks. If we haven't hooked memory yet, this call will 103 // force memory hooking to start. 104 static bool RegisterWatcher(MemoryObserver* watcher); 105 106 // Register a class to stop receiving callbacks. If there are 107 // no more watchers, this call will unhook memory. 108 static bool UnregisterWatcher(MemoryObserver* watcher); 109 110 // MemoryHook provides a private heap for allocating 111 // unwatched memory. Alloc(size_t size)112 static void* Alloc(size_t size) { 113 DCHECK(global_hook_ && global_hook_->heap_); 114 return HeapAlloc(global_hook_->heap_, 0, size); 115 } Free(void * ptr)116 static void Free(void* ptr) { 117 DCHECK(global_hook_ && global_hook_->heap_); 118 HeapFree(global_hook_->heap_, 0, ptr); 119 } 120 121 // Access the global hook. For internal use only from static "C" 122 // hooks. hook()123 static MemoryHook* hook() { return global_hook_; } 124 125 // MemoryObserver interface. 126 virtual void OnTrack(HANDLE hHeap, int32 id, int32 size); 127 virtual void OnUntrack(HANDLE hHeap, int32 id, int32 size); 128 129 private: 130 MemoryHook(); 131 ~MemoryHook(); 132 133 // Enable memory tracing. When memory is 'hooked', 134 // MemoryWatchers which have registered will be called 135 // as memory is allocated and deallocated. 136 static bool Hook(); 137 138 // Disables memory tracing. 139 static bool Unhook(); 140 141 // Create our private heap 142 bool CreateHeap(); 143 144 // Close our private heap. 145 bool CloseHeap(); 146 147 MemoryObserver* watcher_; 148 HANDLE heap_; // An internal accounting heap. 149 static bool hooked_; 150 static MemoryHook* global_hook_; 151 }; 152 153 #endif // MEMORY_WATCHER_MEMORY_HOOK_ 154