OLD | NEW |
1 // Copyright (c) 2007, Google Inc. | 1 // Copyright (c) 2007, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 | 84 |
85 #include <windows.h> | 85 #include <windows.h> |
86 #include <stdio.h> | 86 #include <stdio.h> |
87 #include <malloc.h> // for _msize and _expand | 87 #include <malloc.h> // for _msize and _expand |
88 #include <Psapi.h> // for EnumProcessModules, GetModuleInformation, etc. | 88 #include <Psapi.h> // for EnumProcessModules, GetModuleInformation, etc. |
89 #include <set> | 89 #include <set> |
90 #include <map> | 90 #include <map> |
91 #include <vector> | 91 #include <vector> |
92 #include <base/logging.h> | 92 #include <base/logging.h> |
93 #include "base/spinlock.h" | 93 #include "base/spinlock.h" |
94 #include "google/malloc_hook.h" | 94 #include "gperftools/malloc_hook.h" |
95 #include "malloc_hook-inl.h" | 95 #include "malloc_hook-inl.h" |
96 #include "preamble_patcher.h" | 96 #include "preamble_patcher.h" |
97 | 97 |
98 // The maximum number of modules we allow to be in one executable | 98 // The maximum number of modules we allow to be in one executable |
99 const int kMaxModules = 8182; | 99 const int kMaxModules = 8182; |
100 | 100 |
101 // These are hard-coded, unfortunately. :-( They are also probably | 101 // These are hard-coded, unfortunately. :-( They are also probably |
102 // compiler specific. See get_mangled_names.cc, in this directory, | 102 // compiler specific. See get_mangled_names.cc, in this directory, |
103 // for instructions on how to update these names for your compiler. | 103 // for instructions on how to update these names for your compiler. |
104 const char kMangledNew[] = "??2@YAPAXI@Z"; | 104 const char kMangledNew[] = "??2@YAPAXI@Z"; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 this->module_base_address_ = that.module_base_address_; | 174 this->module_base_address_ = that.module_base_address_; |
175 this->module_base_size_ = that.module_base_size_; | 175 this->module_base_size_ = that.module_base_size_; |
176 } | 176 } |
177 | 177 |
178 enum { | 178 enum { |
179 kMalloc, kFree, kRealloc, kCalloc, | 179 kMalloc, kFree, kRealloc, kCalloc, |
180 kNew, kNewArray, kDelete, kDeleteArray, | 180 kNew, kNewArray, kDelete, kDeleteArray, |
181 kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow, | 181 kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow, |
182 // These are windows-only functions from malloc.h | 182 // These are windows-only functions from malloc.h |
183 k_Msize, k_Expand, | 183 k_Msize, k_Expand, |
| 184 // A MS CRT "internal" function, implemented using _calloc_impl |
| 185 k_CallocCrt, |
184 kNumFunctions | 186 kNumFunctions |
185 }; | 187 }; |
186 | 188 |
187 // I'd like to put these together in a struct (perhaps in the | 189 // I'd like to put these together in a struct (perhaps in the |
188 // subclass, so we can put in perftools_fn_ as well), but vc8 seems | 190 // subclass, so we can put in perftools_fn_ as well), but vc8 seems |
189 // to have a bug where it doesn't initialize the struct properly if | 191 // to have a bug where it doesn't initialize the struct properly if |
190 // we try to take the address of a function that's not yet loaded | 192 // we try to take the address of a function that's not yet loaded |
191 // from a dll, as is the common case for static_fn_. So we need | 193 // from a dll, as is the common case for static_fn_. So we need |
192 // each to be in its own array. :-( | 194 // each to be in its own array. :-( |
193 static const char* const function_name_[kNumFunctions]; | 195 static const char* const function_name_[kNumFunctions]; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 "malloc", "free", "realloc", "calloc", | 399 "malloc", "free", "realloc", "calloc", |
398 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, | 400 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, |
399 // Ideally we should patch the nothrow versions of new/delete, but | 401 // Ideally we should patch the nothrow versions of new/delete, but |
400 // at least in msvcrt, nothrow-new machine-code is of a type we | 402 // at least in msvcrt, nothrow-new machine-code is of a type we |
401 // can't patch. Since these are relatively rare, I'm hoping it's ok | 403 // can't patch. Since these are relatively rare, I'm hoping it's ok |
402 // not to patch them. (NULL name turns off patching.) | 404 // not to patch them. (NULL name turns off patching.) |
403 NULL, // kMangledNewNothrow, | 405 NULL, // kMangledNewNothrow, |
404 NULL, // kMangledNewArrayNothrow, | 406 NULL, // kMangledNewArrayNothrow, |
405 NULL, // kMangledDeleteNothrow, | 407 NULL, // kMangledDeleteNothrow, |
406 NULL, // kMangledDeleteArrayNothrow, | 408 NULL, // kMangledDeleteArrayNothrow, |
407 "_msize", "_expand", | 409 "_msize", "_expand", "_calloc_crt", |
408 }; | 410 }; |
409 | 411 |
410 // For mingw, I can't patch the new/delete here, because the | 412 // For mingw, I can't patch the new/delete here, because the |
411 // instructions are too small to patch. Luckily, they're so small | 413 // instructions are too small to patch. Luckily, they're so small |
412 // because all they do is call into malloc/free, so they still end up | 414 // because all they do is call into malloc/free, so they still end up |
413 // calling tcmalloc routines, and we don't actually lose anything | 415 // calling tcmalloc routines, and we don't actually lose anything |
414 // (except maybe some stacktrace goodness) by not patching. | 416 // (except maybe some stacktrace goodness) by not patching. |
415 const GenericFnPtr LibcInfo::static_fn_[] = { | 417 const GenericFnPtr LibcInfo::static_fn_[] = { |
416 (GenericFnPtr)&::malloc, | 418 (GenericFnPtr)&::malloc, |
417 (GenericFnPtr)&::free, | 419 (GenericFnPtr)&::free, |
(...skipping 10 matching lines...) Expand all Loading... |
428 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, | 430 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, |
429 (GenericFnPtr) | 431 (GenericFnPtr) |
430 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], | 432 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], |
431 (GenericFnPtr) | 433 (GenericFnPtr) |
432 (void(*)(void*, struct std::nothrow_t const &))&::operator delete, | 434 (void(*)(void*, struct std::nothrow_t const &))&::operator delete, |
433 (GenericFnPtr) | 435 (GenericFnPtr) |
434 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], | 436 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], |
435 #endif | 437 #endif |
436 (GenericFnPtr)&::_msize, | 438 (GenericFnPtr)&::_msize, |
437 (GenericFnPtr)&::_expand, | 439 (GenericFnPtr)&::_expand, |
| 440 (GenericFnPtr)&::calloc, |
438 }; | 441 }; |
439 | 442 |
440 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = { | 443 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = { |
441 // This will get filled in at run-time, as patching is done. | 444 // This will get filled in at run-time, as patching is done. |
442 }; | 445 }; |
443 | 446 |
444 template<int T> | 447 template<int T> |
445 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = { | 448 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = { |
446 (GenericFnPtr)&Perftools_malloc, | 449 (GenericFnPtr)&Perftools_malloc, |
447 (GenericFnPtr)&Perftools_free, | 450 (GenericFnPtr)&Perftools_free, |
448 (GenericFnPtr)&Perftools_realloc, | 451 (GenericFnPtr)&Perftools_realloc, |
449 (GenericFnPtr)&Perftools_calloc, | 452 (GenericFnPtr)&Perftools_calloc, |
450 (GenericFnPtr)&Perftools_new, | 453 (GenericFnPtr)&Perftools_new, |
451 (GenericFnPtr)&Perftools_newarray, | 454 (GenericFnPtr)&Perftools_newarray, |
452 (GenericFnPtr)&Perftools_delete, | 455 (GenericFnPtr)&Perftools_delete, |
453 (GenericFnPtr)&Perftools_deletearray, | 456 (GenericFnPtr)&Perftools_deletearray, |
454 (GenericFnPtr)&Perftools_new_nothrow, | 457 (GenericFnPtr)&Perftools_new_nothrow, |
455 (GenericFnPtr)&Perftools_newarray_nothrow, | 458 (GenericFnPtr)&Perftools_newarray_nothrow, |
456 (GenericFnPtr)&Perftools_delete_nothrow, | 459 (GenericFnPtr)&Perftools_delete_nothrow, |
457 (GenericFnPtr)&Perftools_deletearray_nothrow, | 460 (GenericFnPtr)&Perftools_deletearray_nothrow, |
458 (GenericFnPtr)&Perftools__msize, | 461 (GenericFnPtr)&Perftools__msize, |
459 (GenericFnPtr)&Perftools__expand, | 462 (GenericFnPtr)&Perftools__expand, |
| 463 (GenericFnPtr)&Perftools_calloc, |
460 }; | 464 }; |
461 | 465 |
462 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { | 466 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { |
463 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, | 467 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, |
464 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, | 468 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, |
465 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, | 469 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, |
466 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, | 470 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, |
467 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, | 471 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, |
468 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, | 472 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, |
469 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, | 473 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 } | 819 } |
816 if (new_size == 0) { | 820 if (new_size == 0) { |
817 MallocHook::InvokeDeleteHook(old_ptr); | 821 MallocHook::InvokeDeleteHook(old_ptr); |
818 do_free_with_callback(old_ptr, | 822 do_free_with_callback(old_ptr, |
819 (void (*)(void*))origstub_fn_[kFree]); | 823 (void (*)(void*))origstub_fn_[kFree]); |
820 return NULL; | 824 return NULL; |
821 } | 825 } |
822 return do_realloc_with_callback( | 826 return do_realloc_with_callback( |
823 old_ptr, new_size, | 827 old_ptr, new_size, |
824 (void (*)(void*))origstub_fn_[kFree], | 828 (void (*)(void*))origstub_fn_[kFree], |
825 (size_t (*)(void*))origstub_fn_[k_Msize]); | 829 (size_t (*)(const void*))origstub_fn_[k_Msize]); |
826 } | 830 } |
827 | 831 |
828 template<int T> | 832 template<int T> |
829 void* LibcInfoWithPatchFunctions<T>::Perftools_calloc( | 833 void* LibcInfoWithPatchFunctions<T>::Perftools_calloc( |
830 size_t n, size_t elem_size) __THROW { | 834 size_t n, size_t elem_size) __THROW { |
831 void* result = do_calloc(n, elem_size); | 835 void* result = do_calloc(n, elem_size); |
832 MallocHook::InvokeNewHook(result, n * elem_size); | 836 MallocHook::InvokeNewHook(result, n * elem_size); |
833 return result; | 837 return result; |
834 } | 838 } |
835 | 839 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 // _msize() lets you figure out how much space is reserved for a | 897 // _msize() lets you figure out how much space is reserved for a |
894 // pointer, in Windows. Even if applications don't call it, any DLL | 898 // pointer, in Windows. Even if applications don't call it, any DLL |
895 // with global constructors will call (transitively) something called | 899 // with global constructors will call (transitively) something called |
896 // __dllonexit_lk in order to make sure the destructors get called | 900 // __dllonexit_lk in order to make sure the destructors get called |
897 // when the dll unloads. And that will call msize -- horrible things | 901 // when the dll unloads. And that will call msize -- horrible things |
898 // can ensue if this is not hooked. Other parts of libc may also call | 902 // can ensue if this is not hooked. Other parts of libc may also call |
899 // this internally. | 903 // this internally. |
900 | 904 |
901 template<int T> | 905 template<int T> |
902 size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW { | 906 size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW { |
903 return GetSizeWithCallback(ptr, (size_t (*)(void*))origstub_fn_[k_Msize]); | 907 return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]
); |
904 } | 908 } |
905 | 909 |
906 // We need to define this because internal windows functions like to | 910 // We need to define this because internal windows functions like to |
907 // call into it(?). _expand() is like realloc but doesn't move the | 911 // call into it(?). _expand() is like realloc but doesn't move the |
908 // pointer. We punt, which will cause callers to fall back on realloc. | 912 // pointer. We punt, which will cause callers to fall back on realloc. |
909 template<int T> | 913 template<int T> |
910 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, | 914 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, |
911 size_t size) __THROW { | 915 size_t size) __THROW { |
912 return NULL; | 916 return NULL; |
913 } | 917 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 if (libc1.is_valid()) libc1.Unpatch(); | 1071 if (libc1.is_valid()) libc1.Unpatch(); |
1068 if (libc2.is_valid()) libc2.Unpatch(); | 1072 if (libc2.is_valid()) libc2.Unpatch(); |
1069 if (libc3.is_valid()) libc3.Unpatch(); | 1073 if (libc3.is_valid()) libc3.Unpatch(); |
1070 if (libc4.is_valid()) libc4.Unpatch(); | 1074 if (libc4.is_valid()) libc4.Unpatch(); |
1071 if (libc5.is_valid()) libc5.Unpatch(); | 1075 if (libc5.is_valid()) libc5.Unpatch(); |
1072 if (libc6.is_valid()) libc6.Unpatch(); | 1076 if (libc6.is_valid()) libc6.Unpatch(); |
1073 if (libc7.is_valid()) libc7.Unpatch(); | 1077 if (libc7.is_valid()) libc7.Unpatch(); |
1074 if (libc8.is_valid()) libc8.Unpatch(); | 1078 if (libc8.is_valid()) libc8.Unpatch(); |
1075 } | 1079 } |
1076 #endif | 1080 #endif |
OLD | NEW |