Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/tcmalloc/chromium/src/windows/patch_functions.cc

Issue 1076002: Revert 41938 - Merged third_party/tcmalloc/vendor/src(googleperftools r87) in... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h ('k') | third_party/tcmalloc/chromium/src/windows/port.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698