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