15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2007, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Craig Silverstein
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main purpose of this file is to patch the libc allocation
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// routines (malloc and friends, but also _msize and other
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// windows-specific libc-style routines).  However, we also patch
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// windows routines to do accounting.  We do better at the former than
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the latter.  Here are some comments from Paul Pluzhnikov about what
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it might take to do a really good job patching windows routines to
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keep track of memory usage:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "You should intercept at least the following:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     HeapCreate HeapDestroy HeapAlloc HeapReAlloc HeapFree
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     RtlCreateHeap RtlDestroyHeap RtlAllocateHeap RtlFreeHeap
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     malloc calloc realloc free
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     malloc_dbg calloc_dbg realloc_dbg free_dbg
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some of these call the other ones (but not always), sometimes
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recursively (i.e. HeapCreate may call HeapAlloc on a different
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap, IIRC)."
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since Paul didn't mention VirtualAllocEx, he may not have even been
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// considering all the mmap-like functions that windows has (or he may
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just be ignoring it because he's seen we already patch it).  Of the
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// above, we do not patch the *_dbg functions, and of the windows
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions, we only patch HeapAlloc and HeapFree.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The *_dbg functions come into play with /MDd, /MTd, and /MLd,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// probably.  It may be ok to just turn off tcmalloc in those cases --
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the user wants the windows debug malloc, they probably don't
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// want tcmalloc!  We should also test with all of /MD, /MT, and /ML,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which we're not currently doing.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(csilvers): try to do better here?  Paul does conclude:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                 "Keeping track of all of this was a nightmare."
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _WIN32
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error You should only be including windows/patch_functions.cc in a windows environment!
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h>
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32_OVERRIDE_ALLOCATORS
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error This file is intended for patching allocators - use override_functions.cc instead.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use psapi.  Non-MSVC systems will have to link this in themselves.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "Psapi.lib")
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure we always use the 'old' names of the psapi functions.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PSAPI_VERSION
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PSAPI_VERSION 1
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <malloc.h>       // for _msize and _expand
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Psapi.h>        // for EnumProcessModules, GetModuleInformation, etc.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <base/logging.h>
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/spinlock.h"
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gperftools/malloc_hook.h"
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "malloc_hook-inl.h"
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "preamble_patcher.h"
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of modules we allow to be in one executable
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxModules = 8182;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are hard-coded, unfortunately. :-( They are also probably
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compiler specific.  See get_mangled_names.cc, in this directory,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for instructions on how to update these names for your compiler.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledNew[] = "??2@YAPAXI@Z";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledNewArray[] = "??_U@YAPAXI@Z";
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledDelete[] = "??3@YAXPAX@Z";
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledDeleteArray[] = "??_V@YAXPAX@Z";
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z";
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z";
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledDeleteNothrow[] = "??3@YAXPAXABUnothrow_t@std@@@Z";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMangledDeleteArrayNothrow[] = "??_V@YAXPAXABUnothrow_t@std@@@Z";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is an unused but exported symbol that we can use to tell the
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC linker to bring in libtcmalloc, via the /INCLUDE linker flag.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Without this, the linker will likely decide that libtcmalloc.dll
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't add anything to the executable (since it does all its work
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through patching, which the linker can't see), and ignore it
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entirely.  (The name 'tcmalloc' is already reserved for a
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// namespace.  I'd rather export a variable named "_tcmalloc", but I
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// couldn't figure out how to get that to work.  This function exports
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the symbol "__tcmalloc".)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void _tcmalloc();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void _tcmalloc() { }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the version needed for windows x64, which has a different
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// decoration scheme which doesn't auto-add a leading underscore.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void __tcmalloc();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __tcmalloc() { }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {    // most everything here is in an unnamed namespace
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void (*GenericFnPtr)();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using sidestep::PreamblePatcher;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ModuleEntryCopy;   // defined below
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are how we override the memory allocation
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions, just like tcmalloc.cc and malloc_hook.cc do.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is information about the routines we're patching, for a given
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// module that implements libc memory routines.  A single executable
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can have several libc implementations running about (in different
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// .dll's), and we need to patch/unpatch them all.  This defines
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// everything except the new functions we're patching in, which
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are defined in LibcFunctions, below.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LibcInfo {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LibcInfo() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(this, 0, sizeof(*this));  // easiest way to initialize the array
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool patched() const { return is_valid(); }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_is_valid(bool b) { is_valid_ = b; }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // According to http://msdn.microsoft.com/en-us/library/ms684229(VS.85).aspx:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "The load address of a module (lpBaseOfDll) is the same as the HMODULE
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value."
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE hmodule() const {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<HMODULE>(const_cast<void*>(module_base_address_));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populates all the windows_fn_[] vars based on our module info.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns false if windows_fn_ is all NULL's, because there's
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nothing to patch.  Also populates the rest of the module_entry
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // info, such as the module's name.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool PopulateWindowsFn(const ModuleEntryCopy& module_entry);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CopyFrom(const LibcInfo& that) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (this == &that)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->is_valid_ = that.is_valid_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->module_base_address_ = that.module_base_address_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->module_base_size_ = that.module_base_size_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kMalloc, kFree, kRealloc, kCalloc,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNew, kNewArray, kDelete, kDeleteArray,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These are windows-only functions from malloc.h
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k_Msize, k_Expand,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A MS CRT "internal" function, implemented using _calloc_impl
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k_CallocCrt,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNumFunctions
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // I'd like to put these together in a struct (perhaps in the
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subclass, so we can put in perftools_fn_ as well), but vc8 seems
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to have a bug where it doesn't initialize the struct properly if
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we try to take the address of a function that's not yet loaded
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from a dll, as is the common case for static_fn_.  So we need
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // each to be in its own array. :-(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const function_name_[kNumFunctions];
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function is only used when statically linking the binary.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In that case, loading malloc/etc from the dll (via
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PatchOneModule) won't work, since there are no dlls.  Instead,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // you just want to be taking the address of malloc/etc directly.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the common, non-static-link case, these pointers will all be
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULL, since this initializer runs before msvcrt.dll is loaded.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const GenericFnPtr static_fn_[kNumFunctions];
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the address of the function we are going to patch
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (malloc, etc).  Other info about the function is in the
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // patch-specific subclasses, below.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericFnPtr windows_fn_[kNumFunctions];
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is set to true when this structure is initialized (because
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we're patching a new library) and set to false when it's
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // uninitialized (because we've freed that library).
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_valid_;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *module_base_address_;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t module_base_size_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These shouldn't have to be public, since only subclasses of
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LibcInfo need it, but they do.  Maybe something to do with
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // templates.  Shrug.  I hide them down here so users won't see
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them. :-)  (OK, I also need to define ctrgProcAddress late.)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_valid() const { return is_valid_; }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericFnPtr windows_fn(int ifunction) const {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return windows_fn_[ifunction];
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These three are needed by ModuleEntryCopy.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int ctrgProcAddress = kNumFunctions;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static GenericFnPtr static_fn(int ifunction) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_fn_[ifunction];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const function_name(int ifunction) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return function_name_[ifunction];
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Template trickiness: logically, a LibcInfo would include
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// given module, these three go together.  And in fact,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Perftools_malloc_ may need to call origstub_malloc_, which means we
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// either need to change Perftools_malloc_ to take origstub_malloc_ as
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an arugment -- unfortunately impossible since it needs to keep the
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// same API as normal malloc -- or we need to write a different
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// version of Perftools_malloc_ for each LibcInfo instance we create.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We choose the second route, and use templates to implement it (we
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// could have also used macros).  So to get multiple versions
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the struct, we say "struct<1> var1; struct<2> var2;".  The price
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we pay is some code duplication, and more annoying, each instance
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of this var is a separate type.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int> class LibcInfoWithPatchFunctions : public LibcInfo {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // me_info should have had PopulateWindowsFn() called on it, so the
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // module_* vars and windows_fn_ are set up.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Patch(const LibcInfo& me_info);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Unpatch();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This holds the original function contents after we patch the function.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This has to be defined static in the subclass, because the perftools_fns
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference origstub_fn_.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static GenericFnPtr origstub_fn_[kNumFunctions];
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the function we want to patch in
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const GenericFnPtr perftools_fn_[kNumFunctions];
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_malloc(size_t size) __THROW;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Perftools_free(void* ptr) __THROW;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_realloc(void* ptr, size_t size) __THROW;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_calloc(size_t nmemb, size_t size) __THROW;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_new(size_t size);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_newarray(size_t size);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Perftools_delete(void *ptr);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Perftools_deletearray(void *ptr);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_new_nothrow(size_t size,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::nothrow_t&) __THROW;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools_newarray_nothrow(size_t size,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::nothrow_t&) __THROW;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Perftools_delete_nothrow(void *ptr,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::nothrow_t&) __THROW;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Perftools_deletearray_nothrow(void *ptr,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::nothrow_t&) __THROW;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static size_t Perftools__msize(void *ptr) __THROW;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void* Perftools__expand(void *ptr, size_t size) __THROW;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // malloc.h also defines these functions:
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   _aligned_malloc, _aligned_free,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But they seem pretty obscure, and I'm fine not overriding them for now.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It may be they all call into malloc/free anyway.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a subset of MODDULEENTRY32, that we need for patching.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ModuleEntryCopy {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPVOID  modBaseAddr;     // the same as hmodule
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD   modBaseSize;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is not part of MODDULEENTRY32, but is needed to avoid making
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // windows syscalls while we're holding patch_all_modules_lock (see
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lock-inversion comments at patch_all_modules_lock definition, below).
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress];
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModuleEntryCopy() {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modBaseAddr = NULL;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modBaseSize = 0;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgProcAddresses[i] = LibcInfo::static_fn(i);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModuleEntryCopy(const MODULEINFO& mi) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->modBaseAddr = mi.lpBaseOfDll;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->modBaseSize = mi.SizeOfImage;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FARPROC target = ::GetProcAddress(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const HMODULE>(mi.lpBaseOfDll),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LibcInfo::function_name(i));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Sometimes a DLL forwards a function to a function in another
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // DLL.  We don't want to patch those forwarded functions --
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // they'll get patched when the other DLL is processed.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (target >= modBaseAddr && target < modEndAddr)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rgProcAddresses[i] = (GenericFnPtr)target;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rgProcAddresses[i] = (GenericFnPtr)NULL;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is easier because there's only one of them.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WindowsInfo {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Patch();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Unpatch();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 for pre-XP systems?
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kHeapAlloc, kHeapFree, kVirtualAllocEx, kVirtualFreeEx,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW, kFreeLibrary,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNumFunctions
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct FunctionInfo {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* const name;          // name of fn in a module (eg "malloc")
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenericFnPtr windows_fn;         // the fn whose name we call (&malloc)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenericFnPtr origstub_fn;        // original fn contents after we patch
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GenericFnPtr perftools_fn; // fn we want to patch in
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static FunctionInfo function_info_[kNumFunctions];
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A Windows-API equivalent of malloc and free
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           DWORD_PTR dwBytes);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        LPVOID lpMem);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A Windows-API equivalent of mmap and munmap, for "anonymous regions"
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                SIZE_T size, DWORD type,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                DWORD protect);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             SIZE_T size, DWORD type);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A Windows-API equivalent of mmap and munmap, for actual files
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 DWORD dwDesiredAccess,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 DWORD dwFileOffsetHigh,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 DWORD dwFileOffsetLow,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 SIZE_T dwNumberOfBytesToMap,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 LPVOID lpBaseAddress);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BOOL WINAPI Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need the other 3 variants because they all call this one. */
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 HANDLE hFile,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 DWORD dwFlags);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If you run out, just add a few more to the array.  You'll also need
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to update the switch statement in PatchOneModule(), and the list in
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UnpatchWindowsFunctions().
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// main_executable and main_executable_windows are two windows into
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same executable.  One is responsible for patching the libc
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// routines that live in the main executable (if any) to use tcmalloc;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the other is responsible for patching the windows routines like
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapAlloc/etc to use tcmalloc.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<0> main_executable;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<1> libc1;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<2> libc2;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<3> libc3;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<4> libc4;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<5> libc5;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<6> libc6;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<7> libc7;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfoWithPatchFunctions<8> libc8;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibcInfo* g_module_libcs[] = {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WindowsInfo main_executable_windows;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const LibcInfo::function_name_[] = {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "malloc", "free", "realloc", "calloc",
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ideally we should patch the nothrow versions of new/delete, but
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // at least in msvcrt, nothrow-new machine-code is of a type we
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't patch.  Since these are relatively rare, I'm hoping it's ok
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not to patch them.  (NULL name turns off patching.)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,  // kMangledNewNothrow,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,  // kMangledNewArrayNothrow,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,  // kMangledDeleteNothrow,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,  // kMangledDeleteArrayNothrow,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "_msize", "_expand", "_calloc_crt",
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For mingw, I can't patch the new/delete here, because the
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instructions are too small to patch.  Luckily, they're so small
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because all they do is call into malloc/free, so they still end up
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calling tcmalloc routines, and we don't actually lose anything
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (except maybe some stacktrace goodness) by not patching.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GenericFnPtr LibcInfo::static_fn_[] = {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::malloc,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::free,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::realloc,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::calloc,
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __MINGW32__
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)(void*(*)(size_t))&::operator new,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)(void*(*)(size_t))&::operator new[],
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)(void(*)(void*))&::operator delete,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)(void(*)(void*))&::operator delete[],
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void*(*)(size_t, struct std::nothrow_t const &))&::operator new,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[],
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void(*)(void*, struct std::nothrow_t const &))&::operator delete,
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void(*)(void*, struct std::nothrow_t const &))&::operator delete[],
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::_msize,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::_expand,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&::calloc,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will get filled in at run-time, as patching is done.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_malloc,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_free,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_realloc,
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_calloc,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_new,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_newarray,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_delete,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_deletearray,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_new_nothrow,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_newarray_nothrow,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_delete_nothrow,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_deletearray_nothrow,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools__msize,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools__expand,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (GenericFnPtr)&Perftools_calloc,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc },
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree },
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx },
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx },
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx },
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile },
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW },
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary },
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, store the location of the function to patch before
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // patching it.  If none of these functions are found in the module,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then this module has no libc in it, and we just return false.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!function_name_[i])     // we can turn off patching by unsetting name
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The ::GetProcAddress calls were done in the ModuleEntryCopy
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // constructor, so we don't have to make any windows calls here.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GenericFnPtr fn = module_entry.rgProcAddresses[i];
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fn) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windows_fn_[i] = PreamblePatcher::ResolveTarget(fn);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some modules use the same function pointer for new and new[].  If
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we find that, set one of the pointers to NULL so we don't double-
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // patch.  Same may happen with new and nothrow-new, or even new[]
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and nothrow-new.  It's easiest just to check each fn-ptr against
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // every other.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = i+1; j < kNumFunctions; j++) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (windows_fn_[i] == windows_fn_[j]) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We NULL the later one (j), so as to minimize the chances we
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NULL kFree and kRealloc.  See comments below.  This is fragile!
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        windows_fn_[j] = NULL;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There's always a chance that our module uses the same function
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as another module that we've already loaded.  In that case, we
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to set our windows_fn to NULL, to avoid double-patching.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int ifn = 0; ifn < kNumFunctions; ifn++) {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int imod = 0;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs);  imod++) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (g_module_libcs[imod]->is_valid() &&
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        windows_fn_[ifn] = NULL;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_non_null = false;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (windows_fn_[i])
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_non_null = true;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!found_non_null)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc].
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The reason is, if those are NULL-ed out, we'll never patch them
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and thus never get an origstub_fn_ value for them, and when we
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Perftools_realloc, below, it will fail.  We could work around
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that by adding a pointer from one patch-unit to the other, but we
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // haven't needed to yet.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(windows_fn_[kFree]);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(windows_fn_[kRealloc]);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OK, we successfully populated.  Let's store our member information.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_base_address_ = module_entry.modBaseAddr;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_base_size_ = module_entry.modBaseSize;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyFrom(me_info);   // copies the module_entry and the windows_fn_ array
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if origstub_fn_ is not NULL, it's left around from a previous
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // patch.  We need to set it to NULL for the new Patch call.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Since we've patched Unpatch() not to delete origstub_fn_ (it
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // causes problems in some contexts, though obviously not this
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // one), we should delete it now, before setting it to NULL.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // NOTE: casting from a function to a pointer is contra the C++
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //       spec.  It's not safe on IA64, but is on i386.  We use
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //       a C-style cast here to emphasize this is not legal C++.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] (char*)(origstub_fn_[i]);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origstub_fn_[i] = NULL;   // Patch() will fill this in
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i],
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &origstub_fn_[i]));
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_is_valid(true);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Unpatch() {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have to cast our GenericFnPtrs to void* for unpatch.  This is
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contra the C++ spec; we use C-style casts to empahsize that.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (windows_fn_[i])
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               PreamblePatcher::Unpatch((void*)windows_fn_[i],
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        (void*)perftools_fn_[i],
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        (void*)origstub_fn_[i]));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_is_valid(false);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowsInfo::Patch() {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE hkernel32 = ::GetModuleHandleA("kernel32");
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(hkernel32, NULL);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unlike for libc, we know these exist in our module, so we can get
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and patch at the same time.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function_info_[i].windows_fn = (GenericFnPtr)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ::GetProcAddress(hkernel32, function_info_[i].name);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If origstub_fn is not NULL, it's left around from a previous
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // patch.  We need to set it to NULL for the new Patch call.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since we've patched Unpatch() not to delete origstub_fn_ (it
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // causes problems in some contexts, though obviously not this
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // one), we should delete it now, before setting it to NULL.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NOTE: casting from a function to a pointer is contra the C++
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //       spec.  It's not safe on IA64, but is on i386.  We use
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //       a C-style cast here to emphasize this is not legal C++.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] (char*)(function_info_[i].origstub_fn);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function_info_[i].origstub_fn = NULL;  // Patch() will fill this in
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             PreamblePatcher::Patch(function_info_[i].windows_fn,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    function_info_[i].perftools_fn,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &function_info_[i].origstub_fn));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowsInfo::Unpatch() {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have to cast our GenericFnPtrs to void* for unpatch.  This is
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contra the C++ spec; we use C-style casts to empahsize that.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFunctions; i++) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn,
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      (void*)function_info_[i].perftools_fn,
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      (void*)function_info_[i].origstub_fn));
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You should hold the patch_all_modules_lock when calling this.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PatchOneModuleLocked(const LibcInfo& me_info) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we don't already have info on this module, let's add it.  This
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is where we're sad that each libcX has a different type, so we
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't use an array; instead, we have to use a switch statement.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Patch() returns false if there were no libc functions in the module.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!g_module_libcs[i]->is_valid()) {   // found an empty spot to add!
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (i) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 0: libc1.Patch(me_info); return;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 1: libc2.Patch(me_info); return;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 2: libc3.Patch(me_info); return;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 3: libc4.Patch(me_info); return;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 4: libc5.Patch(me_info); return;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 5: libc6.Patch(me_info); return;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 6: libc7.Patch(me_info); return;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 7: libc8.Patch(me_info); return;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("PERFTOOLS ERROR: Too many modules containing libc in this executable\n");
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PatchMainExecutableLocked() {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (main_executable.patched())
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;    // main executable has already been patched
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModuleEntryCopy fake_module_entry;   // make a fake one to pass into Patch()
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to call PopulateModuleEntryProcAddresses on the main executable.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_executable.PopulateWindowsFn(fake_module_entry);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_executable.Patch(main_executable);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This lock is subject to a subtle and annoying lock inversion
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// problem: it may interact badly with unknown internal windows locks.
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In particular, windows may be holding a lock when it calls
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LoadLibraryExW and FreeLibrary, which we've patched.  We have those
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// routines call PatchAllModules, which acquires this lock.  If we
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// make windows system calls while holding this lock, those system
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calls may need the internal windows locks that are being held in
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the call to LoadLibraryExW, resulting in deadlock.  The solution is
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be very careful not to call *any* windows routines while holding
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// patch_all_modules_lock, inside PatchAllModules().
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// last_loaded: The set of modules that were loaded the last time
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PatchAllModules was called.  This is an optimization for only
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// looking at modules that were added or removed from the last call.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::set<HMODULE> *g_last_loaded;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Iterates over all the modules currently loaded by the executable,
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// according to windows, and makes sure they're all patched.  Most
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modules will already be in loaded_modules, meaning we have already
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// loaded and either patched them or determined they did not need to
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be patched.  Others will not, which means we need to patch them
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (if necessary).  Finally, we have to go through the existing
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// g_module_libcs and see if any of those are *not* in the modules
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// currently loaded by the executable.  If so, we need to invalidate
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// them.  Returns true if we did any work (patching or invalidating),
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// false if we were a noop.  May update loaded_modules as well.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: you must hold the patch_all_modules_lock to access loaded_modules.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PatchAllModules() {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ModuleEntryCopy> modules;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool made_changes = false;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HANDLE hCurrentProcess = GetCurrentProcess();
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num_modules = 0;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE hModules[kMaxModules];  // max # of modules we support in one process
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules),
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &num_modules)) {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_modules = 0;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EnumProcessModules actually set the bytes written into hModules,
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we need to divide to make num_modules actually be a module-count.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_modules /= sizeof(*hModules);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_modules >= kMaxModules) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("PERFTOOLS ERROR: Too many modules in this executable to try"
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           " to patch them all (if you need to, raise kMaxModules in"
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           " patch_functions.cc).\n");
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_modules = kMaxModules;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we handle the unpatching of modules we have in g_module_libcs
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but that were not found in EnumProcessModules.  We need to
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate them.  To speed that up, we store the EnumProcessModules
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // output in a set.
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At the same time, we prepare for the adding of new modules, by
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // removing from hModules all the modules we know we've already
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // patched (or decided don't need to be patched).  At the end,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hModules will hold only the modules that we need to consider patching.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<HMODULE> currently_loaded_modules;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder h(&patch_all_modules_lock);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!g_last_loaded)  g_last_loaded = new std::set<HMODULE>;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At the end of this loop, currently_loaded_modules contains the
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // full list of EnumProcessModules, and hModules just the ones we
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // haven't handled yet.
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < num_modules; ) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      currently_loaded_modules.insert(hModules[i]);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (g_last_loaded->count(hModules[i]) > 0) {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hModules[i] = hModules[--num_modules];  // replace element i with tail
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i++;                                    // keep element i
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now we do the unpatching/invalidation.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (g_module_libcs[i]->patched() &&
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          currently_loaded_modules.count(g_module_libcs[i]->hmodule()) == 0) {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Means g_module_libcs[i] is no longer loaded (no me32 matched).
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We could call Unpatch() here, but why bother?  The module
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // has gone away, so nobody is going to call into it anyway.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_module_libcs[i]->set_is_valid(false);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        made_changes = true;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the loaded module cache.
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_last_loaded->swap(currently_loaded_modules);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now that we know what modules are new, let's get the info we'll
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to patch them.  Note this *cannot* be done while holding the
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lock, since it needs to make windows calls (see the lock-inversion
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // comments before the definition of patch_all_modules_lock).
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MODULEINFO mi;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_modules; i++) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::GetModuleInformation(hCurrentProcess, hModules[i], &mi, sizeof(mi)))
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modules.push_back(ModuleEntryCopy(mi));
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we can do the patching of new modules.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder h(&patch_all_modules_lock);
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<ModuleEntryCopy>::iterator it = modules.begin();
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != modules.end(); ++it) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LibcInfo libc_info;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (libc_info.PopulateWindowsFn(*it)) { // true==module has libc routines
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PatchOneModuleLocked(libc_info);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        made_changes = true;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now that we've dealt with the modules (dlls), update the main
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // executable.  We do this last because PatchMainExecutableLocked
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // wants to look at how other modules were patched.
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!main_executable.patched()) {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PatchMainExecutableLocked();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      made_changes = true;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(csilvers): for this to be reliable, we need to also take
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // into account if we *would* have patched any modules had they not
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already been loaded.  (That is, made_changes should ignore
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // g_last_loaded.)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return made_changes;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // end unnamed namespace
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Now that we've done all the patching machinery, let's actually
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// define the functions we're patching in.  Mostly these are
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple wrappers around the do_* routines in tcmalloc.cc.
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In fact, we #include tcmalloc.cc to get at the tcmalloc internal
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// do_* functions, the better to write our own hook functions.
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// U-G-L-Y, I know.  But the alternatives are, perhaps, worse.  This
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also lets us define _msize(), _expand(), and other windows-specific
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions here, using tcmalloc internals, without polluting
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tcmalloc.cc.
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -------------------------------------------------------------------
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(csilvers): refactor tcmalloc.cc into two files, so I can link
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// against the file with do_malloc, and ignore the one with malloc.
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tcmalloc.cc"
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW {
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result = do_malloc_or_cpp_alloc(size);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(result, size);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Perftools_free(void* ptr) __THROW {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(ptr);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This calls the windows free if do_free decides ptr was not
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allocated by tcmalloc.  Note it calls the origstub_free from
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // *this* templatized instance of LibcInfo.  See "template
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // trickiness" above.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree]);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_realloc(
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* old_ptr, size_t new_size) __THROW {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_ptr == NULL) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* result = do_malloc_or_cpp_alloc(new_size);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MallocHook::InvokeNewHook(result, new_size);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_size == 0) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MallocHook::InvokeDeleteHook(old_ptr);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do_free_with_callback(old_ptr,
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          (void (*)(void*))origstub_fn_[kFree]);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return do_realloc_with_callback(
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_ptr, new_size,
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (void (*)(void*))origstub_fn_[kFree],
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (size_t (*)(const void*))origstub_fn_[k_Msize]);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_calloc(
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t n, size_t elem_size) __THROW {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result = do_calloc(n, elem_size);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(result, n * elem_size);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_new(size_t size) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = cpp_alloc(size, false);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(p, size);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_newarray(size_t size) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = cpp_alloc(size, false);
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(p, size);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Perftools_delete(void *p) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(p);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Perftools_deletearray(void *p) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(p);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_new_nothrow(
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size, const std::nothrow_t&) __THROW {
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = cpp_alloc(size, true);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(p, size);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools_newarray_nothrow(
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size, const std::nothrow_t&) __THROW {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = cpp_alloc(size, true);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(p, size);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Perftools_delete_nothrow(
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p, const std::nothrow_t&) __THROW {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(p);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow(
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p, const std::nothrow_t&) __THROW {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(p);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// _msize() lets you figure out how much space is reserved for a
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer, in Windows.  Even if applications don't call it, any DLL
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with global constructors will call (transitively) something called
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// __dllonexit_lk in order to make sure the destructors get called
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when the dll unloads.  And that will call msize -- horrible things
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can ensue if this is not hooked.  Other parts of libc may also call
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this internally.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to define this because internal windows functions like to
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// call into it(?).  _expand() is like realloc but doesn't move the
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer.  We punt, which will cause callers to fall back on realloc.
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<int T>
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       size_t size) __THROW {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               DWORD_PTR dwBytes) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR))
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   function_info_[kHeapAlloc].origstub_fn)(
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       hHeap, dwFlags, dwBytes);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(result, dwBytes);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            LPVOID lpMem) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(lpMem);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((BOOL (WINAPI *)(HANDLE, DWORD, LPVOID))
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          function_info_[kHeapFree].origstub_fn)(
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              hHeap, dwFlags, lpMem);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LPVOID WINAPI WindowsInfo::Perftools_VirtualAllocEx(HANDLE process,
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    LPVOID address,
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    SIZE_T size, DWORD type,
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    DWORD protect) {
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPVOID result = ((LPVOID (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD))
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   function_info_[kVirtualAllocEx].origstub_fn)(
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       process, address, size, type, protect);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // VirtualAllocEx() seems to be the Windows equivalent of mmap()
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMmapHook(result, address, size, protect, type, -1, 0);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI WindowsInfo::Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 SIZE_T size, DWORD type) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMunmapHook(address, size);
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((BOOL (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD))
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          function_info_[kVirtualFreeEx].origstub_fn)(
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              process, address, size, type);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LPVOID WINAPI WindowsInfo::Perftools_MapViewOfFileEx(
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For this function pair, you always deallocate the full block of
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // data that you allocate, so NewHook/DeleteHook is the right API.
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD, DWORD,
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      SIZE_T, LPVOID))
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   function_info_[kMapViewOfFileEx].origstub_fn)(
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeNewHook(result, dwNumberOfBytesToMap);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI WindowsInfo::Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeDeleteHook(lpBaseAddress);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((BOOL (WINAPI *)(LPCVOID))
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          function_info_[kUnmapViewOfFile].origstub_fn)(
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              lpBaseAddress);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// g_load_map holds a copy of windows' refcount for how many times
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each currently loaded module has been loaded and unloaded.  We use
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it as an optimization when the same module is loaded more than
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// once: as long as the refcount stays above 1, we don't need to worry
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// about patching because it's already patched.  Likewise, we don't
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to unpatch until the refcount drops to 0.  load_map is
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// maintained in LoadLibraryExW and FreeLibrary, and only covers
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modules explicitly loaded/freed via those interfaces.
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::map<HMODULE, int>* g_load_map = NULL;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName,
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     HANDLE hFile,
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     DWORD dwFlags) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE rv;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if the modules is already loaded, flag 0 gets a
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference if it was loaded.  If it was loaded no need to call
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PatchAllModules, just increase the reference count to match
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // what GetModuleHandleExW does internally inside windows.
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::GetModuleHandleExW(0, lpFileName, &rv)) {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not already loaded, so load it.
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD))
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  function_info_[kLoadLibraryExW].origstub_fn)(
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      lpFileName, hFile, dwFlags);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will patch any newly loaded libraries, if patching needs
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to be done.
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PatchAllModules();
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL rv = ((BOOL (WINAPI *)(HMODULE))
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             function_info_[kFreeLibrary].origstub_fn)(hLibModule);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if the module is still loaded by passing the base
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // address and seeing if it comes back with the same address.  If it
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is the same address it's still loaded, so the FreeLibrary() call
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was a noop, and there's no need to redo the patching.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE owner = NULL;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL result = ::GetModuleHandleExW(
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (LPCWSTR)hLibModule,
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &owner);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result && owner == hLibModule)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PatchAllModules();    // this will fix up the list of patched libraries
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PatchWindowsFunctions()
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    This is the function that is exposed to the outside world.
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    It should be called before the program becomes multi-threaded,
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    since main_executable_windows.Patch() is not thread-safe.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PatchWindowsFunctions() {
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This does the libc patching in every module, and the main executable.
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PatchAllModules();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_executable_windows.Patch();
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It's possible to unpatch all the functions when we are exiting.
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The idea is to handle properly windows-internal data that is
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocated before PatchWindowsFunctions is called.  If all
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destruction happened in reverse order from construction, then we
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// could call UnpatchWindowsFunctions at just the right time, so that
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that early-allocated data would be freed using the windows
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocation functions rather than tcmalloc.  The problem is that
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// windows allocates some structures lazily, so it would allocate them
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// late (using tcmalloc) and then try to deallocate them late as well.
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So instead of unpatching, we just modify all the tcmalloc routines
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they call through to the libc rountines if the memory in
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// question doesn't seem to have been allocated with tcmalloc.  I keep
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this unpatch code around for reference.
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnpatchWindowsFunctions() {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to go back to the system malloc/etc at global destruct time,
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so objects that were constructed before tcmalloc, using the system
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // malloc, can destroy themselves using the system free.  This depends
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on DLLs unloading in the reverse order in which they load!
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We also go back to the default HeapAlloc/etc, just for consistency.
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Who knows, it may help avoid weird bugs in some situations.
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_executable_windows.Unpatch();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_executable.Unpatch();
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc1.is_valid()) libc1.Unpatch();
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc2.is_valid()) libc2.Unpatch();
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc3.is_valid()) libc3.Unpatch();
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc4.is_valid()) libc4.Unpatch();
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc5.is_valid()) libc5.Unpatch();
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc6.is_valid()) libc6.Unpatch();
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc7.is_valid()) libc7.Unpatch();
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (libc8.is_valid()) libc8.Unpatch();
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1081