OLD | NEW |
| (Empty) |
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 | |
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. | |
42 void deallocate(void* p, size_type) { | |
43 if (p) | |
44 MemoryHook::Free(p); | |
45 } | |
46 | |
47 // Construct the object | |
48 void construct(pointer p, const T& val) { | |
49 new (reinterpret_cast<T*>(p))T(val); | |
50 } | |
51 | |
52 // Destruct an object | |
53 void destroy(pointer p) { p->~T(); } | |
54 | |
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> | |
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: | |
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. | |
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. | |
112 static void* Alloc(size_t size) { | |
113 DCHECK(global_hook_ && global_hook_->heap_); | |
114 return HeapAlloc(global_hook_->heap_, 0, size); | |
115 } | |
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. | |
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_ | |
OLD | NEW |