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

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

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