15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, 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: Sanjay Ghemawat 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some of our malloc implementations can invoke the following hooks whenever 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory is allocated or deallocated. MallocHook is thread-safe, and things 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// you do before calling AddFooHook(MyHook) are visible to any resulting calls 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to MyHook. Hooks must be thread-safe. If you write: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHECK(MallocHook::AddNewHook(&MyNewHook)); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MyNewHook will be invoked in subsequent calls in the current thread, but 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there are no guarantees on when it might be invoked in other threads. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There are a limited number of slots available for each hook type. Add*Hook 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will return false if there are no slots available. Remove*Hook will return 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// false if the given hook was not already installed. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The order in which individual hooks are called in Invoke*Hook is undefined. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is safe for a hook to remove itself within Invoke*Hook and add other 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hooks. Any hooks added inside a hook invocation (for the same hook type) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will not be invoked for the current invocation. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// One important user of these hooks is the heap profiler. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CAVEAT: If you add new MallocHook::Invoke* calls then those calls must be 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// directly in the code of the (de)allocation function that is provided to the 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user and that function must have an ATTRIBUTE_SECTION(malloc_hook) attribute. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: the Invoke*Hook() functions are defined in malloc_hook-inl.h. If you 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to invoke a hook (which you shouldn't unless you're part of tcmalloc), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be sure to #include malloc_hook-inl.h in addition to malloc_hook.h. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE FOR C USERS: If you want to use malloc_hook functionality from 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a C program, #include malloc_hook_c.h instead of this file. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _MALLOC_HOOK_H_ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _MALLOC_HOOK_H_ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_hook_c.h> // a C version of the malloc_hook interface 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Annoying stuff for windows -- makes sure clients can import these functions 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PERFTOOLS_DLL_DECL 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifdef _WIN32 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define PERFTOOLS_DLL_DECL __declspec(dllimport) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define PERFTOOLS_DLL_DECL 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The C++ methods below call the C version (MallocHook_*), and thus 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// convert between an int and a bool. Windows complains about this 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (a "performance warning") which we don't care about, so we suppress. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:4800) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: malloc_hook_c.h defines MallocHook_*Hook and 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MallocHook_{Add,Remove}*Hook. The version of these inside the MallocHook 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// class are defined in terms of the malloc_hook_c version. See malloc_hook_c.h 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for details of these types/functions. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PERFTOOLS_DLL_DECL MallocHook { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The NewHook is invoked whenever an object is allocated. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may be passed NULL if the allocator returned NULL. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_NewHook NewHook; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddNewHook(NewHook hook) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddNewHook(hook); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveNewHook(NewHook hook) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveNewHook(hook); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeNewHook(const void* p, size_t s); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The DeleteHook is invoked whenever an object is deallocated. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may be passed NULL if the caller is trying to delete NULL. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_DeleteHook DeleteHook; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddDeleteHook(DeleteHook hook) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddDeleteHook(hook); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveDeleteHook(DeleteHook hook) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveDeleteHook(hook); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeDeleteHook(const void* p); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The PreMmapHook is invoked with mmap or mmap64 arguments just 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before the call is actually made. Such a hook may be useful 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in memory limited contexts, to catch allocations that will exceed 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a memory limit, and take outside actions to increase that limit. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_PreMmapHook PreMmapHook; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddPreMmapHook(PreMmapHook hook) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddPreMmapHook(hook); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemovePreMmapHook(PreMmapHook hook) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemovePreMmapHook(hook); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokePreMmapHook(const void* start, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MmapReplacement is invoked after the PreMmapHook but before 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the call is actually made. The MmapReplacement should return true 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if it handled the call, or false if it is still necessary to 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call mmap/mmap64. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should be used only by experts, and users must be be 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extremely careful to avoid recursive calls to mmap. The replacement 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be async signal safe. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only one MmapReplacement is supported. After setting an MmapReplacement 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // you must call RemoveMmapReplacement before calling SetMmapReplacement 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // again. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_MmapReplacement MmapReplacement; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool SetMmapReplacement(MmapReplacement hook) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetMmapReplacement(hook); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveMmapReplacement(MmapReplacement hook) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveMmapReplacement(hook); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool InvokeMmapReplacement(const void* start, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** result); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MmapHook is invoked whenever a region of memory is mapped. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may be passed MAP_FAILED if the mmap failed. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_MmapHook MmapHook; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddMmapHook(MmapHook hook) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddMmapHook(hook); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveMmapHook(MmapHook hook) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveMmapHook(hook); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeMmapHook(const void* result, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* start, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MunmapReplacement is invoked with munmap arguments just before 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the call is actually made. The MunmapReplacement should return true 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if it handled the call, or false if it is still necessary to 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call munmap. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should be used only by experts. The replacement should be 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // async signal safe. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only one MunmapReplacement is supported. After setting an 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MunmapReplacement you must call RemoveMunmapReplacement before 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calling SetMunmapReplacement again. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_MunmapReplacement MunmapReplacement; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool SetMunmapReplacement(MunmapReplacement hook) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetMunmapReplacement(hook); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveMunmapReplacement(MunmapReplacement hook) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveMunmapReplacement(hook); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool InvokeMunmapReplacement(const void* p, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* result); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MunmapHook is invoked whenever a region of memory is unmapped. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_MunmapHook MunmapHook; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddMunmapHook(MunmapHook hook) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddMunmapHook(hook); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveMunmapHook(MunmapHook hook) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveMunmapHook(hook); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeMunmapHook(const void* p, size_t size); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MremapHook is invoked whenever a region of memory is remapped. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_MremapHook MremapHook; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddMremapHook(MremapHook hook) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddMremapHook(hook); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveMremapHook(MremapHook hook) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveMremapHook(hook); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeMremapHook(const void* result, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* old_addr, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t old_size, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_size, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* new_addr); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The PreSbrkHook is invoked just before sbrk is called -- except when 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the increment is 0. This is because sbrk(0) is often called 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to get the top of the memory stack, and is not actually a 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // memory-allocation call. It may be useful in memory-limited contexts, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to catch allocations that will exceed the limit and take outside 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actions to increase such a limit. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_PreSbrkHook PreSbrkHook; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddPreSbrkHook(PreSbrkHook hook) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddPreSbrkHook(hook); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemovePreSbrkHook(PreSbrkHook hook) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemovePreSbrkHook(hook); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokePreSbrkHook(ptrdiff_t increment); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The SbrkHook is invoked whenever sbrk is called -- except when 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the increment is 0. This is because sbrk(0) is often called 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to get the top of the memory stack, and is not actually a 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // memory-allocation call. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MallocHook_SbrkHook SbrkHook; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool AddSbrkHook(SbrkHook hook) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_AddSbrkHook(hook); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static bool RemoveSbrkHook(SbrkHook hook) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_RemoveSbrkHook(hook); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the current stack trace. Try to skip all routines up to and 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and including the caller of MallocHook::Invoke*. 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use "skip_count" (similarly to GetStackTrace from stacktrace.h) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as a hint about how many routines to skip if better information 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not available. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static int GetCallerStackTrace(void** result, int max_depth, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int skip_count) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_GetCallerStackTrace(result, max_depth, skip_count); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unhooked versions of mmap() and munmap(). These should be used 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only by experts, since they bypass heapchecking, etc. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: These do not run hooks, but they still use the MmapReplacement 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and MunmapReplacement. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void* UnhookedMMap(void *start, size_t length, int prot, int flags, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, off_t offset); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int UnhookedMUnmap(void *start, size_t length); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The following are DEPRECATED. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static NewHook GetNewHook(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static NewHook SetNewHook(NewHook hook) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetNewHook(hook); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static DeleteHook GetDeleteHook(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static DeleteHook SetDeleteHook(DeleteHook hook) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetDeleteHook(hook); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static PreMmapHook GetPreMmapHook(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static PreMmapHook SetPreMmapHook(PreMmapHook hook) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetPreMmapHook(hook); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MmapHook GetMmapHook(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MmapHook SetMmapHook(MmapHook hook) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetMmapHook(hook); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MunmapHook GetMunmapHook(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MunmapHook SetMunmapHook(MunmapHook hook) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetMunmapHook(hook); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MremapHook GetMremapHook(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static MremapHook SetMremapHook(MremapHook hook) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetMremapHook(hook); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static PreSbrkHook GetPreSbrkHook(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static PreSbrkHook SetPreSbrkHook(PreSbrkHook hook) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetPreSbrkHook(hook); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static SbrkHook GetSbrkHook(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline static SbrkHook SetSbrkHook(SbrkHook hook) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocHook_SetSbrkHook(hook); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // End of DEPRECATED methods. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Slow path versions of Invoke*Hook. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeNewHookSlow(const void* p, size_t s); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeDeleteHookSlow(const void* p); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokePreMmapHookSlow(const void* start, 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeMmapHookSlow(const void* result, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* start, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool InvokeMmapReplacementSlow(const void* start, 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int protection, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offset, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** result); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeMunmapHookSlow(const void* p, size_t size); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool InvokeMunmapReplacementSlow(const void* p, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* result); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeMremapHookSlow(const void* result, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* old_addr, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t old_size, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_size, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* new_addr); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokePreSbrkHookSlow(ptrdiff_t increment); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InvokeSbrkHookSlow(const void* result, ptrdiff_t increment); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* _MALLOC_HOOK_H_ */ 359