1 | /* -*- C++ -*- */ |
---|
2 | |
---|
3 | /* |
---|
4 | The Hoard Multiprocessor Memory Allocator |
---|
5 | www.hoard.org |
---|
6 | |
---|
7 | Author: Emery Berger, http://www.cs.umass.edu/~emery |
---|
8 | |
---|
9 | Copyright (c) 1998-2006 Emery Berger, The University of Texas at Austin |
---|
10 | |
---|
11 | This program is free software; you can redistribute it and/or modify |
---|
12 | it under the terms of the GNU General Public License as published by |
---|
13 | the Free Software Foundation; either version 2 of the License, or |
---|
14 | (at your option) any later version. |
---|
15 | |
---|
16 | This program is distributed in the hope that it will be useful, |
---|
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | GNU General Public License for more details. |
---|
20 | |
---|
21 | You should have received a copy of the GNU General Public License |
---|
22 | along with this program; if not, write to the Free Software |
---|
23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
24 | |
---|
25 | */ |
---|
26 | |
---|
27 | #ifdef _DEBUG |
---|
28 | #error "This library must be compiled in release mode." |
---|
29 | #endif |
---|
30 | |
---|
31 | /* |
---|
32 | |
---|
33 | Compile with compile-winhoard.cmd. |
---|
34 | |
---|
35 | */ |
---|
36 | |
---|
37 | |
---|
38 | #include <windows.h> |
---|
39 | |
---|
40 | #define WIN32_LEAN_AND_MEAN |
---|
41 | |
---|
42 | #if (_WIN32_WINNT < 0x0500) |
---|
43 | #define _WIN32_WINNT 0x0500 |
---|
44 | #endif |
---|
45 | |
---|
46 | #pragma inline_depth(255) |
---|
47 | |
---|
48 | #pragma warning(disable: 4273) |
---|
49 | #pragma warning(disable: 4098) // Library conflict. |
---|
50 | #pragma warning(disable: 4355) // 'this' used in base member initializer list. |
---|
51 | #pragma warning(disable: 4074) // initializers put in compiler reserved area. |
---|
52 | |
---|
53 | void (*hoard_memcpy_ptr)(void *dest, const void *src, size_t count); |
---|
54 | void (*hoard_memset_ptr)(void *dest, int c, size_t count); |
---|
55 | |
---|
56 | const char *RlsCRTLibraryName[] = {"MSVCR71.DLL", "MSVCR80.DLL", "MSVCR90.DLL" }; |
---|
57 | const int RlsCRTLibraryNameLength = 3; |
---|
58 | |
---|
59 | #define IAX86_NEARJMP_OPCODE 0xe9 |
---|
60 | #define MakeIAX86Offset(to,from) ((unsigned)((char*)(to)-(char*)(from)) - 5) |
---|
61 | |
---|
62 | typedef struct |
---|
63 | { |
---|
64 | const char *import; // import name of patch routine |
---|
65 | FARPROC replacement; // pointer to replacement function |
---|
66 | FARPROC original; // pointer to original function |
---|
67 | unsigned char codebytes[5]; // 5 bytes of original code storage |
---|
68 | } PATCH; |
---|
69 | |
---|
70 | |
---|
71 | static bool PatchMeIn (void); |
---|
72 | |
---|
73 | #define CUSTOM_PREFIX(n) hoard_##n |
---|
74 | #define HOARD_PRE_ACTION {PatchMeIn();} |
---|
75 | #define HOARD_POST_ACTION {HeapAlloc (GetProcessHeap(), 0, 1); } |
---|
76 | |
---|
77 | // DisableThreadLibraryCalls ((HMODULE)hinstDLL); |
---|
78 | |
---|
79 | #define CUSTOM_DLLNAME HoardDllMain |
---|
80 | |
---|
81 | #include "libhoard.cpp" |
---|
82 | |
---|
83 | // Intercept the exit functions. |
---|
84 | |
---|
85 | static const int HOARD_MAX_EXIT_FUNCTIONS = 255; |
---|
86 | static int exitCount = 0; |
---|
87 | |
---|
88 | extern "C" { |
---|
89 | |
---|
90 | __declspec(dllexport) int ReferenceHoardStub; |
---|
91 | |
---|
92 | typedef void (*exitFunctionType) (void); |
---|
93 | exitFunctionType exitFunctionBuffer[255]; |
---|
94 | |
---|
95 | void hoard_onexit (void (*function)(void)) { |
---|
96 | if (exitCount < HOARD_MAX_EXIT_FUNCTIONS) { |
---|
97 | exitFunctionBuffer[exitCount] = function; |
---|
98 | exitCount++; |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | void hoard_exit (int code) { |
---|
103 | while (exitCount > 0) { |
---|
104 | exitCount--; |
---|
105 | (exitFunctionBuffer[exitCount])(); |
---|
106 | } |
---|
107 | } |
---|
108 | |
---|
109 | void * hoard_expand (void * ptr) { |
---|
110 | return NULL; |
---|
111 | } |
---|
112 | |
---|
113 | } |
---|
114 | |
---|
115 | |
---|
116 | /* ------------------------------------------------------------------------ */ |
---|
117 | |
---|
118 | static PATCH rls_patches[] = |
---|
119 | { |
---|
120 | // RELEASE CRT library routines supported by this memory manager. |
---|
121 | |
---|
122 | {"_expand", (FARPROC) hoard_expand, 0}, |
---|
123 | {"_onexit", (FARPROC) hoard_onexit, 0}, |
---|
124 | {"_exit", (FARPROC) hoard_exit, 0}, |
---|
125 | |
---|
126 | // operator new, new[], delete, delete[]. |
---|
127 | |
---|
128 | #ifdef _WIN64 |
---|
129 | |
---|
130 | {"??2@YAPEAX_K@Z", (FARPROC) hoard_malloc, 0}, |
---|
131 | {"??_U@YAPEAX_K@Z", (FARPROC) hoard_malloc, 0}, |
---|
132 | {"??3@YAXPEAX@Z", (FARPROC) hoard_free, 0}, |
---|
133 | {"??_V@YAXPEAX@Z", (FARPROC) hoard_free, 0}, |
---|
134 | |
---|
135 | #else |
---|
136 | |
---|
137 | {"??2@YAPAXI@Z", (FARPROC) hoard_malloc, 0}, |
---|
138 | {"??_U@YAPAXI@Z", (FARPROC) hoard_malloc, 0}, |
---|
139 | {"??3@YAXPAX@Z", (FARPROC) hoard_free, 0}, |
---|
140 | {"??_V@YAXPAX@Z", (FARPROC) hoard_free, 0}, |
---|
141 | |
---|
142 | #endif |
---|
143 | |
---|
144 | // the nothrow variants new, new[]. |
---|
145 | |
---|
146 | {"??2@YAPAXIABUnothrow_t@std@@@Z", (FARPROC) hoard_malloc, 0}, |
---|
147 | {"??_U@YAPAXIABUnothrow_t@std@@@Z", (FARPROC) hoard_malloc, 0}, |
---|
148 | |
---|
149 | {"_msize", (FARPROC) hoard_malloc_usable_size, 0}, |
---|
150 | {"calloc", (FARPROC) hoard_calloc, 0}, |
---|
151 | {"malloc", (FARPROC) hoard_malloc, 0}, |
---|
152 | {"realloc", (FARPROC) hoard_realloc, 0}, |
---|
153 | {"free", (FARPROC) hoard_free, 0}, |
---|
154 | }; |
---|
155 | |
---|
156 | |
---|
157 | static void PatchIt (PATCH *patch) |
---|
158 | { |
---|
159 | // Change rights on CRT Library module to execute/read/write. |
---|
160 | |
---|
161 | MEMORY_BASIC_INFORMATION mbi_thunk; |
---|
162 | VirtualQuery((void*)patch->original, &mbi_thunk, |
---|
163 | sizeof(MEMORY_BASIC_INFORMATION)); |
---|
164 | VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, |
---|
165 | PAGE_EXECUTE_READWRITE, &mbi_thunk.Protect); |
---|
166 | |
---|
167 | // Patch CRT library original routine: |
---|
168 | // save original 5 code bytes for exit restoration |
---|
169 | // write jmp <patch_routine> (5 bytes long) to original. |
---|
170 | |
---|
171 | memcpy(patch->codebytes, patch->original, sizeof(patch->codebytes)); |
---|
172 | unsigned char *patchloc = (unsigned char*)patch->original; |
---|
173 | *patchloc++ = IAX86_NEARJMP_OPCODE; |
---|
174 | *(unsigned*)patchloc = MakeIAX86Offset(patch->replacement, patch->original); |
---|
175 | |
---|
176 | // Reset CRT library code to original page protection. |
---|
177 | |
---|
178 | VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, |
---|
179 | mbi_thunk.Protect, &mbi_thunk.Protect); |
---|
180 | } |
---|
181 | |
---|
182 | |
---|
183 | static bool PatchMeIn (void) |
---|
184 | { |
---|
185 | bool patchedIn = false; |
---|
186 | |
---|
187 | // acquire the module handles for the CRT libraries (release and debug) |
---|
188 | for (int i = 0; i < RlsCRTLibraryNameLength; i++) { |
---|
189 | |
---|
190 | HMODULE RlsCRTLibrary = GetModuleHandle(RlsCRTLibraryName[i]); |
---|
191 | |
---|
192 | HMODULE DefCRTLibrary = |
---|
193 | RlsCRTLibrary; |
---|
194 | |
---|
195 | // assign function pointers for required CRT support functions |
---|
196 | if (DefCRTLibrary) { |
---|
197 | hoard_memcpy_ptr = (void(*)(void*,const void*,size_t)) |
---|
198 | GetProcAddress(DefCRTLibrary, "memcpy"); |
---|
199 | hoard_memset_ptr = (void(*)(void*,int,size_t)) |
---|
200 | GetProcAddress(DefCRTLibrary, "memset"); |
---|
201 | } |
---|
202 | |
---|
203 | // patch all relevant Release CRT Library entry points |
---|
204 | if (RlsCRTLibrary) { |
---|
205 | for (int i = 0; i < sizeof(rls_patches) / sizeof(*rls_patches); i++) { |
---|
206 | if (rls_patches[i].original = GetProcAddress(RlsCRTLibrary, rls_patches[i].import)) { |
---|
207 | PatchIt(&rls_patches[i]); |
---|
208 | patchedIn = true; |
---|
209 | } |
---|
210 | } |
---|
211 | } |
---|
212 | } |
---|
213 | return patchedIn; |
---|
214 | } |
---|