source: proiecte/swift/trunk/lib/hoard-371/src/hoarddetours.cpp @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 8.6 KB
Line 
1/**
2 * @file hoarddetours.cpp
3 * @brief Hooks to Hoard for Detours.
4 * @author Emery Berger <http://www.cs.umass.edu/~emery>
5 */
6
7/*
8   To compile, run compile-detours.cmd, or do the following:
9
10   cl /I.. /LD /MD /DNDEBUG /Ox /Zp8 /Oa /G6 /Oy /I/detours/include hoarddetours.cpp  \detours\lib\detours.lib /link /subsystem:console /entry:_DllMainCRTStartup@12 /force:multiple
11
12   To use (via withdll.exe, from Detours):
13
14   detours\withdll -d:hoarddetours.dll myexecutable.exe
15
16  */
17
18#include "VERSION.h"
19
20#define CUSTOM_PREFIX(n) hoard##n
21
22#if !defined(_WIN32)
23#error "This file is for Windows only."
24#endif
25
26#define WIN32_LEAN_AND_MEAN
27#define _WIN32_WINNT 0x0500
28#define NT
29
30#include <windows.h>
31#include <stdio.h>
32#include <malloc.h>
33#include "detours.h"
34
35#if defined(_WIN32)
36#pragma inline_depth(255)
37#endif
38
39#include "cpuinfo.h"
40#include "hoard.h"
41
42volatile int anyThreadCreated = 0;
43
44const int MaxThreads = 512;
45const int NumHeaps = 64;
46
47using namespace Hoard;
48
49class TheCustomHeapType : public HoardHeap<MaxThreads, NumHeaps> {};
50
51inline static TheCustomHeapType * getCustomHeap (void) {
52  static char thBuf[sizeof(TheCustomHeapType)];
53  static TheCustomHeapType * th = new (thBuf) TheCustomHeapType;
54  return th;
55}
56
57// Allocate exactly one object.
58static void * objectAllocated = (void *) 0x1;
59
60extern "C" {
61  DETOUR_TRAMPOLINE(void __cdecl real_onexit (void (*f)(void)),
62                    onexit);
63
64  DETOUR_TRAMPOLINE(void __cdecl real_exit (int code),
65                    exit);
66
67  DETOUR_TRAMPOLINE(void *  __cdecl real_malloc (size_t sz),
68                    malloc);
69 
70  DETOUR_TRAMPOLINE(void *  __cdecl real_realloc (void * ptr, size_t sz),
71                    realloc);
72 
73  DETOUR_TRAMPOLINE(void *  __cdecl real_calloc (size_t sz, size_t n),
74                    calloc);
75 
76  DETOUR_TRAMPOLINE(void *  __cdecl real_free (void * ptr),
77                    free);
78 
79  DETOUR_TRAMPOLINE(size_t  __cdecl real_msize (void * ptr),
80                    _msize);
81
82  DETOUR_TRAMPOLINE(void * __cdecl real_expand(void * memblock, size_t size),
83                    _expand);
84
85  DETOUR_TRAMPOLINE(char *  __cdecl real_strdup (const char * s),
86                    strdup);
87
88}
89
90/* Detours */
91
92#include "wrapper.cpp"
93
94// We use Hoard to manage small objects and the original allocator
95// to manage large objects.
96
97static const int HOARD_MAX_EXIT_FUNCTIONS = 512;
98static int exitCount = 0;
99
100typedef void (*exitFunctionType) (void);
101exitFunctionType exitFunctionBuffer[HOARD_MAX_EXIT_FUNCTIONS];
102
103extern "C" void my_onexit (void (*function)(void)) {
104  if (exitCount < HOARD_MAX_EXIT_FUNCTIONS) {
105    exitFunctionBuffer[exitCount] = function;
106    exitCount++;
107  }
108}
109
110extern "C" void my_exit (int code) {
111  while (exitCount > 0) {
112    exitCount--;
113    (exitFunctionBuffer[exitCount])();
114  }
115  real_exit (code);
116}
117
118extern "C" void my_cexit (void) {
119  my_exit (0);
120}
121
122extern "C" void * my_expand (void * memblock, size_t size)
123{
124  // Disable by always returning NULL (the error condition for _expand).
125  return NULL;
126}
127
128
129/* Install Detours trampolines. */
130
131#define REPLACE(module,x,fn) \
132{ \
133  PBYTE p; \
134  p = DetourFindFunction ((module), (x)); \
135  if (p) { \
136    DetourFunction (p, (PBYTE) (fn));  \
137  } \
138}
139
140#define REMOVE(module,x,fn) \
141{ \
142  PBYTE p; \
143  p = DetourFindFunction ((module), (x)); \
144  if (p) { \
145    DetourRemove (p, (PBYTE) (fn));  \
146  } \
147}
148
149
150void trampolineInstall (HMODULE hModule,
151                        bool insert)
152{
153  typedef PBYTE (__stdcall *drtype)(PBYTE, PBYTE);
154  typedef BOOL (__stdcall *dfwtype)(PBYTE, PBYTE);
155  PBYTE p;
156  drtype dr;
157  dfwtype dfw;
158
159  if (insert) {
160    dfw = &DetourFunctionWithTrampoline;
161    dr = &DetourFunction;
162  } else {
163    dfw = &DetourRemove;
164    dr = (drtype) &DetourRemove;
165  }
166
167  (*dfw) ((PBYTE) real_realloc, (PBYTE) CUSTOM_PREFIX(realloc));
168  (*dfw) ((PBYTE) real_calloc,  (PBYTE) CUSTOM_PREFIX(calloc));
169  (*dfw) ((PBYTE) real_msize,   (PBYTE) CUSTOM_PREFIX(malloc_usable_size));
170  (*dfw) ((PBYTE) real_strdup,  (PBYTE) CUSTOM_PREFIX(strdup));
171  (*dfw) ((PBYTE) real_malloc,  (PBYTE) CUSTOM_PREFIX(malloc));
172  (*dfw) ((PBYTE) real_free,    (PBYTE) CUSTOM_PREFIX(free));
173  (*dfw) ((PBYTE) real_expand,  (PBYTE) my_expand);
174  (*dfw) ((PBYTE) real_onexit,  (PBYTE) my_onexit);
175  (*dfw) ((PBYTE) real_exit,  (PBYTE) my_exit);
176
177  char dllName[MAX_PATH];
178
179  for (HINSTANCE hInst = NULL; (hInst = DetourEnumerateModules(hInst)) != NULL; ) {
180    GetModuleFileName(hInst, dllName, MAX_PATH);
181
182    // Replace the memory allocation calls in the MSVCR library.
183   
184    if ((strstr(dllName, "MSVCR") != 0) || (strstr(dllName, "msvcr") != 0)) {
185
186      // operator new, new[], delete, delete[]
187      // see undname
188
189      // operator new
190      p = DetourFindFunction (dllName, "??2@YAPAXI@Z");
191      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(malloc));
192
193      // operator new[]
194      p = DetourFindFunction (dllName, "??_U@YAPAXI@Z");
195      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(malloc));
196     
197      // operator delete
198      p = DetourFindFunction (dllName, "??3@YAXPAX@Z");
199      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(free));
200
201      // operator delete[]
202      p = DetourFindFunction (dllName, "??_V@YAXPAX@Z");
203      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(free));
204
205      p = DetourFindFunction (dllName, "realloc");
206      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(realloc));
207     
208      p = DetourFindFunction (dllName, "calloc");
209      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(calloc));
210     
211      p = DetourFindFunction (dllName, "_msize");
212      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(malloc_usable_size));
213     
214      p = DetourFindFunction (dllName, "strdup");
215      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(strdup));
216     
217      p = DetourFindFunction (dllName, "malloc");
218      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(malloc));
219     
220      p = DetourFindFunction (dllName, "free");
221      if (p) (*dr)(p, (PBYTE) CUSTOM_PREFIX(free));
222     
223      p = DetourFindFunction (dllName, "_expand");
224      if (p) (*dr)(p, (PBYTE) my_expand);
225
226      p = DetourFindFunction (dllName, "_onexit");
227      if (p) (*dr)(p, (PBYTE) my_onexit);
228
229      p = DetourFindFunction (dllName, "exit");
230      if (p) (*dr)(p, (PBYTE) my_exit);
231
232      p = DetourFindFunction (dllName, "_cexit");
233      if (p) (*dr)(p, (PBYTE) my_cexit);
234    }
235  }
236}
237
238void trampolineWith (HMODULE hModule) {
239  trampolineInstall (hModule, true);
240}
241
242
243#if defined(_WIN32)
244#pragma warning(disable:4273)
245#endif
246
247static void initializeMaps (void) {
248  int i;
249  for (i = 0; i < TheCustomHeapType::MaxThreads; i++) {
250    getCustomHeap()->setTidMap(i, 0);
251  }
252  for (i = 0; i < TheCustomHeapType::MaxHeaps; i++) {
253    getCustomHeap()->setInusemap (i, 0);
254  }
255}
256
257static void findUnusedHeap (void) {
258  // Find an unused heap.
259 
260  int tid = HL::CPUInfo::getThreadId() % TheCustomHeapType::MaxThreads;
261
262  int i = 0;
263  while ((i < TheCustomHeapType::MaxHeaps) && (getCustomHeap()->getInusemap(i)))
264    i++;
265  if (i >= TheCustomHeapType::MaxHeaps) {
266    // Every heap is in use: pick a random victim.
267    i = (int) ( TheCustomHeapType::MaxHeaps * ((double) rand() / (double) RAND_MAX));
268  }
269  int v = getCustomHeap()->getInusemap(i);
270
271  getCustomHeap()->setInusemap (i, 1);
272  getCustomHeap()->setTidMap (tid, i);
273}
274
275static void releaseHeap (void) {
276  // Decrement the ref-count on the current heap.
277
278  enum { VerifyPowerOfTwo = 1 / ((TheCustomHeapType::MaxThreads & ~(TheCustomHeapType::MaxThreads-1))) };
279
280  int tid = HL::CPUInfo::getThreadId() & (TheCustomHeapType::MaxThreads - 1);
281  int heapIndex = getCustomHeap()->getTidMap (tid);
282
283  //  printf ("thread %d releasing heap %d\n", tid, heapIndex);
284 
285  int v = getCustomHeap()->getInusemap (heapIndex);
286  getCustomHeap()->setInusemap (heapIndex, 0);
287
288  // Prevent underruns (defensive programming).
289
290  if (getCustomHeap()->getInusemap (heapIndex) < 0) {
291    getCustomHeap()->setInusemap (heapIndex, 0);
292  }
293}
294
295
296BOOL APIENTRY DllMain (HINSTANCE hModule,
297                       DWORD dwReason,
298                       PVOID lpReserved)
299{
300  int i;
301  int tid;
302  static int np = HL::CPUInfo::computeNumProcessors();
303  char dllName[MAX_PATH];
304  switch (dwReason) {
305  case DLL_PROCESS_ATTACH:
306    fprintf (stderr, "This software uses the Hoard scalable memory allocator (version " HOARD_VERSION_STRING ", Detours).\nCopyright (C) 2005 Emery Berger, The University of Texas at Austin,\nand the University of Massachusetts Amherst.\nFor more information, see http://www.hoard.org\n");
307    initializeMaps();
308    trampolineWith (hModule);
309    break;
310  case DLL_PROCESS_DETACH:
311    // Notice that we haven't replaced all heap calls. Here's one.
312    objectAllocated = (void *) real_malloc(1);
313    break;
314  case DLL_THREAD_ATTACH:
315    anyThreadCreated = 1;
316    if (np == 1) {
317      getCustomHeap()->setTidMap ((int) HL::CPUInfo::getThreadId() % TheCustomHeapType::MaxThreads, 0);
318    } else {
319      findUnusedHeap();
320    }
321    break;
322  case DLL_THREAD_DETACH:
323    if (np != 1) {
324      releaseHeap();
325    }
326    break;
327  }
328  return TRUE;
329}
330
331
Note: See TracBrowser for help on using the repository browser.