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

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

Issue 7050034: Merge google-perftools r109 (the current contents of third_party/tcmalloc/vendor) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 // Without this, the linker will likely decide that libtcmalloc.dll 115 // Without this, the linker will likely decide that libtcmalloc.dll
116 // doesn't add anything to the executable (since it does all its work 116 // doesn't add anything to the executable (since it does all its work
117 // through patching, which the linker can't see), and ignore it 117 // through patching, which the linker can't see), and ignore it
118 // entirely. (The name 'tcmalloc' is already reserved for a 118 // entirely. (The name 'tcmalloc' is already reserved for a
119 // namespace. I'd rather export a variable named "_tcmalloc", but I 119 // namespace. I'd rather export a variable named "_tcmalloc", but I
120 // couldn't figure out how to get that to work. This function exports 120 // couldn't figure out how to get that to work. This function exports
121 // the symbol "__tcmalloc".) 121 // the symbol "__tcmalloc".)
122 extern "C" PERFTOOLS_DLL_DECL void _tcmalloc(); 122 extern "C" PERFTOOLS_DLL_DECL void _tcmalloc();
123 void _tcmalloc() { } 123 void _tcmalloc() { }
124 124
125 // This is the version needed for windows x64, which has a different
126 // decoration scheme which doesn't auto-add a leading underscore.
127 extern "C" PERFTOOLS_DLL_DECL void __tcmalloc();
128 void __tcmalloc() { }
129
125 namespace { // most everything here is in an unnamed namespace 130 namespace { // most everything here is in an unnamed namespace
126 131
127 typedef void (*GenericFnPtr)(); 132 typedef void (*GenericFnPtr)();
128 133
129 using sidestep::PreamblePatcher; 134 using sidestep::PreamblePatcher;
130 135
131 struct ModuleEntryCopy; // defined below 136 struct ModuleEntryCopy; // defined below
132 137
133 // These functions are how we override the memory allocation 138 // These functions are how we override the memory allocation
134 // functions, just like tcmalloc.cc and malloc_hook.cc do. 139 // functions, just like tcmalloc.cc and malloc_hook.cc do.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_)); 173 memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_));
169 this->module_base_address_ = that.module_base_address_; 174 this->module_base_address_ = that.module_base_address_;
170 this->module_base_size_ = that.module_base_size_; 175 this->module_base_size_ = that.module_base_size_;
171 } 176 }
172 177
173 enum { 178 enum {
174 kMalloc, kFree, kRealloc, kCalloc, 179 kMalloc, kFree, kRealloc, kCalloc,
175 kNew, kNewArray, kDelete, kDeleteArray, 180 kNew, kNewArray, kDelete, kDeleteArray,
176 kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow, 181 kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow,
177 // These are windows-only functions from malloc.h 182 // These are windows-only functions from malloc.h
178 k_Msize, k_Expand, k_Aligned_malloc, k_Aligned_free, 183 k_Msize, k_Expand,
179 kNumFunctions 184 kNumFunctions
180 }; 185 };
181 186
182 // I'd like to put these together in a struct (perhaps in the 187 // I'd like to put these together in a struct (perhaps in the
183 // subclass, so we can put in perftools_fn_ as well), but vc8 seems 188 // subclass, so we can put in perftools_fn_ as well), but vc8 seems
184 // to have a bug where it doesn't initialize the struct properly if 189 // to have a bug where it doesn't initialize the struct properly if
185 // we try to take the address of a function that's not yet loaded 190 // we try to take the address of a function that's not yet loaded
186 // from a dll, as is the common case for static_fn_. So we need 191 // from a dll, as is the common case for static_fn_. So we need
187 // each to be in its own array. :-( 192 // each to be in its own array. :-(
188 static const char* const function_name_[kNumFunctions]; 193 static const char* const function_name_[kNumFunctions];
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 static void* Perftools_new_nothrow(size_t size, 272 static void* Perftools_new_nothrow(size_t size,
268 const std::nothrow_t&) __THROW; 273 const std::nothrow_t&) __THROW;
269 static void* Perftools_newarray_nothrow(size_t size, 274 static void* Perftools_newarray_nothrow(size_t size,
270 const std::nothrow_t&) __THROW; 275 const std::nothrow_t&) __THROW;
271 static void Perftools_delete_nothrow(void *ptr, 276 static void Perftools_delete_nothrow(void *ptr,
272 const std::nothrow_t&) __THROW; 277 const std::nothrow_t&) __THROW;
273 static void Perftools_deletearray_nothrow(void *ptr, 278 static void Perftools_deletearray_nothrow(void *ptr,
274 const std::nothrow_t&) __THROW; 279 const std::nothrow_t&) __THROW;
275 static size_t Perftools__msize(void *ptr) __THROW; 280 static size_t Perftools__msize(void *ptr) __THROW;
276 static void* Perftools__expand(void *ptr, size_t size) __THROW; 281 static void* Perftools__expand(void *ptr, size_t size) __THROW;
277 static void* Perftools__aligned_malloc(size_t size, size_t alignment) __THROW;
278 static void Perftools__aligned_free(void *ptr) __THROW;
279 // malloc.h also defines these functions: 282 // malloc.h also defines these functions:
283 // _aligned_malloc, _aligned_free,
280 // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc 284 // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc
281 // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea 285 // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea
282 // But they seem pretty obscure, and I'm fine not overriding them for now. 286 // But they seem pretty obscure, and I'm fine not overriding them for now.
287 // It may be they all call into malloc/free anyway.
283 }; 288 };
284 289
285 // This is a subset of MODDULEENTRY32, that we need for patching. 290 // This is a subset of MODDULEENTRY32, that we need for patching.
286 struct ModuleEntryCopy { 291 struct ModuleEntryCopy {
287 LPVOID modBaseAddr; // the same as hmodule 292 LPVOID modBaseAddr; // the same as hmodule
288 DWORD modBaseSize; 293 DWORD modBaseSize;
289 // This is not part of MODDULEENTRY32, but is needed to avoid making 294 // This is not part of MODDULEENTRY32, but is needed to avoid making
290 // windows syscalls while we're holding patch_all_modules_lock (see 295 // windows syscalls while we're holding patch_all_modules_lock (see
291 // lock-inversion comments at patch_all_modules_lock definition, below). 296 // lock-inversion comments at patch_all_modules_lock definition, below).
292 GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress]; 297 GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress];
293 298
294 ModuleEntryCopy() { 299 ModuleEntryCopy() {
295 modBaseAddr = NULL; 300 modBaseAddr = NULL;
296 modBaseSize = 0; 301 modBaseSize = 0;
297 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) 302 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++)
298 rgProcAddresses[i] = LibcInfo::static_fn(i); 303 rgProcAddresses[i] = LibcInfo::static_fn(i);
299 } 304 }
300 ModuleEntryCopy(const MODULEINFO& mi) { 305 ModuleEntryCopy(const MODULEINFO& mi) {
301 this->modBaseAddr = mi.lpBaseOfDll; 306 this->modBaseAddr = mi.lpBaseOfDll;
302 this->modBaseSize = mi.SizeOfImage; 307 this->modBaseSize = mi.SizeOfImage;
303 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) 308 LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
304 rgProcAddresses[i] = (GenericFnPtr)::GetProcAddress( 309 for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) {
310 FARPROC target = ::GetProcAddress(
305 reinterpret_cast<const HMODULE>(mi.lpBaseOfDll), 311 reinterpret_cast<const HMODULE>(mi.lpBaseOfDll),
306 LibcInfo::function_name(i)); 312 LibcInfo::function_name(i));
313 // Sometimes a DLL forwards a function to a function in another
314 // DLL. We don't want to patch those forwarded functions --
315 // they'll get patched when the other DLL is processed.
316 if (target >= modBaseAddr && target < modEndAddr)
317 rgProcAddresses[i] = (GenericFnPtr)target;
318 else
319 rgProcAddresses[i] = (GenericFnPtr)NULL;
320 }
307 } 321 }
308 }; 322 };
309 323
310 // This class is easier because there's only one of them. 324 // This class is easier because there's only one of them.
311 class WindowsInfo { 325 class WindowsInfo {
312 public: 326 public:
313 void Patch(); 327 void Patch();
314 void Unpatch(); 328 void Unpatch();
315 329
316 private: 330 private:
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 "malloc", "free", "realloc", "calloc", 397 "malloc", "free", "realloc", "calloc",
384 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, 398 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray,
385 // Ideally we should patch the nothrow versions of new/delete, but 399 // Ideally we should patch the nothrow versions of new/delete, but
386 // at least in msvcrt, nothrow-new machine-code is of a type we 400 // at least in msvcrt, nothrow-new machine-code is of a type we
387 // can't patch. Since these are relatively rare, I'm hoping it's ok 401 // can't patch. Since these are relatively rare, I'm hoping it's ok
388 // not to patch them. (NULL name turns off patching.) 402 // not to patch them. (NULL name turns off patching.)
389 NULL, // kMangledNewNothrow, 403 NULL, // kMangledNewNothrow,
390 NULL, // kMangledNewArrayNothrow, 404 NULL, // kMangledNewArrayNothrow,
391 NULL, // kMangledDeleteNothrow, 405 NULL, // kMangledDeleteNothrow,
392 NULL, // kMangledDeleteArrayNothrow, 406 NULL, // kMangledDeleteArrayNothrow,
393 "_msize", "_expand", "_aligned_malloc", "_aligned_free", 407 "_msize", "_expand",
394 }; 408 };
395 409
396 // For mingw, I can't patch the new/delete here, because the 410 // For mingw, I can't patch the new/delete here, because the
397 // instructions are too small to patch. Luckily, they're so small 411 // instructions are too small to patch. Luckily, they're so small
398 // because all they do is call into malloc/free, so they still end up 412 // because all they do is call into malloc/free, so they still end up
399 // calling tcmalloc routines, and we don't actually lose anything 413 // calling tcmalloc routines, and we don't actually lose anything
400 // (except maybe some stacktrace goodness) by not patching. 414 // (except maybe some stacktrace goodness) by not patching.
401 const GenericFnPtr LibcInfo::static_fn_[] = { 415 const GenericFnPtr LibcInfo::static_fn_[] = {
402 (GenericFnPtr)&::malloc, 416 (GenericFnPtr)&::malloc,
403 (GenericFnPtr)&::free, 417 (GenericFnPtr)&::free,
(...skipping 10 matching lines...) Expand all
414 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, 428 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new,
415 (GenericFnPtr) 429 (GenericFnPtr)
416 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], 430 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[],
417 (GenericFnPtr) 431 (GenericFnPtr)
418 (void(*)(void*, struct std::nothrow_t const &))&::operator delete, 432 (void(*)(void*, struct std::nothrow_t const &))&::operator delete,
419 (GenericFnPtr) 433 (GenericFnPtr)
420 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], 434 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[],
421 #endif 435 #endif
422 (GenericFnPtr)&::_msize, 436 (GenericFnPtr)&::_msize,
423 (GenericFnPtr)&::_expand, 437 (GenericFnPtr)&::_expand,
424 #ifdef PERFTOOLS_NO_ALIGNED_MALLOC // for older versions of mingw
425 // _aligned_malloc isn't always available in mingw, so don't try to patch.
426 (GenericFnPtr)NULL,
427 (GenericFnPtr)NULL,
428 #else
429 (GenericFnPtr)&::_aligned_malloc,
430 (GenericFnPtr)&::_aligned_free,
431 #endif
432 }; 438 };
433 439
434 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = { 440 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
435 // This will get filled in at run-time, as patching is done. 441 // This will get filled in at run-time, as patching is done.
436 }; 442 };
437 443
438 template<int T> 444 template<int T>
439 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = { 445 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
440 (GenericFnPtr)&Perftools_malloc, 446 (GenericFnPtr)&Perftools_malloc,
441 (GenericFnPtr)&Perftools_free, 447 (GenericFnPtr)&Perftools_free,
442 (GenericFnPtr)&Perftools_realloc, 448 (GenericFnPtr)&Perftools_realloc,
443 (GenericFnPtr)&Perftools_calloc, 449 (GenericFnPtr)&Perftools_calloc,
444 (GenericFnPtr)&Perftools_new, 450 (GenericFnPtr)&Perftools_new,
445 (GenericFnPtr)&Perftools_newarray, 451 (GenericFnPtr)&Perftools_newarray,
446 (GenericFnPtr)&Perftools_delete, 452 (GenericFnPtr)&Perftools_delete,
447 (GenericFnPtr)&Perftools_deletearray, 453 (GenericFnPtr)&Perftools_deletearray,
448 (GenericFnPtr)&Perftools_new_nothrow, 454 (GenericFnPtr)&Perftools_new_nothrow,
449 (GenericFnPtr)&Perftools_newarray_nothrow, 455 (GenericFnPtr)&Perftools_newarray_nothrow,
450 (GenericFnPtr)&Perftools_delete_nothrow, 456 (GenericFnPtr)&Perftools_delete_nothrow,
451 (GenericFnPtr)&Perftools_deletearray_nothrow, 457 (GenericFnPtr)&Perftools_deletearray_nothrow,
452 (GenericFnPtr)&Perftools__msize, 458 (GenericFnPtr)&Perftools__msize,
453 (GenericFnPtr)&Perftools__expand, 459 (GenericFnPtr)&Perftools__expand,
454 (GenericFnPtr)&Perftools__aligned_malloc,
455 (GenericFnPtr)&Perftools__aligned_free,
456 }; 460 };
457 461
458 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { 462 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = {
459 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, 463 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc },
460 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, 464 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree },
461 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, 465 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx },
462 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, 466 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx },
463 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, 467 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx },
464 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, 468 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile },
465 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, 469 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW },
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 905
902 // We need to define this because internal windows functions like to 906 // We need to define this because internal windows functions like to
903 // call into it(?). _expand() is like realloc but doesn't move the 907 // call into it(?). _expand() is like realloc but doesn't move the
904 // pointer. We punt, which will cause callers to fall back on realloc. 908 // pointer. We punt, which will cause callers to fall back on realloc.
905 template<int T> 909 template<int T>
906 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, 910 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr,
907 size_t size) __THROW { 911 size_t size) __THROW {
908 return NULL; 912 return NULL;
909 } 913 }
910 914
911 template<int T>
912 void* LibcInfoWithPatchFunctions<T>::Perftools__aligned_malloc(size_t size,
913 size_t alignment)
914 __THROW {
915 void* result = do_memalign_or_cpp_memalign(alignment, size);
916 MallocHook::InvokeNewHook(result, size);
917 return result;
918 }
919
920 template<int T>
921 void LibcInfoWithPatchFunctions<T>::Perftools__aligned_free(void *ptr) __THROW {
922 MallocHook::InvokeDeleteHook(ptr);
923 do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[k_Aligned_free]);
924 }
925
926 LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags, 915 LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
927 DWORD_PTR dwBytes) { 916 DWORD_PTR dwBytes) {
928 LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR)) 917 LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR))
929 function_info_[kHeapAlloc].origstub_fn)( 918 function_info_[kHeapAlloc].origstub_fn)(
930 hHeap, dwFlags, dwBytes); 919 hHeap, dwFlags, dwBytes);
931 MallocHook::InvokeNewHook(result, dwBytes); 920 MallocHook::InvokeNewHook(result, dwBytes);
932 return result; 921 return result;
933 } 922 }
934 923
935 BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags, 924 BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 if (libc1.is_valid()) libc1.Unpatch(); 1067 if (libc1.is_valid()) libc1.Unpatch();
1079 if (libc2.is_valid()) libc2.Unpatch(); 1068 if (libc2.is_valid()) libc2.Unpatch();
1080 if (libc3.is_valid()) libc3.Unpatch(); 1069 if (libc3.is_valid()) libc3.Unpatch();
1081 if (libc4.is_valid()) libc4.Unpatch(); 1070 if (libc4.is_valid()) libc4.Unpatch();
1082 if (libc5.is_valid()) libc5.Unpatch(); 1071 if (libc5.is_valid()) libc5.Unpatch();
1083 if (libc6.is_valid()) libc6.Unpatch(); 1072 if (libc6.is_valid()) libc6.Unpatch();
1084 if (libc7.is_valid()) libc7.Unpatch(); 1073 if (libc7.is_valid()) libc7.Unpatch();
1085 if (libc8.is_valid()) libc8.Unpatch(); 1074 if (libc8.is_valid()) libc8.Unpatch();
1086 } 1075 }
1087 #endif 1076 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698