| OLD | NEW |
| 1 // Copyright (c) 2007, Google Inc. | 1 // Copyright (c) 2007, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 #ifndef _WIN32 | 65 #ifndef _WIN32 |
| 66 # error You should only be including windows/patch_functions.cc in a windows env
ironment! | 66 # error You should only be including windows/patch_functions.cc in a windows env
ironment! |
| 67 #endif | 67 #endif |
| 68 | 68 |
| 69 #include <config.h> | 69 #include <config.h> |
| 70 | 70 |
| 71 #ifdef WIN32_OVERRIDE_ALLOCATORS | 71 #ifdef WIN32_OVERRIDE_ALLOCATORS |
| 72 #error This file is intended for patching allocators - use override_functions.cc
instead. | 72 #error This file is intended for patching allocators - use override_functions.cc
instead. |
| 73 #endif | 73 #endif |
| 74 | 74 |
| 75 // We use psapi. Non-MSVC systems will have to link this in themselves. |
| 76 #ifdef _MSC_VER |
| 77 #pragma comment(lib, "Psapi.lib") |
| 78 #endif |
| 79 |
| 80 // Make sure we always use the 'old' names of the psapi functions. |
| 81 #ifndef PSAPI_VERSION |
| 82 #define PSAPI_VERSION 1 |
| 83 #endif |
| 84 |
| 75 #include <windows.h> | 85 #include <windows.h> |
| 76 #include <malloc.h> // for _msize and _expand | 86 #include <malloc.h> // for _msize and _expand |
| 77 #include <tlhelp32.h> // for CreateToolhelp32Snapshot() | 87 #include <Psapi.h> // for EnumProcessModules, GetModuleInformation, etc. |
| 88 #include <set> |
| 89 #include <map> |
| 78 #include <vector> | 90 #include <vector> |
| 79 #include <base/logging.h> | 91 #include <base/logging.h> |
| 80 #include "base/spinlock.h" | 92 #include "base/spinlock.h" |
| 81 #include "google/malloc_hook.h" | 93 #include "google/malloc_hook.h" |
| 82 #include "malloc_hook-inl.h" | 94 #include "malloc_hook-inl.h" |
| 83 #include "preamble_patcher.h" | 95 #include "preamble_patcher.h" |
| 84 | 96 |
| 85 // MinGW doesn't seem to define this, perhaps some windowsen don't either. | 97 // The maximum number of modules we allow to be in one executable |
| 86 #ifndef TH32CS_SNAPMODULE32 | 98 const int kMaxModules = 8182; |
| 87 #define TH32CS_SNAPMODULE32 0 | 99 // The maximum size of a module's basename |
| 88 #endif | 100 const int kMaxModuleNameSize = 256; |
| 89 | 101 |
| 90 // These are hard-coded, unfortunately. :-( They are also probably | 102 // These are hard-coded, unfortunately. :-( They are also probably |
| 91 // compiler specific. See get_mangled_names.cc, in this directory, | 103 // compiler specific. See get_mangled_names.cc, in this directory, |
| 92 // for instructions on how to update these names for your compiler. | 104 // for instructions on how to update these names for your compiler. |
| 93 const char kMangledNew[] = "??2@YAPAXI@Z"; | 105 const char kMangledNew[] = "??2@YAPAXI@Z"; |
| 94 const char kMangledNewArray[] = "??_U@YAPAXI@Z"; | 106 const char kMangledNewArray[] = "??_U@YAPAXI@Z"; |
| 95 const char kMangledDelete[] = "??3@YAXPAX@Z"; | 107 const char kMangledDelete[] = "??3@YAXPAX@Z"; |
| 96 const char kMangledDeleteArray[] = "??_V@YAXPAX@Z"; | 108 const char kMangledDeleteArray[] = "??_V@YAXPAX@Z"; |
| 97 const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z"; | 109 const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z"; |
| 98 const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z"; | 110 const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 110 // the symbol "__tcmalloc".) | 122 // the symbol "__tcmalloc".) |
| 111 extern "C" PERFTOOLS_DLL_DECL void _tcmalloc(); | 123 extern "C" PERFTOOLS_DLL_DECL void _tcmalloc(); |
| 112 void _tcmalloc() { } | 124 void _tcmalloc() { } |
| 113 | 125 |
| 114 namespace { // most everything here is in an unnamed namespace | 126 namespace { // most everything here is in an unnamed namespace |
| 115 | 127 |
| 116 typedef void (*GenericFnPtr)(); | 128 typedef void (*GenericFnPtr)(); |
| 117 | 129 |
| 118 using sidestep::PreamblePatcher; | 130 using sidestep::PreamblePatcher; |
| 119 | 131 |
| 132 struct ModuleEntryCopy; // defined below |
| 133 |
| 120 // These functions are how we override the memory allocation | 134 // These functions are how we override the memory allocation |
| 121 // functions, just like tcmalloc.cc and malloc_hook.cc do. | 135 // functions, just like tcmalloc.cc and malloc_hook.cc do. |
| 122 | 136 |
| 123 // This is information about the routines we're patching, for a given | 137 // This is information about the routines we're patching, for a given |
| 124 // module that implements libc memory routines. A single executable | 138 // module that implements libc memory routines. A single executable |
| 125 // can have several libc implementations running about (in different | 139 // can have several libc implementations running about (in different |
| 126 // .dll's), and we need to patch/unpatch them all. This defines | 140 // .dll's), and we need to patch/unpatch them all. This defines |
| 127 // everything except the new functions we're patching in, which | 141 // everything except the new functions we're patching in, which |
| 128 // are defined in LibcFunctions, below. | 142 // are defined in LibcFunctions, below. |
| 129 class LibcInfo { | 143 class LibcInfo { |
| 130 public: | 144 public: |
| 131 LibcInfo() { | 145 LibcInfo() { |
| 132 memset(this, 0, sizeof(*this)); // easiest way to initialize the array | 146 memset(this, 0, sizeof(*this)); // easiest way to initialize the array |
| 133 } | 147 } |
| 134 bool SameAs(const LibcInfo& that) const { | 148 bool SameAs(const LibcInfo& that) const; |
| 135 return (is_valid() && | 149 bool SameAsModuleEntry(const ModuleEntryCopy& module_entry) const; |
| 136 module_base_address_ == that.module_base_address_ && | 150 |
| 137 module_base_size_ == that.module_base_size_); | |
| 138 } | |
| 139 bool SameAsME32(const MODULEENTRY32& me32) const { | |
| 140 return (is_valid() && | |
| 141 module_base_address_ == me32.modBaseAddr && | |
| 142 module_base_size_ == me32.modBaseSize); | |
| 143 } | |
| 144 bool patched() const { return is_valid() && module_name_[0] != '\0'; } | 151 bool patched() const { return is_valid() && module_name_[0] != '\0'; } |
| 145 const char* module_name() const { return is_valid() ? module_name_ : ""; } | 152 const char* module_name() const { return is_valid() ? module_name_ : ""; } |
| 146 | 153 |
| 147 void set_is_valid(bool b) { is_valid_ = b; } | 154 void set_is_valid(bool b) { is_valid_ = b; } |
| 148 | 155 |
| 149 // These shouldn't have to be public, since only subclasses of | |
| 150 // LibcInfo need it, but they do. Maybe something to do with | |
| 151 // templates. Shrug. | |
| 152 bool is_valid() const { return is_valid_; } | |
| 153 GenericFnPtr windows_fn(int ifunction) const { | |
| 154 return windows_fn_[ifunction]; | |
| 155 } | |
| 156 | |
| 157 // Populates all the windows_fn_[] vars based on our module info. | 156 // Populates all the windows_fn_[] vars based on our module info. |
| 158 // Returns false if windows_fn_ is all NULL's, because there's | 157 // Returns false if windows_fn_ is all NULL's, because there's |
| 159 // nothing to patch. Also populates the me32 info. | 158 // nothing to patch. Also populates the rest of the module_entry |
| 160 bool PopulateWindowsFn(const MODULEENTRY32& me32); | 159 // info, such as the module's name. |
| 160 bool PopulateWindowsFn(const ModuleEntryCopy& module_entry); |
| 161 | 161 |
| 162 protected: | 162 protected: |
| 163 void CopyFrom(const LibcInfo& that) { | 163 void CopyFrom(const LibcInfo& that) { |
| 164 if (this == &that) | 164 if (this == &that) |
| 165 return; | 165 return; |
| 166 this->is_valid_ = that.is_valid_; | 166 this->is_valid_ = that.is_valid_; |
| 167 memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_)); | 167 memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_)); |
| 168 this->module_base_address_ = that.module_base_address_; | 168 this->module_base_address_ = that.module_base_address_; |
| 169 this->module_base_size_ = that.module_base_size_; | 169 this->module_base_size_ = that.module_base_size_; |
| 170 memcpy(this->module_name_, that.module_name_, sizeof(module_name_)); | 170 memcpy(this->module_name_, that.module_name_, sizeof(module_name_)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 200 // patch-specific subclasses, below. | 200 // patch-specific subclasses, below. |
| 201 GenericFnPtr windows_fn_[kNumFunctions]; | 201 GenericFnPtr windows_fn_[kNumFunctions]; |
| 202 | 202 |
| 203 // This is set to true when this structure is initialized (because | 203 // This is set to true when this structure is initialized (because |
| 204 // we're patching a new library) and set to false when it's | 204 // we're patching a new library) and set to false when it's |
| 205 // uninitialized (because we've freed that library). | 205 // uninitialized (because we've freed that library). |
| 206 bool is_valid_; | 206 bool is_valid_; |
| 207 | 207 |
| 208 const void *module_base_address_; | 208 const void *module_base_address_; |
| 209 size_t module_base_size_; | 209 size_t module_base_size_; |
| 210 char module_name_[MAX_MODULE_NAME32 + 1]; | 210 char module_name_[kMaxModuleNameSize]; |
| 211 |
| 212 public: |
| 213 // These shouldn't have to be public, since only subclasses of |
| 214 // LibcInfo need it, but they do. Maybe something to do with |
| 215 // templates. Shrug. I hide them down here so users won't see |
| 216 // them. :-) (OK, I also need to define ctrgProcAddress late.) |
| 217 bool is_valid() const { return is_valid_; } |
| 218 GenericFnPtr windows_fn(int ifunction) const { |
| 219 return windows_fn_[ifunction]; |
| 220 } |
| 221 // These three are needed by ModuleEntryCopy. |
| 222 static const int ctrgProcAddress = kNumFunctions; |
| 223 static GenericFnPtr static_fn(int ifunction) { |
| 224 return static_fn_[ifunction]; |
| 225 } |
| 226 static const char* const function_name(int ifunction) { |
| 227 return function_name_[ifunction]; |
| 228 } |
| 211 }; | 229 }; |
| 212 | 230 |
| 213 // Template trickiness: logically, a LibcInfo would include | 231 // Template trickiness: logically, a LibcInfo would include |
| 214 // Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a | 232 // Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a |
| 215 // given module, these three go together. And in fact, | 233 // given module, these three go together. And in fact, |
| 216 // Perftools_malloc_ may need to call origstub_malloc_, which means we | 234 // Perftools_malloc_ may need to call origstub_malloc_, which means we |
| 217 // either need to change Perftools_malloc_ to take origstub_malloc_ as | 235 // either need to change Perftools_malloc_ to take origstub_malloc_ as |
| 218 // an arugment -- unfortunately impossible since it needs to keep the | 236 // an arugment -- unfortunately impossible since it needs to keep the |
| 219 // same API as normal malloc -- or we need to write a different | 237 // same API as normal malloc -- or we need to write a different |
| 220 // version of Perftools_malloc_ for each LibcInfo instance we create. | 238 // version of Perftools_malloc_ for each LibcInfo instance we create. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 static size_t Perftools__msize(void *ptr) __THROW; | 276 static size_t Perftools__msize(void *ptr) __THROW; |
| 259 static void* Perftools__expand(void *ptr, size_t size) __THROW; | 277 static void* Perftools__expand(void *ptr, size_t size) __THROW; |
| 260 static void* Perftools__aligned_malloc(size_t size, size_t alignment) __THROW; | 278 static void* Perftools__aligned_malloc(size_t size, size_t alignment) __THROW; |
| 261 static void Perftools__aligned_free(void *ptr) __THROW; | 279 static void Perftools__aligned_free(void *ptr) __THROW; |
| 262 // malloc.h also defines these functions: | 280 // malloc.h also defines these functions: |
| 263 // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc | 281 // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc |
| 264 // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea | 282 // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea |
| 265 // But they seem pretty obscure, and I'm fine not overriding them for now. | 283 // But they seem pretty obscure, and I'm fine not overriding them for now. |
| 266 }; | 284 }; |
| 267 | 285 |
| 286 // This is a subset of MODDULEENTRY32, that we need for patching. |
| 287 struct ModuleEntryCopy { |
| 288 LPVOID modBaseAddr; |
| 289 DWORD modBaseSize; |
| 290 HMODULE hModule; |
| 291 TCHAR szModule[kMaxModuleNameSize]; |
| 292 // This is not part of MODDULEENTRY32, but is needed to avoid making |
| 293 // windows syscalls while we're holding patch_all_modules_lock (see |
| 294 // lock-inversion comments at patch_all_modules_lock definition, below). |
| 295 GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress]; |
| 296 |
| 297 ModuleEntryCopy() { |
| 298 modBaseAddr = NULL; |
| 299 modBaseSize = 0; |
| 300 hModule = NULL; |
| 301 strcpy(szModule, "<executable>"); |
| 302 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) |
| 303 rgProcAddresses[i] = LibcInfo::static_fn(i); |
| 304 } |
| 305 ModuleEntryCopy(HANDLE hprocess, HMODULE hmodule, const MODULEINFO& mi) { |
| 306 this->modBaseAddr = mi.lpBaseOfDll; |
| 307 this->modBaseSize = mi.SizeOfImage; |
| 308 this->hModule = hmodule; |
| 309 // TODO(csilvers): we could make more efficient by calling these |
| 310 // lazily (not until the vars are needed, which is often never). |
| 311 // However, there's tricky business with calling windows functions |
| 312 // inside the patch_all_modules_lock (see the lock inversion |
| 313 // comments with the patch_all_modules_lock definition, below), so |
| 314 // it's safest to do it all here, where no lock is needed. |
| 315 ::GetModuleBaseNameA(hprocess, hmodule, |
| 316 this->szModule, sizeof(this->szModule)); |
| 317 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) |
| 318 rgProcAddresses[i] = |
| 319 (GenericFnPtr)::GetProcAddress(hModule, LibcInfo::function_name(i)); |
| 320 } |
| 321 }; |
| 322 |
| 268 // This class is easier because there's only one of them. | 323 // This class is easier because there's only one of them. |
| 269 class WindowsInfo { | 324 class WindowsInfo { |
| 270 public: | 325 public: |
| 271 void Patch(); | 326 void Patch(); |
| 272 void Unpatch(); | 327 void Unpatch(); |
| 273 | 328 |
| 274 private: | 329 private: |
| 275 // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead, | 330 // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead, |
| 276 // for pre-XP systems? | 331 // for pre-XP systems? |
| 277 enum { | 332 enum { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 // We don't need the other 3 variants because they all call this one. */ | 366 // We don't need the other 3 variants because they all call this one. */ |
| 312 static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName, | 367 static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName, |
| 313 HANDLE hFile, | 368 HANDLE hFile, |
| 314 DWORD dwFlags); | 369 DWORD dwFlags); |
| 315 static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule); | 370 static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule); |
| 316 }; | 371 }; |
| 317 | 372 |
| 318 // If you run out, just add a few more to the array. You'll also need | 373 // If you run out, just add a few more to the array. You'll also need |
| 319 // to update the switch statement in PatchOneModule(), and the list in | 374 // to update the switch statement in PatchOneModule(), and the list in |
| 320 // UnpatchWindowsFunctions(). | 375 // UnpatchWindowsFunctions(). |
| 376 // main_executable and main_executable_windows are two windows into |
| 377 // the same executable. One is responsible for patching the libc |
| 378 // routines that live in the main executable (if any) to use tcmalloc; |
| 379 // the other is responsible for patching the windows routines like |
| 380 // HeapAlloc/etc to use tcmalloc. |
| 321 static LibcInfoWithPatchFunctions<0> main_executable; | 381 static LibcInfoWithPatchFunctions<0> main_executable; |
| 322 static LibcInfoWithPatchFunctions<1> libc1; | 382 static LibcInfoWithPatchFunctions<1> libc1; |
| 323 static LibcInfoWithPatchFunctions<2> libc2; | 383 static LibcInfoWithPatchFunctions<2> libc2; |
| 324 static LibcInfoWithPatchFunctions<3> libc3; | 384 static LibcInfoWithPatchFunctions<3> libc3; |
| 325 static LibcInfoWithPatchFunctions<4> libc4; | 385 static LibcInfoWithPatchFunctions<4> libc4; |
| 326 static LibcInfoWithPatchFunctions<5> libc5; | 386 static LibcInfoWithPatchFunctions<5> libc5; |
| 327 static LibcInfoWithPatchFunctions<6> libc6; | 387 static LibcInfoWithPatchFunctions<6> libc6; |
| 328 static LibcInfoWithPatchFunctions<7> libc7; | 388 static LibcInfoWithPatchFunctions<7> libc7; |
| 329 static LibcInfoWithPatchFunctions<8> libc8; | 389 static LibcInfoWithPatchFunctions<8> libc8; |
| 330 static LibcInfo* module_libcs[] = { | 390 static LibcInfo* g_module_libcs[] = { |
| 331 &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8 | 391 &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8 |
| 332 }; | 392 }; |
| 333 static WindowsInfo main_executable_windows; | 393 static WindowsInfo main_executable_windows; |
| 334 | 394 |
| 335 const char* const LibcInfo::function_name_[] = { | 395 const char* const LibcInfo::function_name_[] = { |
| 336 "malloc", "free", "realloc", "calloc", | 396 "malloc", "free", "realloc", "calloc", |
| 337 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, | 397 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, |
| 338 // Ideally we should patch the nothrow versions of new/delete, but | 398 // Ideally we should patch the nothrow versions of new/delete, but |
| 339 // at least in msvcrt, nothrow-new machine-code is of a type we | 399 // at least in msvcrt, nothrow-new machine-code is of a type we |
| 340 // can't patch. Since these are relatively rare, I'm hoping it's ok | 400 // can't patch. Since these are relatively rare, I'm hoping it's ok |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, | 472 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, |
| 413 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, | 473 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, |
| 414 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, | 474 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, |
| 415 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, | 475 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, |
| 416 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, | 476 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, |
| 417 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, | 477 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, |
| 418 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, | 478 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, |
| 419 { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary }, | 479 { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary }, |
| 420 }; | 480 }; |
| 421 | 481 |
| 422 bool LibcInfo::PopulateWindowsFn(const MODULEENTRY32& me32) { | 482 bool LibcInfo::SameAs(const LibcInfo& that) const { |
| 423 module_base_address_ = me32.modBaseAddr; | 483 return (is_valid() && |
| 424 module_base_size_ = me32.modBaseSize; | 484 module_base_address_ == that.module_base_address_ && |
| 425 strcpy(module_name_, me32.szModule); | 485 module_base_size_ == that.module_base_size_); |
| 486 } |
| 426 | 487 |
| 488 bool LibcInfo::SameAsModuleEntry(const ModuleEntryCopy& module_entry) const { |
| 489 return (is_valid() && |
| 490 module_base_address_ == module_entry.modBaseAddr && |
| 491 module_base_size_ == module_entry.modBaseSize); |
| 492 } |
| 493 |
| 494 bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) { |
| 427 // First, store the location of the function to patch before | 495 // First, store the location of the function to patch before |
| 428 // patching it. If none of these functions are found in the module, | 496 // patching it. If none of these functions are found in the module, |
| 429 // then this module has no libc in it, and we just return false. | 497 // then this module has no libc in it, and we just return false. |
| 430 for (int i = 0; i < kNumFunctions; i++) { | 498 for (int i = 0; i < kNumFunctions; i++) { |
| 431 if (!function_name_[i]) // we can turn off patching by unsetting name | 499 if (!function_name_[i]) // we can turn off patching by unsetting name |
| 432 continue; | 500 continue; |
| 433 GenericFnPtr fn = NULL; | 501 // The ::GetProcAddress calls were done in the ModuleEntryCopy |
| 434 if (me32.hModule == NULL) { // used for the main executable | 502 // constructor, so we don't have to make any windows calls here. |
| 435 // This is used only for a statically-linked-in libc. | 503 const GenericFnPtr fn = module_entry.rgProcAddresses[i]; |
| 436 fn = static_fn_[i]; | |
| 437 } else { | |
| 438 fn = (GenericFnPtr)::GetProcAddress(me32.hModule, function_name_[i]); | |
| 439 } | |
| 440 if (fn) { | 504 if (fn) { |
| 441 windows_fn_[i] = PreamblePatcher::ResolveTarget(fn); | 505 windows_fn_[i] = PreamblePatcher::ResolveTarget(fn); |
| 442 } | 506 } |
| 443 } | 507 } |
| 444 | 508 |
| 445 // Some modules use the same function pointer for new and new[]. If | 509 // Some modules use the same function pointer for new and new[]. If |
| 446 // we find that, set one of the pointers to NULL so we don't double- | 510 // we find that, set one of the pointers to NULL so we don't double- |
| 447 // patch. Same may happen with new and nothrow-new, or even new[] | 511 // patch. Same may happen with new and nothrow-new, or even new[] |
| 448 // and nothrow-new. It's easiest just to check each fn-ptr against | 512 // and nothrow-new. It's easiest just to check each fn-ptr against |
| 449 // every other. | 513 // every other. |
| 450 for (int i = 0; i < kNumFunctions; i++) { | 514 for (int i = 0; i < kNumFunctions; i++) { |
| 451 for (int j = i+1; j < kNumFunctions; j++) { | 515 for (int j = i+1; j < kNumFunctions; j++) { |
| 452 if (windows_fn_[i] == windows_fn_[j]) { | 516 if (windows_fn_[i] == windows_fn_[j]) { |
| 453 // We NULL the later one (j), so as to minimize the chances we | 517 // We NULL the later one (j), so as to minimize the chances we |
| 454 // NULL kFree and kRealloc. See comments below. This is fragile! | 518 // NULL kFree and kRealloc. See comments below. This is fragile! |
| 455 windows_fn_[j] = NULL; | 519 windows_fn_[j] = NULL; |
| 456 } | 520 } |
| 457 } | 521 } |
| 458 } | 522 } |
| 459 | 523 |
| 460 // There's always a chance that our module uses the same function | 524 // There's always a chance that our module uses the same function |
| 461 // as another module that we've already loaded. In that case, we | 525 // as another module that we've already loaded. In that case, we |
| 462 // need to set our windows_fn to NULL, to avoid double-patching. | 526 // need to set our windows_fn to NULL, to avoid double-patching. |
| 463 for (int ifn = 0; ifn < kNumFunctions; ifn++) { | 527 for (int ifn = 0; ifn < kNumFunctions; ifn++) { |
| 464 for (int imod = 0; | 528 for (int imod = 0; |
| 465 imod < sizeof(module_libcs)/sizeof(*module_libcs); imod++) { | 529 imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs); imod++) { |
| 466 if (module_libcs[imod]->is_valid() && | 530 if (g_module_libcs[imod]->is_valid() && |
| 467 this->windows_fn(ifn) == module_libcs[imod]->windows_fn(ifn)) { | 531 this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) { |
| 468 windows_fn_[ifn] = NULL; | 532 windows_fn_[ifn] = NULL; |
| 469 } | 533 } |
| 470 } | 534 } |
| 471 } | 535 } |
| 472 | 536 |
| 473 bool found_non_null = false; | 537 bool found_non_null = false; |
| 474 for (int i = 0; i < kNumFunctions; i++) { | 538 for (int i = 0; i < kNumFunctions; i++) { |
| 475 if (windows_fn_[i]) | 539 if (windows_fn_[i]) |
| 476 found_non_null = true; | 540 found_non_null = true; |
| 477 } | 541 } |
| 478 if (!found_non_null) | 542 if (!found_non_null) |
| 479 return false; | 543 return false; |
| 480 | 544 |
| 481 // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc]. | 545 // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc]. |
| 482 // The reason is, if those are NULL-ed out, we'll never patch them | 546 // The reason is, if those are NULL-ed out, we'll never patch them |
| 483 // and thus never get an origstub_fn_ value for them, and when we | 547 // and thus never get an origstub_fn_ value for them, and when we |
| 484 // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and | 548 // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and |
| 485 // Perftools_realloc, below, it will fail. We could work around | 549 // Perftools_realloc, below, it will fail. We could work around |
| 486 // that by adding a pointer from one patch-unit to the other, but we | 550 // that by adding a pointer from one patch-unit to the other, but we |
| 487 // haven't needed to yet. | 551 // haven't needed to yet. |
| 488 CHECK(windows_fn_[kFree]); | 552 CHECK(windows_fn_[kFree]); |
| 489 CHECK(windows_fn_[kRealloc]); | 553 CHECK(windows_fn_[kRealloc]); |
| 554 |
| 555 // OK, we successfully patched. Let's store our member information. |
| 556 module_base_address_ = module_entry.modBaseAddr; |
| 557 module_base_size_ = module_entry.modBaseSize; |
| 558 strcpy(module_name_, module_entry.szModule); |
| 490 return true; | 559 return true; |
| 491 } | 560 } |
| 492 | 561 |
| 493 template<int T> | 562 template<int T> |
| 494 bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) { | 563 bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) { |
| 495 CopyFrom(me_info); // copies the me32 and the windows_fn_ array | 564 CopyFrom(me_info); // copies the module_entry and the windows_fn_ array |
| 496 for (int i = 0; i < kNumFunctions; i++) { | 565 for (int i = 0; i < kNumFunctions; i++) { |
| 497 if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) | 566 if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) { |
| 567 // if origstub_fn_ is not NULL, it's left around from a previous |
| 568 // patch. We need to set it to NULL for the new Patch call. |
| 569 // Since we've patched Unpatch() not to delete origstub_fn_ (it |
| 570 // causes problems in some contexts, though obviously not this |
| 571 // one), we should delete it now, before setting it to NULL. |
| 572 // NOTE: casting from a function to a pointer is contra the C++ |
| 573 // spec. It's not safe on IA64, but is on i386. We use |
| 574 // a C-style cast here to emphasize this is not legal C++. |
| 575 delete[] (char*)(origstub_fn_[i]); |
| 576 origstub_fn_[i] = NULL; // Patch() will fill this in |
| 498 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, | 577 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, |
| 499 PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i], | 578 PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i], |
| 500 &origstub_fn_[i])); | 579 &origstub_fn_[i])); |
| 580 } |
| 501 } | 581 } |
| 502 set_is_valid(true); | 582 set_is_valid(true); |
| 503 return true; | 583 return true; |
| 504 } | 584 } |
| 505 | 585 |
| 506 template<int T> | 586 template<int T> |
| 507 void LibcInfoWithPatchFunctions<T>::Unpatch() { | 587 void LibcInfoWithPatchFunctions<T>::Unpatch() { |
| 508 // We have to cast our GenericFnPtrs to void* for unpatch. This is | 588 // We have to cast our GenericFnPtrs to void* for unpatch. This is |
| 509 // contra the C++ spec; we use C-style casts to empahsize that. | 589 // contra the C++ spec; we use C-style casts to empahsize that. |
| 510 for (int i = 0; i < kNumFunctions; i++) { | 590 for (int i = 0; i < kNumFunctions; i++) { |
| 511 if (windows_fn_[i]) | 591 if (windows_fn_[i]) |
| 512 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, | 592 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, |
| 513 PreamblePatcher::Unpatch((void*)windows_fn_[i], | 593 PreamblePatcher::Unpatch((void*)windows_fn_[i], |
| 514 (void*)perftools_fn_[i], | 594 (void*)perftools_fn_[i], |
| 515 (void*)origstub_fn_[i])); | 595 (void*)origstub_fn_[i])); |
| 516 } | 596 } |
| 517 set_is_valid(false); | 597 set_is_valid(false); |
| 518 } | 598 } |
| 519 | 599 |
| 520 void WindowsInfo::Patch() { | 600 void WindowsInfo::Patch() { |
| 521 HMODULE hkernel32 = ::GetModuleHandleA("kernel32"); | 601 HMODULE hkernel32 = ::GetModuleHandleA("kernel32"); |
| 522 CHECK_NE(hkernel32, NULL); | 602 CHECK_NE(hkernel32, NULL); |
| 523 | 603 |
| 524 // Unlike for libc, we know these exist in our module, so we can get | 604 // Unlike for libc, we know these exist in our module, so we can get |
| 525 // and patch at the same time. | 605 // and patch at the same time. |
| 526 for (int i = 0; i < kNumFunctions; i++) { | 606 for (int i = 0; i < kNumFunctions; i++) { |
| 527 function_info_[i].windows_fn = (GenericFnPtr) | 607 function_info_[i].windows_fn = (GenericFnPtr) |
| 528 ::GetProcAddress(hkernel32, function_info_[i].name); | 608 ::GetProcAddress(hkernel32, function_info_[i].name); |
| 609 // If origstub_fn is not NULL, it's left around from a previous |
| 610 // patch. We need to set it to NULL for the new Patch call. |
| 611 // Since we've patched Unpatch() not to delete origstub_fn_ (it |
| 612 // causes problems in some contexts, though obviously not this |
| 613 // one), we should delete it now, before setting it to NULL. |
| 614 // NOTE: casting from a function to a pointer is contra the C++ |
| 615 // spec. It's not safe on IA64, but is on i386. We use |
| 616 // a C-style cast here to emphasize this is not legal C++. |
| 617 delete[] (char*)(function_info_[i].origstub_fn); |
| 618 function_info_[i].origstub_fn = NULL; // Patch() will fill this in |
| 529 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, | 619 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, |
| 530 PreamblePatcher::Patch(function_info_[i].windows_fn, | 620 PreamblePatcher::Patch(function_info_[i].windows_fn, |
| 531 function_info_[i].perftools_fn, | 621 function_info_[i].perftools_fn, |
| 532 &function_info_[i].origstub_fn)); | 622 &function_info_[i].origstub_fn)); |
| 533 } | 623 } |
| 534 } | 624 } |
| 535 | 625 |
| 536 void WindowsInfo::Unpatch() { | 626 void WindowsInfo::Unpatch() { |
| 537 // We have to cast our GenericFnPtrs to void* for unpatch. This is | 627 // We have to cast our GenericFnPtrs to void* for unpatch. This is |
| 538 // contra the C++ spec; we use C-style casts to empahsize that. | 628 // contra the C++ spec; we use C-style casts to empahsize that. |
| 539 for (int i = 0; i < kNumFunctions; i++) { | 629 for (int i = 0; i < kNumFunctions; i++) { |
| 540 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, | 630 CHECK_EQ(sidestep::SIDESTEP_SUCCESS, |
| 541 PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn, | 631 PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn, |
| 542 (void*)function_info_[i].perftools_fn, | 632 (void*)function_info_[i].perftools_fn, |
| 543 (void*)function_info_[i].origstub_fn)); | 633 (void*)function_info_[i].origstub_fn)); |
| 544 } | 634 } |
| 545 } | 635 } |
| 546 | 636 |
| 547 // You should hold the patch_all_modules_lock when calling this. | 637 // You should hold the patch_all_modules_lock when calling this. |
| 548 void PatchOneModuleLocked(const LibcInfo& me_info) { | 638 void PatchOneModuleLocked(const LibcInfo& me_info) { |
| 549 // Double-check we haven't seen this module before. | 639 // Double-check we haven't seen this module before. |
| 550 for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) { | 640 for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) { |
| 551 if (module_libcs[i]->SameAs(me_info)) { | 641 if (g_module_libcs[i]->SameAs(me_info)) { |
| 552 fprintf(stderr, "%s:%d: FATAL ERROR: %s double-patched somehow.\n", | 642 fprintf(stderr, "%s:%d: FATAL PERFTOOLS ERROR: %s double-patched somehow.\
n", |
| 553 __FILE__, __LINE__, module_libcs[i]->module_name()); | 643 __FILE__, __LINE__, g_module_libcs[i]->module_name()); |
| 554 CHECK(false); | 644 CHECK(false); |
| 555 } | 645 } |
| 556 } | 646 } |
| 557 // If we don't already have info on this module, let's add it. This | 647 // If we don't already have info on this module, let's add it. This |
| 558 // is where we're sad that each libcX has a different type, so we | 648 // is where we're sad that each libcX has a different type, so we |
| 559 // can't use an array; instead, we have to use a switch statement. | 649 // can't use an array; instead, we have to use a switch statement. |
| 560 // Patch() returns false if there were no libc functions in the module. | 650 // Patch() returns false if there were no libc functions in the module. |
| 561 for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) { | 651 for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) { |
| 562 if (!module_libcs[i]->is_valid()) { // found an empty spot to add! | 652 if (!g_module_libcs[i]->is_valid()) { // found an empty spot to add! |
| 563 switch (i) { | 653 switch (i) { |
| 564 case 0: libc1.Patch(me_info); return; | 654 case 0: libc1.Patch(me_info); return; |
| 565 case 1: libc2.Patch(me_info); return; | 655 case 1: libc2.Patch(me_info); return; |
| 566 case 2: libc3.Patch(me_info); return; | 656 case 2: libc3.Patch(me_info); return; |
| 567 case 3: libc4.Patch(me_info); return; | 657 case 3: libc4.Patch(me_info); return; |
| 568 case 4: libc5.Patch(me_info); return; | 658 case 4: libc5.Patch(me_info); return; |
| 569 case 5: libc6.Patch(me_info); return; | 659 case 5: libc6.Patch(me_info); return; |
| 570 case 6: libc7.Patch(me_info); return; | 660 case 6: libc7.Patch(me_info); return; |
| 571 case 7: libc8.Patch(me_info); return; | 661 case 7: libc8.Patch(me_info); return; |
| 572 } | 662 } |
| 573 } | 663 } |
| 574 } | 664 } |
| 575 printf("ERROR: Too many modules containing libc in this executable\n"); | 665 printf("PERFTOOLS ERROR: Too many modules containing libc in this executable\n
"); |
| 576 } | 666 } |
| 577 | 667 |
| 578 void PatchMainExecutableLocked() { | 668 void PatchMainExecutableLocked() { |
| 579 if (main_executable.patched()) | 669 if (main_executable.patched()) |
| 580 return; // main executable has already been patched | 670 return; // main executable has already been patched |
| 581 MODULEENTRY32 fake_me32; // we make a fake one to pass into Patch() | 671 ModuleEntryCopy fake_module_entry; // make a fake one to pass into Patch() |
| 582 fake_me32.modBaseAddr = NULL; | 672 // No need to call PopulateModuleEntryProcAddresses on the main executable. |
| 583 fake_me32.modBaseSize = 0; | 673 main_executable.PopulateWindowsFn(fake_module_entry); |
| 584 strcpy(fake_me32.szModule, "<executable>"); | |
| 585 fake_me32.hModule = NULL; | |
| 586 main_executable.PopulateWindowsFn(fake_me32); | |
| 587 main_executable.Patch(main_executable); | 674 main_executable.Patch(main_executable); |
| 588 } | 675 } |
| 589 | 676 |
| 677 // This lock is subject to a subtle and annoying lock inversion |
| 678 // problem: it may interact badly with unknown internal windows locks. |
| 679 // In particular, windows may be holding a lock when it calls |
| 680 // LoadLibraryExW and FreeLibrary, which we've patched. We have those |
| 681 // routines call PatchAllModules, which acquires this lock. If we |
| 682 // make windows system calls while holding this lock, those system |
| 683 // calls may need the internal windows locks that are being held in |
| 684 // the call to LoadLibraryExW, resulting in deadlock. The solution is |
| 685 // to be very careful not to call *any* windows routines while holding |
| 686 // patch_all_modules_lock, inside PatchAllModules(). |
| 590 static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED); | 687 static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED); |
| 591 | 688 |
| 592 // Iterates over all the modules currently loaded by the executable, | 689 // Iterates over all the modules currently loaded by the executable, |
| 593 // and makes sure they're all patched. For ones that aren't, we patch | 690 // and makes sure they're all patched. For ones that aren't, we patch |
| 594 // them in. We also check that every module we had patched in the | 691 // them in. We also check that every module we had patched in the |
| 595 // past is still loaded, and update internal data structures if so. | 692 // past is still loaded, and update internal data structures if so. |
| 596 void PatchAllModules() { | 693 // We return true if this PatchAllModules did any work, false else. |
| 597 std::vector<LibcInfo*> modules; | 694 bool PatchAllModules() { |
| 598 bool still_loaded[sizeof(module_libcs)/sizeof(*module_libcs)] = {}; | 695 std::vector<ModuleEntryCopy> modules; |
| 696 bool made_changes = false; |
| 599 | 697 |
| 600 HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | | 698 const HANDLE hCurrentProcess = GetCurrentProcess(); |
| 601 TH32CS_SNAPMODULE32, | 699 MODULEINFO mi; |
| 602 GetCurrentProcessId()); | 700 DWORD cbNeeded = 0; |
| 603 if (hModuleSnap != INVALID_HANDLE_VALUE) { | 701 HMODULE hModules[kMaxModules]; // max # of modules we support in one process |
| 604 MODULEENTRY32 me32; | 702 if (::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules), |
| 605 me32.dwSize = sizeof(me32); | 703 &cbNeeded)) { |
| 606 if (Module32First(hModuleSnap, &me32)) { | 704 for (int i = 0; i < cbNeeded / sizeof(*hModules); ++i) { |
| 607 do { | 705 if (i >= kMaxModules) { |
| 608 bool module_already_loaded = false; | 706 printf("PERFTOOLS ERROR: Too many modules in this executable to try" |
| 609 for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) { | 707 " to patch them all (if you need to, raise kMaxModules in" |
| 610 if (module_libcs[i]->SameAsME32(me32)) { | 708 " patch_functions.cc).\n"); |
| 611 still_loaded[i] = true; | 709 break; |
| 612 module_already_loaded = true; | 710 } |
| 613 break; | 711 if (::GetModuleInformation(hCurrentProcess, hModules[i], &mi, sizeof(mi))) |
| 614 } | 712 modules.push_back(ModuleEntryCopy(hCurrentProcess, hModules[i], mi)); |
| 615 } | |
| 616 if (!module_already_loaded) { | |
| 617 LibcInfo* libc_info = new LibcInfo; | |
| 618 if (libc_info->PopulateWindowsFn(me32)) | |
| 619 modules.push_back(libc_info); | |
| 620 else // means module has no libc routines | |
| 621 delete libc_info; | |
| 622 } | |
| 623 } while (Module32Next(hModuleSnap, &me32)); | |
| 624 } | 713 } |
| 625 CloseHandle(hModuleSnap); | |
| 626 } | 714 } |
| 627 | 715 |
| 628 // Now do the actual patching. | 716 // Now do the actual patching and unpatching. |
| 629 { | 717 { |
| 630 SpinLockHolder h(&patch_all_modules_lock); | 718 SpinLockHolder h(&patch_all_modules_lock); |
| 631 // First, delete the modules that are no longer loaded. (We go first | 719 for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) { |
| 632 // so we can try to open up space for the new modules we need to load.) | 720 if (!g_module_libcs[i]->is_valid()) |
| 633 for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) { | 721 continue; |
| 634 if (!still_loaded[i]) { | 722 bool still_loaded = false; |
| 723 for (std::vector<ModuleEntryCopy>::iterator it = modules.begin(); |
| 724 it != modules.end(); ++it) { |
| 725 if (g_module_libcs[i]->SameAsModuleEntry(*it)) { |
| 726 // Both g_module_libcs[i] and it are still valid. Mark it by |
| 727 // removing it from the vector; mark g_module_libcs[i] by |
| 728 // setting a bool. |
| 729 modules.erase(it); |
| 730 still_loaded = true; |
| 731 break; |
| 732 } |
| 733 } |
| 734 if (!still_loaded) { |
| 735 // Means g_module_libcs[i] is no longer loaded (no me32 matched). |
| 635 // We could call Unpatch() here, but why bother? The module | 736 // We could call Unpatch() here, but why bother? The module |
| 636 // has gone away, so nobody is going to call into it anyway. | 737 // has gone away, so nobody is going to call into it anyway. |
| 637 module_libcs[i]->set_is_valid(false); | 738 g_module_libcs[i]->set_is_valid(false); |
| 739 made_changes = true; |
| 638 } | 740 } |
| 639 } | 741 } |
| 640 | 742 |
| 641 // Now, add in new modules that we need to load. | 743 // We've handled all the g_module_libcs. Now let's handle the rest |
| 642 for (std::vector<LibcInfo*>::iterator it = modules.begin(); | 744 // of the module-entries: those that haven't already been loaded. |
| 643 it != modules.end(); ++it) { | 745 for (std::vector<ModuleEntryCopy>::const_iterator it = modules.begin(); |
| 644 PatchOneModuleLocked(**it); // updates num_patched_modules | 746 it != modules.end(); ++it) { |
| 747 LibcInfo libc_info; |
| 748 if (libc_info.PopulateWindowsFn(*it)) { // true==module has libc routines |
| 749 PatchOneModuleLocked(libc_info); // updates num_patched_modules |
| 750 made_changes = true; |
| 751 } |
| 645 } | 752 } |
| 646 | 753 |
| 647 // Now that we've dealt with the modules (dlls), update the main | 754 // Now that we've dealt with the modules (dlls), update the main |
| 648 // executable. We do this last because PatchMainExecutableLocked | 755 // executable. We do this last because PatchMainExecutableLocked |
| 649 // wants to look at how other modules were patched. | 756 // wants to look at how other modules were patched. |
| 650 PatchMainExecutableLocked(); | 757 if (!main_executable.patched()) { |
| 758 PatchMainExecutableLocked(); |
| 759 made_changes = true; |
| 760 } |
| 651 } | 761 } |
| 652 | 762 return made_changes; |
| 653 for (std::vector<LibcInfo*>::iterator it = modules.begin(); | |
| 654 it != modules.end(); ++it) { | |
| 655 delete *it; | |
| 656 } | |
| 657 } | 763 } |
| 658 | 764 |
| 659 | 765 |
| 660 } // end unnamed namespace | 766 } // end unnamed namespace |
| 661 | 767 |
| 662 // --------------------------------------------------------------------- | 768 // --------------------------------------------------------------------- |
| 663 // PatchWindowsFunctions() | 769 // PatchWindowsFunctions() |
| 664 // This is the function that is exposed to the outside world. | 770 // This is the function that is exposed to the outside world. |
| 771 // It should be called before the program becomes multi-threaded, |
| 772 // since main_executable_windows.Patch() is not thread-safe. |
| 665 // --------------------------------------------------------------------- | 773 // --------------------------------------------------------------------- |
| 666 | 774 |
| 667 void PatchWindowsFunctions() { | 775 void PatchWindowsFunctions() { |
| 668 // This does the libc patching in every module, and the main executable. | 776 // This does the libc patching in every module, and the main executable. |
| 669 PatchAllModules(); | 777 PatchAllModules(); |
| 670 main_executable_windows.Patch(); | 778 main_executable_windows.Patch(); |
| 671 } | 779 } |
| 672 | 780 |
| 673 #if 0 | 781 #if 0 |
| 674 // It's possible to unpatch all the functions when we are exiting. | 782 // It's possible to unpatch all the functions when we are exiting. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 // functions here, using tcmalloc internals, without polluting | 827 // functions here, using tcmalloc internals, without polluting |
| 720 // tcmalloc.cc. | 828 // tcmalloc.cc. |
| 721 // ------------------------------------------------------------------- | 829 // ------------------------------------------------------------------- |
| 722 | 830 |
| 723 // TODO(csilvers): refactor tcmalloc.cc into two files, so I can link | 831 // TODO(csilvers): refactor tcmalloc.cc into two files, so I can link |
| 724 // against the file with do_malloc, and ignore the one with malloc. | 832 // against the file with do_malloc, and ignore the one with malloc. |
| 725 #include "tcmalloc.cc" | 833 #include "tcmalloc.cc" |
| 726 | 834 |
| 727 template<int T> | 835 template<int T> |
| 728 void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW { | 836 void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW { |
| 729 void* result = do_malloc(size); | 837 void* result = do_malloc_or_cpp_alloc(size); |
| 730 MallocHook::InvokeNewHook(result, size); | 838 MallocHook::InvokeNewHook(result, size); |
| 731 return result; | 839 return result; |
| 732 } | 840 } |
| 733 | 841 |
| 734 template<int T> | 842 template<int T> |
| 735 void LibcInfoWithPatchFunctions<T>::Perftools_free(void* ptr) __THROW { | 843 void LibcInfoWithPatchFunctions<T>::Perftools_free(void* ptr) __THROW { |
| 736 MallocHook::InvokeDeleteHook(ptr); | 844 MallocHook::InvokeDeleteHook(ptr); |
| 737 // This calls the windows free if do_free decides ptr was not | 845 // This calls the windows free if do_free decides ptr was not |
| 738 // allocated by tcmalloc. Note it calls the origstub_free from | 846 // allocated by tcmalloc. Note it calls the origstub_free from |
| 739 // *this* templatized instance of LibcInfo. See "template | 847 // *this* templatized instance of LibcInfo. See "template |
| 740 // trickiness" above. | 848 // trickiness" above. |
| 741 do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree]); | 849 do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree]); |
| 742 } | 850 } |
| 743 | 851 |
| 744 template<int T> | 852 template<int T> |
| 745 void* LibcInfoWithPatchFunctions<T>::Perftools_realloc( | 853 void* LibcInfoWithPatchFunctions<T>::Perftools_realloc( |
| 746 void* old_ptr, size_t new_size) __THROW { | 854 void* old_ptr, size_t new_size) __THROW { |
| 747 if (old_ptr == NULL) { | 855 if (old_ptr == NULL) { |
| 748 void* result = do_malloc(new_size); | 856 void* result = do_malloc_or_cpp_alloc(new_size); |
| 749 MallocHook::InvokeNewHook(result, new_size); | 857 MallocHook::InvokeNewHook(result, new_size); |
| 750 return result; | 858 return result; |
| 751 } | 859 } |
| 752 if (new_size == 0) { | 860 if (new_size == 0) { |
| 753 MallocHook::InvokeDeleteHook(old_ptr); | 861 MallocHook::InvokeDeleteHook(old_ptr); |
| 754 do_free_with_callback(old_ptr, | 862 do_free_with_callback(old_ptr, |
| 755 (void (*)(void*))origstub_fn_[kFree]); | 863 (void (*)(void*))origstub_fn_[kFree]); |
| 756 return NULL; | 864 return NULL; |
| 757 } | 865 } |
| 758 return do_realloc_with_callback( | 866 return do_realloc_with_callback( |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 template<int T> | 953 template<int T> |
| 846 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, | 954 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, |
| 847 size_t size) __THROW { | 955 size_t size) __THROW { |
| 848 return NULL; | 956 return NULL; |
| 849 } | 957 } |
| 850 | 958 |
| 851 template<int T> | 959 template<int T> |
| 852 void* LibcInfoWithPatchFunctions<T>::Perftools__aligned_malloc(size_t size, | 960 void* LibcInfoWithPatchFunctions<T>::Perftools__aligned_malloc(size_t size, |
| 853 size_t alignment) | 961 size_t alignment) |
| 854 __THROW { | 962 __THROW { |
| 855 void* result = do_memalign(alignment, size); | 963 void* result = do_memalign_or_cpp_memalign(alignment, size); |
| 856 MallocHook::InvokeNewHook(result, size); | 964 MallocHook::InvokeNewHook(result, size); |
| 857 return result; | 965 return result; |
| 858 } | 966 } |
| 859 | 967 |
| 860 template<int T> | 968 template<int T> |
| 861 void LibcInfoWithPatchFunctions<T>::Perftools__aligned_free(void *ptr) __THROW { | 969 void LibcInfoWithPatchFunctions<T>::Perftools__aligned_free(void *ptr) __THROW { |
| 862 MallocHook::InvokeDeleteHook(ptr); | 970 MallocHook::InvokeDeleteHook(ptr); |
| 863 do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[k_Aligned_free]); | 971 do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[k_Aligned_free]); |
| 864 } | 972 } |
| 865 | 973 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 function_info_[kUnmapViewOfFile].origstub_fn)( | 1028 function_info_[kUnmapViewOfFile].origstub_fn)( |
| 921 lpBaseAddress); | 1029 lpBaseAddress); |
| 922 } | 1030 } |
| 923 | 1031 |
| 924 HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName, | 1032 HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName, |
| 925 HANDLE hFile, | 1033 HANDLE hFile, |
| 926 DWORD dwFlags) { | 1034 DWORD dwFlags) { |
| 927 HMODULE rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD)) | 1035 HMODULE rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD)) |
| 928 function_info_[kLoadLibraryExW].origstub_fn)( | 1036 function_info_[kLoadLibraryExW].origstub_fn)( |
| 929 lpFileName, hFile, dwFlags); | 1037 lpFileName, hFile, dwFlags); |
| 930 PatchAllModules(); // this will patch any newly loaded libraries | 1038 PatchAllModules(); |
| 931 return rv; | 1039 return rv; |
| 932 } | 1040 } |
| 933 | 1041 |
| 934 BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) { | 1042 BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) { |
| 935 BOOL rv = ((BOOL (WINAPI *)(HMODULE)) | 1043 BOOL rv = ((BOOL (WINAPI *)(HMODULE)) |
| 936 function_info_[kFreeLibrary].origstub_fn)(hLibModule); | 1044 function_info_[kFreeLibrary].origstub_fn)(hLibModule); |
| 937 PatchAllModules(); // this will fix up the list of patched libraries | 1045 PatchAllModules(); // this will fix up the list of patched libraries |
| 938 return rv; | 1046 return rv; |
| 939 } | 1047 } |
| OLD | NEW |