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 "gperftools/malloc_hook.h" | 94 #include "google/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, | |
186 kNumFunctions | 184 kNumFunctions |
187 }; | 185 }; |
188 | 186 |
189 // 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 |
190 // 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 |
191 // 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 |
192 // 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 |
193 // 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 |
194 // each to be in its own array. :-( | 192 // each to be in its own array. :-( |
195 static const char* const function_name_[kNumFunctions]; | 193 static const char* const function_name_[kNumFunctions]; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 "malloc", "free", "realloc", "calloc", | 397 "malloc", "free", "realloc", "calloc", |
400 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, | 398 kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, |
401 // Ideally we should patch the nothrow versions of new/delete, but | 399 // Ideally we should patch the nothrow versions of new/delete, but |
402 // 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 |
403 // 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 |
404 // not to patch them. (NULL name turns off patching.) | 402 // not to patch them. (NULL name turns off patching.) |
405 NULL, // kMangledNewNothrow, | 403 NULL, // kMangledNewNothrow, |
406 NULL, // kMangledNewArrayNothrow, | 404 NULL, // kMangledNewArrayNothrow, |
407 NULL, // kMangledDeleteNothrow, | 405 NULL, // kMangledDeleteNothrow, |
408 NULL, // kMangledDeleteArrayNothrow, | 406 NULL, // kMangledDeleteArrayNothrow, |
409 "_msize", "_expand", "_calloc_crt", | 407 "_msize", "_expand", |
410 }; | 408 }; |
411 | 409 |
412 // 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 |
413 // instructions are too small to patch. Luckily, they're so small | 411 // instructions are too small to patch. Luckily, they're so small |
414 // 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 |
415 // calling tcmalloc routines, and we don't actually lose anything | 413 // calling tcmalloc routines, and we don't actually lose anything |
416 // (except maybe some stacktrace goodness) by not patching. | 414 // (except maybe some stacktrace goodness) by not patching. |
417 const GenericFnPtr LibcInfo::static_fn_[] = { | 415 const GenericFnPtr LibcInfo::static_fn_[] = { |
418 (GenericFnPtr)&::malloc, | 416 (GenericFnPtr)&::malloc, |
419 (GenericFnPtr)&::free, | 417 (GenericFnPtr)&::free, |
(...skipping 10 matching lines...) Expand all Loading... |
430 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, | 428 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, |
431 (GenericFnPtr) | 429 (GenericFnPtr) |
432 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], | 430 (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], |
433 (GenericFnPtr) | 431 (GenericFnPtr) |
434 (void(*)(void*, struct std::nothrow_t const &))&::operator delete, | 432 (void(*)(void*, struct std::nothrow_t const &))&::operator delete, |
435 (GenericFnPtr) | 433 (GenericFnPtr) |
436 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], | 434 (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], |
437 #endif | 435 #endif |
438 (GenericFnPtr)&::_msize, | 436 (GenericFnPtr)&::_msize, |
439 (GenericFnPtr)&::_expand, | 437 (GenericFnPtr)&::_expand, |
440 (GenericFnPtr)&::calloc, | |
441 }; | 438 }; |
442 | 439 |
443 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = { | 440 template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = { |
444 // 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. |
445 }; | 442 }; |
446 | 443 |
447 template<int T> | 444 template<int T> |
448 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = { | 445 const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = { |
449 (GenericFnPtr)&Perftools_malloc, | 446 (GenericFnPtr)&Perftools_malloc, |
450 (GenericFnPtr)&Perftools_free, | 447 (GenericFnPtr)&Perftools_free, |
451 (GenericFnPtr)&Perftools_realloc, | 448 (GenericFnPtr)&Perftools_realloc, |
452 (GenericFnPtr)&Perftools_calloc, | 449 (GenericFnPtr)&Perftools_calloc, |
453 (GenericFnPtr)&Perftools_new, | 450 (GenericFnPtr)&Perftools_new, |
454 (GenericFnPtr)&Perftools_newarray, | 451 (GenericFnPtr)&Perftools_newarray, |
455 (GenericFnPtr)&Perftools_delete, | 452 (GenericFnPtr)&Perftools_delete, |
456 (GenericFnPtr)&Perftools_deletearray, | 453 (GenericFnPtr)&Perftools_deletearray, |
457 (GenericFnPtr)&Perftools_new_nothrow, | 454 (GenericFnPtr)&Perftools_new_nothrow, |
458 (GenericFnPtr)&Perftools_newarray_nothrow, | 455 (GenericFnPtr)&Perftools_newarray_nothrow, |
459 (GenericFnPtr)&Perftools_delete_nothrow, | 456 (GenericFnPtr)&Perftools_delete_nothrow, |
460 (GenericFnPtr)&Perftools_deletearray_nothrow, | 457 (GenericFnPtr)&Perftools_deletearray_nothrow, |
461 (GenericFnPtr)&Perftools__msize, | 458 (GenericFnPtr)&Perftools__msize, |
462 (GenericFnPtr)&Perftools__expand, | 459 (GenericFnPtr)&Perftools__expand, |
463 (GenericFnPtr)&Perftools_calloc, | |
464 }; | 460 }; |
465 | 461 |
466 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { | 462 /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { |
467 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, | 463 { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, |
468 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, | 464 { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, |
469 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, | 465 { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, |
470 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, | 466 { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, |
471 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, | 467 { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, |
472 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, | 468 { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, |
473 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, | 469 { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 } | 815 } |
820 if (new_size == 0) { | 816 if (new_size == 0) { |
821 MallocHook::InvokeDeleteHook(old_ptr); | 817 MallocHook::InvokeDeleteHook(old_ptr); |
822 do_free_with_callback(old_ptr, | 818 do_free_with_callback(old_ptr, |
823 (void (*)(void*))origstub_fn_[kFree]); | 819 (void (*)(void*))origstub_fn_[kFree]); |
824 return NULL; | 820 return NULL; |
825 } | 821 } |
826 return do_realloc_with_callback( | 822 return do_realloc_with_callback( |
827 old_ptr, new_size, | 823 old_ptr, new_size, |
828 (void (*)(void*))origstub_fn_[kFree], | 824 (void (*)(void*))origstub_fn_[kFree], |
829 (size_t (*)(const void*))origstub_fn_[k_Msize]); | 825 (size_t (*)(void*))origstub_fn_[k_Msize]); |
830 } | 826 } |
831 | 827 |
832 template<int T> | 828 template<int T> |
833 void* LibcInfoWithPatchFunctions<T>::Perftools_calloc( | 829 void* LibcInfoWithPatchFunctions<T>::Perftools_calloc( |
834 size_t n, size_t elem_size) __THROW { | 830 size_t n, size_t elem_size) __THROW { |
835 void* result = do_calloc(n, elem_size); | 831 void* result = do_calloc(n, elem_size); |
836 MallocHook::InvokeNewHook(result, n * elem_size); | 832 MallocHook::InvokeNewHook(result, n * elem_size); |
837 return result; | 833 return result; |
838 } | 834 } |
839 | 835 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 // _msize() lets you figure out how much space is reserved for a | 893 // _msize() lets you figure out how much space is reserved for a |
898 // pointer, in Windows. Even if applications don't call it, any DLL | 894 // pointer, in Windows. Even if applications don't call it, any DLL |
899 // with global constructors will call (transitively) something called | 895 // with global constructors will call (transitively) something called |
900 // __dllonexit_lk in order to make sure the destructors get called | 896 // __dllonexit_lk in order to make sure the destructors get called |
901 // when the dll unloads. And that will call msize -- horrible things | 897 // when the dll unloads. And that will call msize -- horrible things |
902 // can ensue if this is not hooked. Other parts of libc may also call | 898 // can ensue if this is not hooked. Other parts of libc may also call |
903 // this internally. | 899 // this internally. |
904 | 900 |
905 template<int T> | 901 template<int T> |
906 size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW { | 902 size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW { |
907 return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]
); | 903 return GetSizeWithCallback(ptr, (size_t (*)(void*))origstub_fn_[k_Msize]); |
908 } | 904 } |
909 | 905 |
910 // We need to define this because internal windows functions like to | 906 // We need to define this because internal windows functions like to |
911 // 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 |
912 // 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. |
913 template<int T> | 909 template<int T> |
914 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, | 910 void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr, |
915 size_t size) __THROW { | 911 size_t size) __THROW { |
916 return NULL; | 912 return NULL; |
917 } | 913 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 if (libc1.is_valid()) libc1.Unpatch(); | 1067 if (libc1.is_valid()) libc1.Unpatch(); |
1072 if (libc2.is_valid()) libc2.Unpatch(); | 1068 if (libc2.is_valid()) libc2.Unpatch(); |
1073 if (libc3.is_valid()) libc3.Unpatch(); | 1069 if (libc3.is_valid()) libc3.Unpatch(); |
1074 if (libc4.is_valid()) libc4.Unpatch(); | 1070 if (libc4.is_valid()) libc4.Unpatch(); |
1075 if (libc5.is_valid()) libc5.Unpatch(); | 1071 if (libc5.is_valid()) libc5.Unpatch(); |
1076 if (libc6.is_valid()) libc6.Unpatch(); | 1072 if (libc6.is_valid()) libc6.Unpatch(); |
1077 if (libc7.is_valid()) libc7.Unpatch(); | 1073 if (libc7.is_valid()) libc7.Unpatch(); |
1078 if (libc8.is_valid()) libc8.Unpatch(); | 1074 if (libc8.is_valid()) libc8.Unpatch(); |
1079 } | 1075 } |
1080 #endif | 1076 #endif |
OLD | NEW |