patch_functions.cc 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. // Copyright (c) 2007, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. //
  30. // ---
  31. // Author: Craig Silverstein
  32. //
  33. // The main purpose of this file is to patch the libc allocation
  34. // routines (malloc and friends, but also _msize and other
  35. // windows-specific libc-style routines). However, we also patch
  36. // windows routines to do accounting. We do better at the former than
  37. // the latter. Here are some comments from Paul Pluzhnikov about what
  38. // it might take to do a really good job patching windows routines to
  39. // keep track of memory usage:
  40. //
  41. // "You should intercept at least the following:
  42. // HeapCreate HeapDestroy HeapAlloc HeapReAlloc HeapFree
  43. // RtlCreateHeap RtlDestroyHeap RtlAllocateHeap RtlFreeHeap
  44. // malloc calloc realloc free
  45. // malloc_dbg calloc_dbg realloc_dbg free_dbg
  46. // Some of these call the other ones (but not always), sometimes
  47. // recursively (i.e. HeapCreate may call HeapAlloc on a different
  48. // heap, IIRC)."
  49. //
  50. // Since Paul didn't mention VirtualAllocEx, he may not have even been
  51. // considering all the mmap-like functions that windows has (or he may
  52. // just be ignoring it because he's seen we already patch it). Of the
  53. // above, we do not patch the *_dbg functions, and of the windows
  54. // functions, we only patch HeapAlloc and HeapFree.
  55. //
  56. // The *_dbg functions come into play with /MDd, /MTd, and /MLd,
  57. // probably. It may be ok to just turn off tcmalloc in those cases --
  58. // if the user wants the windows debug malloc, they probably don't
  59. // want tcmalloc! We should also test with all of /MD, /MT, and /ML,
  60. // which we're not currently doing.
  61. // TODO(csilvers): try to do better here? Paul does conclude:
  62. // "Keeping track of all of this was a nightmare."
  63. #ifndef _WIN32
  64. # error You should only be including windows/patch_functions.cc in a windows environment!
  65. #endif
  66. #include <config.h>
  67. #ifdef WIN32_OVERRIDE_ALLOCATORS
  68. #error This file is intended for patching allocators - use override_functions.cc instead.
  69. #endif
  70. // We use psapi. Non-MSVC systems will have to link this in themselves.
  71. #ifdef _MSC_VER
  72. #pragma comment(lib, "Psapi.lib")
  73. #endif
  74. // Make sure we always use the 'old' names of the psapi functions.
  75. #ifndef PSAPI_VERSION
  76. #define PSAPI_VERSION 1
  77. #endif
  78. #include <windows.h>
  79. #include <stdio.h>
  80. #include <malloc.h> // for _msize and _expand
  81. #include <psapi.h> // for EnumProcessModules, GetModuleInformation, etc.
  82. #include <set>
  83. #include <map>
  84. #include <vector>
  85. #include <base/logging.h>
  86. #include "base/spinlock.h"
  87. #include "gperftools/malloc_hook.h"
  88. #include "malloc_hook-inl.h"
  89. #include "preamble_patcher.h"
  90. // The maximum number of modules we allow to be in one executable
  91. const int kMaxModules = 8182;
  92. // These are hard-coded, unfortunately. :-( They are also probably
  93. // compiler specific. See get_mangled_names.cc, in this directory,
  94. // for instructions on how to update these names for your compiler.
  95. #ifdef _WIN64
  96. const char kMangledNew[] = "??2@YAPEAX_K@Z";
  97. const char kMangledNewArray[] = "??_U@YAPEAX_K@Z";
  98. const char kMangledDelete[] = "??3@YAXPEAX@Z";
  99. const char kMangledDeleteArray[] = "??_V@YAXPEAX@Z";
  100. const char kMangledNewNothrow[] = "??2@YAPEAX_KAEBUnothrow_t@std@@@Z";
  101. const char kMangledNewArrayNothrow[] = "??_U@YAPEAX_KAEBUnothrow_t@std@@@Z";
  102. const char kMangledDeleteNothrow[] = "??3@YAXPEAXAEBUnothrow_t@std@@@Z";
  103. const char kMangledDeleteArrayNothrow[] = "??_V@YAXPEAXAEBUnothrow_t@std@@@Z";
  104. #else
  105. const char kMangledNew[] = "??2@YAPAXI@Z";
  106. const char kMangledNewArray[] = "??_U@YAPAXI@Z";
  107. const char kMangledDelete[] = "??3@YAXPAX@Z";
  108. const char kMangledDeleteArray[] = "??_V@YAXPAX@Z";
  109. const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z";
  110. const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z";
  111. const char kMangledDeleteNothrow[] = "??3@YAXPAXABUnothrow_t@std@@@Z";
  112. const char kMangledDeleteArrayNothrow[] = "??_V@YAXPAXABUnothrow_t@std@@@Z";
  113. #endif
  114. // This is an unused but exported symbol that we can use to tell the
  115. // MSVC linker to bring in libtcmalloc, via the /INCLUDE linker flag.
  116. // Without this, the linker will likely decide that libtcmalloc.dll
  117. // doesn't add anything to the executable (since it does all its work
  118. // through patching, which the linker can't see), and ignore it
  119. // entirely. (The name 'tcmalloc' is already reserved for a
  120. // namespace. I'd rather export a variable named "_tcmalloc", but I
  121. // couldn't figure out how to get that to work. This function exports
  122. // the symbol "__tcmalloc".)
  123. extern "C" PERFTOOLS_DLL_DECL void _tcmalloc();
  124. void _tcmalloc() { }
  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. namespace { // most everything here is in an unnamed namespace
  130. typedef void (*GenericFnPtr)();
  131. using sidestep::PreamblePatcher;
  132. struct ModuleEntryCopy; // defined below
  133. // These functions are how we override the memory allocation
  134. // functions, just like tcmalloc.cc and malloc_hook.cc do.
  135. // This is information about the routines we're patching, for a given
  136. // module that implements libc memory routines. A single executable
  137. // can have several libc implementations running about (in different
  138. // .dll's), and we need to patch/unpatch them all. This defines
  139. // everything except the new functions we're patching in, which
  140. // are defined in LibcFunctions, below.
  141. class LibcInfo {
  142. public:
  143. LibcInfo() {
  144. memset(this, 0, sizeof(*this)); // easiest way to initialize the array
  145. }
  146. bool patched() const { return is_valid(); }
  147. void set_is_valid(bool b) { is_valid_ = b; }
  148. // According to http://msdn.microsoft.com/en-us/library/ms684229(VS.85).aspx:
  149. // "The load address of a module (lpBaseOfDll) is the same as the HMODULE
  150. // value."
  151. HMODULE hmodule() const {
  152. return reinterpret_cast<HMODULE>(const_cast<void*>(module_base_address_));
  153. }
  154. // Populates all the windows_fn_[] vars based on our module info.
  155. // Returns false if windows_fn_ is all NULL's, because there's
  156. // nothing to patch. Also populates the rest of the module_entry
  157. // info, such as the module's name.
  158. bool PopulateWindowsFn(const ModuleEntryCopy& module_entry);
  159. protected:
  160. void CopyFrom(const LibcInfo& that) {
  161. if (this == &that)
  162. return;
  163. this->is_valid_ = that.is_valid_;
  164. memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_));
  165. this->module_base_address_ = that.module_base_address_;
  166. this->module_base_size_ = that.module_base_size_;
  167. }
  168. enum {
  169. kMalloc, kFree, kRealloc, kCalloc,
  170. kNew, kNewArray, kDelete, kDeleteArray,
  171. kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow,
  172. // These are windows-only functions from malloc.h
  173. k_Msize, k_Expand,
  174. // A MS CRT "internal" function, implemented using _calloc_impl
  175. k_CallocCrt,
  176. kNumFunctions
  177. };
  178. // I'd like to put these together in a struct (perhaps in the
  179. // subclass, so we can put in perftools_fn_ as well), but vc8 seems
  180. // to have a bug where it doesn't initialize the struct properly if
  181. // we try to take the address of a function that's not yet loaded
  182. // from a dll, as is the common case for static_fn_. So we need
  183. // each to be in its own array. :-(
  184. static const char* const function_name_[kNumFunctions];
  185. // This function is only used when statically linking the binary.
  186. // In that case, loading malloc/etc from the dll (via
  187. // PatchOneModule) won't work, since there are no dlls. Instead,
  188. // you just want to be taking the address of malloc/etc directly.
  189. // In the common, non-static-link case, these pointers will all be
  190. // NULL, since this initializer runs before msvcrt.dll is loaded.
  191. static const GenericFnPtr static_fn_[kNumFunctions];
  192. // This is the address of the function we are going to patch
  193. // (malloc, etc). Other info about the function is in the
  194. // patch-specific subclasses, below.
  195. GenericFnPtr windows_fn_[kNumFunctions];
  196. // This is set to true when this structure is initialized (because
  197. // we're patching a new library) and set to false when it's
  198. // uninitialized (because we've freed that library).
  199. bool is_valid_;
  200. const void *module_base_address_;
  201. size_t module_base_size_;
  202. public:
  203. // These shouldn't have to be public, since only subclasses of
  204. // LibcInfo need it, but they do. Maybe something to do with
  205. // templates. Shrug. I hide them down here so users won't see
  206. // them. :-) (OK, I also need to define ctrgProcAddress late.)
  207. bool is_valid() const { return is_valid_; }
  208. GenericFnPtr windows_fn(int ifunction) const {
  209. return windows_fn_[ifunction];
  210. }
  211. // These three are needed by ModuleEntryCopy.
  212. static const int ctrgProcAddress = kNumFunctions;
  213. static GenericFnPtr static_fn(int ifunction) {
  214. return static_fn_[ifunction];
  215. }
  216. static const char* const function_name(int ifunction) {
  217. return function_name_[ifunction];
  218. }
  219. };
  220. // Template trickiness: logically, a LibcInfo would include
  221. // Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a
  222. // given module, these three go together. And in fact,
  223. // Perftools_malloc_ may need to call origstub_malloc_, which means we
  224. // either need to change Perftools_malloc_ to take origstub_malloc_ as
  225. // an argument -- unfortunately impossible since it needs to keep the
  226. // same API as normal malloc -- or we need to write a different
  227. // version of Perftools_malloc_ for each LibcInfo instance we create.
  228. // We choose the second route, and use templates to implement it (we
  229. // could have also used macros). So to get multiple versions
  230. // of the struct, we say "struct<1> var1; struct<2> var2;". The price
  231. // we pay is some code duplication, and more annoying, each instance
  232. // of this var is a separate type.
  233. template<int> class LibcInfoWithPatchFunctions : public LibcInfo {
  234. public:
  235. // me_info should have had PopulateWindowsFn() called on it, so the
  236. // module_* vars and windows_fn_ are set up.
  237. bool Patch(const LibcInfo& me_info);
  238. void Unpatch();
  239. private:
  240. // This holds the original function contents after we patch the function.
  241. // This has to be defined static in the subclass, because the perftools_fns
  242. // reference origstub_fn_.
  243. static GenericFnPtr origstub_fn_[kNumFunctions];
  244. // This is the function we want to patch in
  245. static const GenericFnPtr perftools_fn_[kNumFunctions];
  246. static void* Perftools_malloc(size_t size) __THROW;
  247. static void Perftools_free(void* ptr) __THROW;
  248. static void* Perftools_realloc(void* ptr, size_t size) __THROW;
  249. static void* Perftools_calloc(size_t nmemb, size_t size) __THROW;
  250. static void* Perftools_new(size_t size);
  251. static void* Perftools_newarray(size_t size);
  252. static void Perftools_delete(void *ptr);
  253. static void Perftools_deletearray(void *ptr);
  254. static void* Perftools_new_nothrow(size_t size,
  255. const std::nothrow_t&) __THROW;
  256. static void* Perftools_newarray_nothrow(size_t size,
  257. const std::nothrow_t&) __THROW;
  258. static void Perftools_delete_nothrow(void *ptr,
  259. const std::nothrow_t&) __THROW;
  260. static void Perftools_deletearray_nothrow(void *ptr,
  261. const std::nothrow_t&) __THROW;
  262. static size_t Perftools__msize(void *ptr) __THROW;
  263. static void* Perftools__expand(void *ptr, size_t size) __THROW;
  264. // malloc.h also defines these functions:
  265. // _aligned_malloc, _aligned_free,
  266. // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc
  267. // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea
  268. // But they seem pretty obscure, and I'm fine not overriding them for now.
  269. // It may be they all call into malloc/free anyway.
  270. };
  271. // This is a subset of MODDULEENTRY32, that we need for patching.
  272. struct ModuleEntryCopy {
  273. LPVOID modBaseAddr; // the same as hmodule
  274. DWORD modBaseSize;
  275. // This is not part of MODDULEENTRY32, but is needed to avoid making
  276. // windows syscalls while we're holding patch_all_modules_lock (see
  277. // lock-inversion comments at patch_all_modules_lock definition, below).
  278. GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress];
  279. ModuleEntryCopy() {
  280. modBaseAddr = NULL;
  281. modBaseSize = 0;
  282. for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++)
  283. rgProcAddresses[i] = LibcInfo::static_fn(i);
  284. }
  285. ModuleEntryCopy(const MODULEINFO& mi) {
  286. this->modBaseAddr = mi.lpBaseOfDll;
  287. this->modBaseSize = mi.SizeOfImage;
  288. LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
  289. for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) {
  290. FARPROC target = ::GetProcAddress(
  291. reinterpret_cast<const HMODULE>(mi.lpBaseOfDll),
  292. LibcInfo::function_name(i));
  293. // Sometimes a DLL forwards a function to a function in another
  294. // DLL. We don't want to patch those forwarded functions --
  295. // they'll get patched when the other DLL is processed.
  296. if (target >= modBaseAddr && target < modEndAddr)
  297. rgProcAddresses[i] = (GenericFnPtr)target;
  298. else
  299. rgProcAddresses[i] = (GenericFnPtr)NULL;
  300. }
  301. }
  302. };
  303. // This class is easier because there's only one of them.
  304. class WindowsInfo {
  305. public:
  306. void Patch();
  307. void Unpatch();
  308. private:
  309. // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead,
  310. // for pre-XP systems?
  311. enum {
  312. kHeapAlloc, kHeapFree, kVirtualAllocEx, kVirtualFreeEx,
  313. kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW, kFreeLibrary,
  314. kNumFunctions
  315. };
  316. struct FunctionInfo {
  317. const char* const name; // name of fn in a module (eg "malloc")
  318. GenericFnPtr windows_fn; // the fn whose name we call (&malloc)
  319. GenericFnPtr origstub_fn; // original fn contents after we patch
  320. const GenericFnPtr perftools_fn; // fn we want to patch in
  321. };
  322. static FunctionInfo function_info_[kNumFunctions];
  323. // A Windows-API equivalent of malloc and free
  324. static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
  325. DWORD_PTR dwBytes);
  326. static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
  327. LPVOID lpMem);
  328. // A Windows-API equivalent of mmap and munmap, for "anonymous regions"
  329. static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address,
  330. SIZE_T size, DWORD type,
  331. DWORD protect);
  332. static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
  333. SIZE_T size, DWORD type);
  334. // A Windows-API equivalent of mmap and munmap, for actual files
  335. static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject,
  336. DWORD dwDesiredAccess,
  337. DWORD dwFileOffsetHigh,
  338. DWORD dwFileOffsetLow,
  339. SIZE_T dwNumberOfBytesToMap,
  340. LPVOID lpBaseAddress);
  341. static BOOL WINAPI Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress);
  342. // We don't need the other 3 variants because they all call this one. */
  343. static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName,
  344. HANDLE hFile,
  345. DWORD dwFlags);
  346. static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule);
  347. };
  348. // If you run out, just add a few more to the array. You'll also need
  349. // to update the switch statement in PatchOneModule(), and the list in
  350. // UnpatchWindowsFunctions().
  351. // main_executable and main_executable_windows are two windows into
  352. // the same executable. One is responsible for patching the libc
  353. // routines that live in the main executable (if any) to use tcmalloc;
  354. // the other is responsible for patching the windows routines like
  355. // HeapAlloc/etc to use tcmalloc.
  356. static LibcInfoWithPatchFunctions<0> main_executable;
  357. static LibcInfoWithPatchFunctions<1> libc1;
  358. static LibcInfoWithPatchFunctions<2> libc2;
  359. static LibcInfoWithPatchFunctions<3> libc3;
  360. static LibcInfoWithPatchFunctions<4> libc4;
  361. static LibcInfoWithPatchFunctions<5> libc5;
  362. static LibcInfoWithPatchFunctions<6> libc6;
  363. static LibcInfoWithPatchFunctions<7> libc7;
  364. static LibcInfoWithPatchFunctions<8> libc8;
  365. static LibcInfo* g_module_libcs[] = {
  366. &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8
  367. };
  368. static WindowsInfo main_executable_windows;
  369. const char* const LibcInfo::function_name_[] = {
  370. "malloc", "free", "realloc", "calloc",
  371. kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray,
  372. // Ideally we should patch the nothrow versions of new/delete, but
  373. // at least in msvcrt, nothrow-new machine-code is of a type we
  374. // can't patch. Since these are relatively rare, I'm hoping it's ok
  375. // not to patch them. (NULL name turns off patching.)
  376. NULL, // kMangledNewNothrow,
  377. NULL, // kMangledNewArrayNothrow,
  378. NULL, // kMangledDeleteNothrow,
  379. NULL, // kMangledDeleteArrayNothrow,
  380. "_msize", "_expand", "_calloc_crt",
  381. };
  382. // For mingw, I can't patch the new/delete here, because the
  383. // instructions are too small to patch. Luckily, they're so small
  384. // because all they do is call into malloc/free, so they still end up
  385. // calling tcmalloc routines, and we don't actually lose anything
  386. // (except maybe some stacktrace goodness) by not patching.
  387. const GenericFnPtr LibcInfo::static_fn_[] = {
  388. (GenericFnPtr)&::malloc,
  389. (GenericFnPtr)&::free,
  390. (GenericFnPtr)&::realloc,
  391. (GenericFnPtr)&::calloc,
  392. #ifdef __MINGW32__
  393. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  394. #else
  395. (GenericFnPtr)(void*(*)(size_t))&::operator new,
  396. (GenericFnPtr)(void*(*)(size_t))&::operator new[],
  397. (GenericFnPtr)(void(*)(void*))&::operator delete,
  398. (GenericFnPtr)(void(*)(void*))&::operator delete[],
  399. (GenericFnPtr)
  400. (void*(*)(size_t, struct std::nothrow_t const &))&::operator new,
  401. (GenericFnPtr)
  402. (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[],
  403. (GenericFnPtr)
  404. (void(*)(void*, struct std::nothrow_t const &))&::operator delete,
  405. (GenericFnPtr)
  406. (void(*)(void*, struct std::nothrow_t const &))&::operator delete[],
  407. #endif
  408. (GenericFnPtr)&::_msize,
  409. (GenericFnPtr)&::_expand,
  410. (GenericFnPtr)&::calloc,
  411. };
  412. template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
  413. // This will get filled in at run-time, as patching is done.
  414. };
  415. template<int T>
  416. const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
  417. (GenericFnPtr)&Perftools_malloc,
  418. (GenericFnPtr)&Perftools_free,
  419. (GenericFnPtr)&Perftools_realloc,
  420. (GenericFnPtr)&Perftools_calloc,
  421. (GenericFnPtr)&Perftools_new,
  422. (GenericFnPtr)&Perftools_newarray,
  423. (GenericFnPtr)&Perftools_delete,
  424. (GenericFnPtr)&Perftools_deletearray,
  425. (GenericFnPtr)&Perftools_new_nothrow,
  426. (GenericFnPtr)&Perftools_newarray_nothrow,
  427. (GenericFnPtr)&Perftools_delete_nothrow,
  428. (GenericFnPtr)&Perftools_deletearray_nothrow,
  429. (GenericFnPtr)&Perftools__msize,
  430. (GenericFnPtr)&Perftools__expand,
  431. (GenericFnPtr)&Perftools_calloc,
  432. };
  433. /*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = {
  434. { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc },
  435. { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree },
  436. { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx },
  437. { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx },
  438. { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx },
  439. { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile },
  440. { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW },
  441. { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary },
  442. };
  443. bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) {
  444. // First, store the location of the function to patch before
  445. // patching it. If none of these functions are found in the module,
  446. // then this module has no libc in it, and we just return false.
  447. for (int i = 0; i < kNumFunctions; i++) {
  448. if (!function_name_[i]) // we can turn off patching by unsetting name
  449. continue;
  450. // The ::GetProcAddress calls were done in the ModuleEntryCopy
  451. // constructor, so we don't have to make any windows calls here.
  452. const GenericFnPtr fn = module_entry.rgProcAddresses[i];
  453. if (fn) {
  454. windows_fn_[i] = PreamblePatcher::ResolveTarget(fn);
  455. }
  456. }
  457. // Some modules use the same function pointer for new and new[]. If
  458. // we find that, set one of the pointers to NULL so we don't double-
  459. // patch. Same may happen with new and nothrow-new, or even new[]
  460. // and nothrow-new. It's easiest just to check each fn-ptr against
  461. // every other.
  462. for (int i = 0; i < kNumFunctions; i++) {
  463. for (int j = i+1; j < kNumFunctions; j++) {
  464. if (windows_fn_[i] == windows_fn_[j]) {
  465. // We NULL the later one (j), so as to minimize the chances we
  466. // NULL kFree and kRealloc. See comments below. This is fragile!
  467. windows_fn_[j] = NULL;
  468. }
  469. }
  470. }
  471. // There's always a chance that our module uses the same function
  472. // as another module that we've already loaded. In that case, we
  473. // need to set our windows_fn to NULL, to avoid double-patching.
  474. for (int ifn = 0; ifn < kNumFunctions; ifn++) {
  475. for (int imod = 0;
  476. imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs); imod++) {
  477. if (g_module_libcs[imod]->is_valid() &&
  478. this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) {
  479. windows_fn_[ifn] = NULL;
  480. }
  481. }
  482. }
  483. bool found_non_null = false;
  484. for (int i = 0; i < kNumFunctions; i++) {
  485. if (windows_fn_[i])
  486. found_non_null = true;
  487. }
  488. if (!found_non_null)
  489. return false;
  490. // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc].
  491. // The reason is, if those are NULL-ed out, we'll never patch them
  492. // and thus never get an origstub_fn_ value for them, and when we
  493. // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and
  494. // Perftools_realloc, below, it will fail. We could work around
  495. // that by adding a pointer from one patch-unit to the other, but we
  496. // haven't needed to yet.
  497. CHECK(windows_fn_[kFree]);
  498. CHECK(windows_fn_[kRealloc]);
  499. // OK, we successfully populated. Let's store our member information.
  500. module_base_address_ = module_entry.modBaseAddr;
  501. module_base_size_ = module_entry.modBaseSize;
  502. return true;
  503. }
  504. template<int T>
  505. bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) {
  506. CopyFrom(me_info); // copies the module_entry and the windows_fn_ array
  507. for (int i = 0; i < kNumFunctions; i++) {
  508. if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) {
  509. // if origstub_fn_ is not NULL, it's left around from a previous
  510. // patch. We need to set it to NULL for the new Patch call.
  511. //
  512. // Note that origstub_fn_ was logically freed by
  513. // PreamblePatcher::Unpatch, so we don't have to do anything
  514. // about it.
  515. origstub_fn_[i] = NULL; // Patch() will fill this in
  516. CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
  517. PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i],
  518. &origstub_fn_[i]));
  519. }
  520. }
  521. set_is_valid(true);
  522. return true;
  523. }
  524. template<int T>
  525. void LibcInfoWithPatchFunctions<T>::Unpatch() {
  526. // We have to cast our GenericFnPtrs to void* for unpatch. This is
  527. // contra the C++ spec; we use C-style casts to empahsize that.
  528. for (int i = 0; i < kNumFunctions; i++) {
  529. if (windows_fn_[i])
  530. CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
  531. PreamblePatcher::Unpatch((void*)windows_fn_[i],
  532. (void*)perftools_fn_[i],
  533. (void*)origstub_fn_[i]));
  534. }
  535. set_is_valid(false);
  536. }
  537. void WindowsInfo::Patch() {
  538. HMODULE hkernel32 = ::GetModuleHandleA("kernel32");
  539. CHECK_NE(hkernel32, NULL);
  540. // Unlike for libc, we know these exist in our module, so we can get
  541. // and patch at the same time.
  542. for (int i = 0; i < kNumFunctions; i++) {
  543. function_info_[i].windows_fn = (GenericFnPtr)
  544. ::GetProcAddress(hkernel32, function_info_[i].name);
  545. // If origstub_fn is not NULL, it's left around from a previous
  546. // patch. We need to set it to NULL for the new Patch call.
  547. // Since we've patched Unpatch() not to delete origstub_fn_ (it
  548. // causes problems in some contexts, though obviously not this
  549. // one), we should delete it now, before setting it to NULL.
  550. // NOTE: casting from a function to a pointer is contra the C++
  551. // spec. It's not safe on IA64, but is on i386. We use
  552. // a C-style cast here to emphasize this is not legal C++.
  553. delete[] (char*)(function_info_[i].origstub_fn);
  554. function_info_[i].origstub_fn = NULL; // Patch() will fill this in
  555. CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
  556. PreamblePatcher::Patch(function_info_[i].windows_fn,
  557. function_info_[i].perftools_fn,
  558. &function_info_[i].origstub_fn));
  559. }
  560. }
  561. void WindowsInfo::Unpatch() {
  562. // We have to cast our GenericFnPtrs to void* for unpatch. This is
  563. // contra the C++ spec; we use C-style casts to empahsize that.
  564. for (int i = 0; i < kNumFunctions; i++) {
  565. CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
  566. PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn,
  567. (void*)function_info_[i].perftools_fn,
  568. (void*)function_info_[i].origstub_fn));
  569. }
  570. }
  571. // You should hold the patch_all_modules_lock when calling this.
  572. void PatchOneModuleLocked(const LibcInfo& me_info) {
  573. // If we don't already have info on this module, let's add it. This
  574. // is where we're sad that each libcX has a different type, so we
  575. // can't use an array; instead, we have to use a switch statement.
  576. // Patch() returns false if there were no libc functions in the module.
  577. for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
  578. if (!g_module_libcs[i]->is_valid()) { // found an empty spot to add!
  579. switch (i) {
  580. case 0: libc1.Patch(me_info); return;
  581. case 1: libc2.Patch(me_info); return;
  582. case 2: libc3.Patch(me_info); return;
  583. case 3: libc4.Patch(me_info); return;
  584. case 4: libc5.Patch(me_info); return;
  585. case 5: libc6.Patch(me_info); return;
  586. case 6: libc7.Patch(me_info); return;
  587. case 7: libc8.Patch(me_info); return;
  588. }
  589. }
  590. }
  591. printf("PERFTOOLS ERROR: Too many modules containing libc in this executable\n");
  592. }
  593. void PatchMainExecutableLocked() {
  594. if (main_executable.patched())
  595. return; // main executable has already been patched
  596. ModuleEntryCopy fake_module_entry; // make a fake one to pass into Patch()
  597. // No need to call PopulateModuleEntryProcAddresses on the main executable.
  598. main_executable.PopulateWindowsFn(fake_module_entry);
  599. main_executable.Patch(main_executable);
  600. }
  601. // This lock is subject to a subtle and annoying lock inversion
  602. // problem: it may interact badly with unknown internal windows locks.
  603. // In particular, windows may be holding a lock when it calls
  604. // LoadLibraryExW and FreeLibrary, which we've patched. We have those
  605. // routines call PatchAllModules, which acquires this lock. If we
  606. // make windows system calls while holding this lock, those system
  607. // calls may need the internal windows locks that are being held in
  608. // the call to LoadLibraryExW, resulting in deadlock. The solution is
  609. // to be very careful not to call *any* windows routines while holding
  610. // patch_all_modules_lock, inside PatchAllModules().
  611. static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED);
  612. // last_loaded: The set of modules that were loaded the last time
  613. // PatchAllModules was called. This is an optimization for only
  614. // looking at modules that were added or removed from the last call.
  615. static std::set<HMODULE> *g_last_loaded;
  616. // Iterates over all the modules currently loaded by the executable,
  617. // according to windows, and makes sure they're all patched. Most
  618. // modules will already be in loaded_modules, meaning we have already
  619. // loaded and either patched them or determined they did not need to
  620. // be patched. Others will not, which means we need to patch them
  621. // (if necessary). Finally, we have to go through the existing
  622. // g_module_libcs and see if any of those are *not* in the modules
  623. // currently loaded by the executable. If so, we need to invalidate
  624. // them. Returns true if we did any work (patching or invalidating),
  625. // false if we were a noop. May update loaded_modules as well.
  626. // NOTE: you must hold the patch_all_modules_lock to access loaded_modules.
  627. bool PatchAllModules() {
  628. std::vector<ModuleEntryCopy> modules;
  629. bool made_changes = false;
  630. const HANDLE hCurrentProcess = GetCurrentProcess();
  631. DWORD num_modules = 0;
  632. HMODULE hModules[kMaxModules]; // max # of modules we support in one process
  633. if (!::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules),
  634. &num_modules)) {
  635. num_modules = 0;
  636. }
  637. // EnumProcessModules actually set the bytes written into hModules,
  638. // so we need to divide to make num_modules actually be a module-count.
  639. num_modules /= sizeof(*hModules);
  640. if (num_modules >= kMaxModules) {
  641. printf("PERFTOOLS ERROR: Too many modules in this executable to try"
  642. " to patch them all (if you need to, raise kMaxModules in"
  643. " patch_functions.cc).\n");
  644. num_modules = kMaxModules;
  645. }
  646. // Now we handle the unpatching of modules we have in g_module_libcs
  647. // but that were not found in EnumProcessModules. We need to
  648. // invalidate them. To speed that up, we store the EnumProcessModules
  649. // output in a set.
  650. // At the same time, we prepare for the adding of new modules, by
  651. // removing from hModules all the modules we know we've already
  652. // patched (or decided don't need to be patched). At the end,
  653. // hModules will hold only the modules that we need to consider patching.
  654. std::set<HMODULE> currently_loaded_modules;
  655. {
  656. SpinLockHolder h(&patch_all_modules_lock);
  657. if (!g_last_loaded) g_last_loaded = new std::set<HMODULE>;
  658. // At the end of this loop, currently_loaded_modules contains the
  659. // full list of EnumProcessModules, and hModules just the ones we
  660. // haven't handled yet.
  661. for (int i = 0; i < num_modules; ) {
  662. currently_loaded_modules.insert(hModules[i]);
  663. if (g_last_loaded->count(hModules[i]) > 0) {
  664. hModules[i] = hModules[--num_modules]; // replace element i with tail
  665. } else {
  666. i++; // keep element i
  667. }
  668. }
  669. // Now we do the unpatching/invalidation.
  670. for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
  671. if (g_module_libcs[i]->patched() &&
  672. currently_loaded_modules.count(g_module_libcs[i]->hmodule()) == 0) {
  673. // Means g_module_libcs[i] is no longer loaded (no me32 matched).
  674. // We could call Unpatch() here, but why bother? The module
  675. // has gone away, so nobody is going to call into it anyway.
  676. g_module_libcs[i]->set_is_valid(false);
  677. made_changes = true;
  678. }
  679. }
  680. // Update the loaded module cache.
  681. g_last_loaded->swap(currently_loaded_modules);
  682. }
  683. // Now that we know what modules are new, let's get the info we'll
  684. // need to patch them. Note this *cannot* be done while holding the
  685. // lock, since it needs to make windows calls (see the lock-inversion
  686. // comments before the definition of patch_all_modules_lock).
  687. MODULEINFO mi;
  688. for (int i = 0; i < num_modules; i++) {
  689. if (::GetModuleInformation(hCurrentProcess, hModules[i], &mi, sizeof(mi)))
  690. modules.push_back(ModuleEntryCopy(mi));
  691. }
  692. // Now we can do the patching of new modules.
  693. {
  694. SpinLockHolder h(&patch_all_modules_lock);
  695. for (std::vector<ModuleEntryCopy>::iterator it = modules.begin();
  696. it != modules.end(); ++it) {
  697. LibcInfo libc_info;
  698. if (libc_info.PopulateWindowsFn(*it)) { // true==module has libc routines
  699. PatchOneModuleLocked(libc_info);
  700. made_changes = true;
  701. }
  702. }
  703. // Now that we've dealt with the modules (dlls), update the main
  704. // executable. We do this last because PatchMainExecutableLocked
  705. // wants to look at how other modules were patched.
  706. if (!main_executable.patched()) {
  707. PatchMainExecutableLocked();
  708. made_changes = true;
  709. }
  710. }
  711. // TODO(csilvers): for this to be reliable, we need to also take
  712. // into account if we *would* have patched any modules had they not
  713. // already been loaded. (That is, made_changes should ignore
  714. // g_last_loaded.)
  715. return made_changes;
  716. }
  717. } // end unnamed namespace
  718. // ---------------------------------------------------------------------
  719. // Now that we've done all the patching machinery, let's actually
  720. // define the functions we're patching in. Mostly these are
  721. // simple wrappers around the do_* routines in tcmalloc.cc.
  722. //
  723. // In fact, we #include tcmalloc.cc to get at the tcmalloc internal
  724. // do_* functions, the better to write our own hook functions.
  725. // U-G-L-Y, I know. But the alternatives are, perhaps, worse. This
  726. // also lets us define _msize(), _expand(), and other windows-specific
  727. // functions here, using tcmalloc internals, without polluting
  728. // tcmalloc.cc.
  729. // -------------------------------------------------------------------
  730. // TODO(csilvers): refactor tcmalloc.cc into two files, so I can link
  731. // against the file with do_malloc, and ignore the one with malloc.
  732. #include "tcmalloc.cc"
  733. template<int T>
  734. void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW {
  735. void* result = do_malloc_or_cpp_alloc(size);
  736. MallocHook::InvokeNewHook(result, size);
  737. return result;
  738. }
  739. template<int T>
  740. void LibcInfoWithPatchFunctions<T>::Perftools_free(void* ptr) __THROW {
  741. MallocHook::InvokeDeleteHook(ptr);
  742. // This calls the windows free if do_free decides ptr was not
  743. // allocated by tcmalloc. Note it calls the origstub_free from
  744. // *this* templatized instance of LibcInfo. See "template
  745. // trickiness" above.
  746. do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree], false, 0);
  747. }
  748. template<int T>
  749. void* LibcInfoWithPatchFunctions<T>::Perftools_realloc(
  750. void* old_ptr, size_t new_size) __THROW {
  751. if (old_ptr == NULL) {
  752. void* result = do_malloc_or_cpp_alloc(new_size);
  753. MallocHook::InvokeNewHook(result, new_size);
  754. return result;
  755. }
  756. if (new_size == 0) {
  757. MallocHook::InvokeDeleteHook(old_ptr);
  758. do_free_with_callback(old_ptr,
  759. (void (*)(void*))origstub_fn_[kFree], false, 0);
  760. return NULL;
  761. }
  762. return do_realloc_with_callback(
  763. old_ptr, new_size,
  764. (void (*)(void*))origstub_fn_[kFree],
  765. (size_t (*)(const void*))origstub_fn_[k_Msize]);
  766. }
  767. template<int T>
  768. void* LibcInfoWithPatchFunctions<T>::Perftools_calloc(
  769. size_t n, size_t elem_size) __THROW {
  770. void* result = do_calloc(n, elem_size);
  771. MallocHook::InvokeNewHook(result, n * elem_size);
  772. return result;
  773. }
  774. template<int T>
  775. void* LibcInfoWithPatchFunctions<T>::Perftools_new(size_t size) {
  776. void* p = cpp_alloc(size, false);
  777. MallocHook::InvokeNewHook(p, size);
  778. return p;
  779. }
  780. template<int T>
  781. void* LibcInfoWithPatchFunctions<T>::Perftools_newarray(size_t size) {
  782. void* p = cpp_alloc(size, false);
  783. MallocHook::InvokeNewHook(p, size);
  784. return p;
  785. }
  786. template<int T>
  787. void LibcInfoWithPatchFunctions<T>::Perftools_delete(void *p) {
  788. MallocHook::InvokeDeleteHook(p);
  789. do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
  790. }
  791. template<int T>
  792. void LibcInfoWithPatchFunctions<T>::Perftools_deletearray(void *p) {
  793. MallocHook::InvokeDeleteHook(p);
  794. do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
  795. }
  796. template<int T>
  797. void* LibcInfoWithPatchFunctions<T>::Perftools_new_nothrow(
  798. size_t size, const std::nothrow_t&) __THROW {
  799. void* p = cpp_alloc(size, true);
  800. MallocHook::InvokeNewHook(p, size);
  801. return p;
  802. }
  803. template<int T>
  804. void* LibcInfoWithPatchFunctions<T>::Perftools_newarray_nothrow(
  805. size_t size, const std::nothrow_t&) __THROW {
  806. void* p = cpp_alloc(size, true);
  807. MallocHook::InvokeNewHook(p, size);
  808. return p;
  809. }
  810. template<int T>
  811. void LibcInfoWithPatchFunctions<T>::Perftools_delete_nothrow(
  812. void *p, const std::nothrow_t&) __THROW {
  813. MallocHook::InvokeDeleteHook(p);
  814. do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
  815. }
  816. template<int T>
  817. void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow(
  818. void *p, const std::nothrow_t&) __THROW {
  819. MallocHook::InvokeDeleteHook(p);
  820. do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
  821. }
  822. // _msize() lets you figure out how much space is reserved for a
  823. // pointer, in Windows. Even if applications don't call it, any DLL
  824. // with global constructors will call (transitively) something called
  825. // __dllonexit_lk in order to make sure the destructors get called
  826. // when the dll unloads. And that will call msize -- horrible things
  827. // can ensue if this is not hooked. Other parts of libc may also call
  828. // this internally.
  829. template<int T>
  830. size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW {
  831. return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]);
  832. }
  833. // We need to define this because internal windows functions like to
  834. // call into it(?). _expand() is like realloc but doesn't move the
  835. // pointer. We punt, which will cause callers to fall back on realloc.
  836. template<int T>
  837. void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr,
  838. size_t size) __THROW {
  839. return NULL;
  840. }
  841. LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
  842. DWORD_PTR dwBytes) {
  843. LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR))
  844. function_info_[kHeapAlloc].origstub_fn)(
  845. hHeap, dwFlags, dwBytes);
  846. MallocHook::InvokeNewHook(result, dwBytes);
  847. return result;
  848. }
  849. BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
  850. LPVOID lpMem) {
  851. MallocHook::InvokeDeleteHook(lpMem);
  852. return ((BOOL (WINAPI *)(HANDLE, DWORD, LPVOID))
  853. function_info_[kHeapFree].origstub_fn)(
  854. hHeap, dwFlags, lpMem);
  855. }
  856. LPVOID WINAPI WindowsInfo::Perftools_VirtualAllocEx(HANDLE process,
  857. LPVOID address,
  858. SIZE_T size, DWORD type,
  859. DWORD protect) {
  860. LPVOID result = ((LPVOID (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD))
  861. function_info_[kVirtualAllocEx].origstub_fn)(
  862. process, address, size, type, protect);
  863. // VirtualAllocEx() seems to be the Windows equivalent of mmap()
  864. MallocHook::InvokeMmapHook(result, address, size, protect, type, -1, 0);
  865. return result;
  866. }
  867. BOOL WINAPI WindowsInfo::Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
  868. SIZE_T size, DWORD type) {
  869. MallocHook::InvokeMunmapHook(address, size);
  870. return ((BOOL (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD))
  871. function_info_[kVirtualFreeEx].origstub_fn)(
  872. process, address, size, type);
  873. }
  874. LPVOID WINAPI WindowsInfo::Perftools_MapViewOfFileEx(
  875. HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
  876. DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {
  877. // For this function pair, you always deallocate the full block of
  878. // data that you allocate, so NewHook/DeleteHook is the right API.
  879. LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD, DWORD,
  880. SIZE_T, LPVOID))
  881. function_info_[kMapViewOfFileEx].origstub_fn)(
  882. hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
  883. dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);
  884. MallocHook::InvokeNewHook(result, dwNumberOfBytesToMap);
  885. return result;
  886. }
  887. BOOL WINAPI WindowsInfo::Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress) {
  888. MallocHook::InvokeDeleteHook(lpBaseAddress);
  889. return ((BOOL (WINAPI *)(LPCVOID))
  890. function_info_[kUnmapViewOfFile].origstub_fn)(
  891. lpBaseAddress);
  892. }
  893. // g_load_map holds a copy of windows' refcount for how many times
  894. // each currently loaded module has been loaded and unloaded. We use
  895. // it as an optimization when the same module is loaded more than
  896. // once: as long as the refcount stays above 1, we don't need to worry
  897. // about patching because it's already patched. Likewise, we don't
  898. // need to unpatch until the refcount drops to 0. load_map is
  899. // maintained in LoadLibraryExW and FreeLibrary, and only covers
  900. // modules explicitly loaded/freed via those interfaces.
  901. static std::map<HMODULE, int>* g_load_map = NULL;
  902. HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName,
  903. HANDLE hFile,
  904. DWORD dwFlags) {
  905. HMODULE rv;
  906. // Check to see if the modules is already loaded, flag 0 gets a
  907. // reference if it was loaded. If it was loaded no need to call
  908. // PatchAllModules, just increase the reference count to match
  909. // what GetModuleHandleExW does internally inside windows.
  910. if (::GetModuleHandleExW(0, lpFileName, &rv)) {
  911. return rv;
  912. } else {
  913. // Not already loaded, so load it.
  914. rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD))
  915. function_info_[kLoadLibraryExW].origstub_fn)(
  916. lpFileName, hFile, dwFlags);
  917. // This will patch any newly loaded libraries, if patching needs
  918. // to be done.
  919. PatchAllModules();
  920. return rv;
  921. }
  922. }
  923. BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) {
  924. BOOL rv = ((BOOL (WINAPI *)(HMODULE))
  925. function_info_[kFreeLibrary].origstub_fn)(hLibModule);
  926. // Check to see if the module is still loaded by passing the base
  927. // address and seeing if it comes back with the same address. If it
  928. // is the same address it's still loaded, so the FreeLibrary() call
  929. // was a noop, and there's no need to redo the patching.
  930. HMODULE owner = NULL;
  931. BOOL result = ::GetModuleHandleExW(
  932. (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
  933. GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
  934. (LPCWSTR)hLibModule,
  935. &owner);
  936. if (result && owner == hLibModule)
  937. return rv;
  938. PatchAllModules(); // this will fix up the list of patched libraries
  939. return rv;
  940. }
  941. // ---------------------------------------------------------------------
  942. // PatchWindowsFunctions()
  943. // This is the function that is exposed to the outside world.
  944. // It should be called before the program becomes multi-threaded,
  945. // since main_executable_windows.Patch() is not thread-safe.
  946. // ---------------------------------------------------------------------
  947. void PatchWindowsFunctions() {
  948. // This does the libc patching in every module, and the main executable.
  949. PatchAllModules();
  950. main_executable_windows.Patch();
  951. }
  952. #if 0
  953. // It's possible to unpatch all the functions when we are exiting.
  954. // The idea is to handle properly windows-internal data that is
  955. // allocated before PatchWindowsFunctions is called. If all
  956. // destruction happened in reverse order from construction, then we
  957. // could call UnpatchWindowsFunctions at just the right time, so that
  958. // that early-allocated data would be freed using the windows
  959. // allocation functions rather than tcmalloc. The problem is that
  960. // windows allocates some structures lazily, so it would allocate them
  961. // late (using tcmalloc) and then try to deallocate them late as well.
  962. // So instead of unpatching, we just modify all the tcmalloc routines
  963. // so they call through to the libc rountines if the memory in
  964. // question doesn't seem to have been allocated with tcmalloc. I keep
  965. // this unpatch code around for reference.
  966. void UnpatchWindowsFunctions() {
  967. // We need to go back to the system malloc/etc at global destruct time,
  968. // so objects that were constructed before tcmalloc, using the system
  969. // malloc, can destroy themselves using the system free. This depends
  970. // on DLLs unloading in the reverse order in which they load!
  971. //
  972. // We also go back to the default HeapAlloc/etc, just for consistency.
  973. // Who knows, it may help avoid weird bugs in some situations.
  974. main_executable_windows.Unpatch();
  975. main_executable.Unpatch();
  976. if (libc1.is_valid()) libc1.Unpatch();
  977. if (libc2.is_valid()) libc2.Unpatch();
  978. if (libc3.is_valid()) libc3.Unpatch();
  979. if (libc4.is_valid()) libc4.Unpatch();
  980. if (libc5.is_valid()) libc5.Unpatch();
  981. if (libc6.is_valid()) libc6.Unpatch();
  982. if (libc7.is_valid()) libc7.Unpatch();
  983. if (libc8.is_valid()) libc8.Unpatch();
  984. }
  985. #endif