[176] | 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 | } |
---|