| 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 |