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