// Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Author: Sanjay Ghemawat // // Some of our malloc implementations can invoke the following hooks // whenever memory is allocated or deallocated. If the hooks are // NULL, they are not invoked. // // One important user of these hooks is the heap profiler. // // CAVEAT: If you add new MallocHook::Invoke* calls (not for chaining hooks), // then those calls must be directly in the code of the (de)allocation // function that is provided to the user and that function must have // an ATTRIBUTE_SECTION(malloc_hook) attribute. #ifndef _MALLOC_HOOK_H #define _MALLOC_HOOK_H #include #include // Annoying stuff for windows -- makes sure clients can import these functions #ifndef PERFTOOLS_DLL_DECL # ifdef WIN32 # define PERFTOOLS_DLL_DECL __declspec(dllimport) # else # define PERFTOOLS_DLL_DECL # endif #endif class PERFTOOLS_DLL_DECL MallocHook { public: // The NewHook is invoked whenever an object is allocated. // It may be passed NULL if the allocator returned NULL. typedef void (*NewHook)(const void* ptr, size_t size); inline static NewHook GetNewHook() { return new_hook_; } inline static NewHook SetNewHook(NewHook hook) { NewHook result = new_hook_; new_hook_ = hook; return result; } inline static void InvokeNewHook(const void* p, size_t s) { if (new_hook_ != NULL) (*new_hook_)(p, s); } // The DeleteHook is invoked whenever an object is deallocated. // It may be passed NULL if the caller is trying to delete NULL. typedef void (*DeleteHook)(const void* ptr); inline static DeleteHook GetDeleteHook() { return delete_hook_; } inline static DeleteHook SetDeleteHook(DeleteHook hook) { DeleteHook result = delete_hook_; delete_hook_ = hook; return result; } inline static void InvokeDeleteHook(const void* p) { if (delete_hook_ != NULL) (*delete_hook_)(p); } // The MmapHook is invoked whenever a region of memory is mapped. // It may be passed MAP_FAILED if the mmap failed. typedef void (*MmapHook)(const void* result, const void* start, size_t size, int protection, int flags, int fd, off_t offset); inline static MmapHook GetMmapHook() { return mmap_hook_; } inline static MmapHook SetMmapHook(MmapHook hook) { MmapHook result = mmap_hook_; mmap_hook_ = hook; return result; } inline static void InvokeMmapHook(const void* result, const void* start, size_t size, int protection, int flags, int fd, off_t offset) { if (mmap_hook_ != NULL) (*mmap_hook_)(result, start, size, protection, flags, fd, offset); } // The MunmapHook is invoked whenever a region of memory is unmapped. typedef void (*MunmapHook)(const void* ptr, size_t size); inline static MunmapHook GetMunmapHook() { return munmap_hook_; } inline static MunmapHook SetMunmapHook(MunmapHook hook) { MunmapHook result = munmap_hook_; munmap_hook_ = hook; return result; } inline static void InvokeMunmapHook(const void* p, size_t size) { if (munmap_hook_ != NULL) (*munmap_hook_)(p, size); } // The MremapHook is invoked whenever a region of memory is remapped. typedef void (*MremapHook)(const void* result, const void* old_addr, size_t old_size, size_t new_size, int flags, const void* new_addr); inline static MremapHook GetMremapHook() { return mremap_hook_; } inline static MremapHook SetMremapHook(MremapHook hook) { MremapHook result = mremap_hook_; mremap_hook_ = hook; return result; } inline static void InvokeMremapHook(const void* result, const void* old_addr, size_t old_size, size_t new_size, int flags, const void* new_addr) { if (mremap_hook_ != NULL) (*mremap_hook_)(result, old_addr, old_size, new_size, flags, new_addr); } // The SbrkHook is invoked whenever sbrk is called -- except when // the increment is 0. This is because sbrk(0) is often called // to get the top of the memory stack, and is not actually a // memory-allocation call. typedef void (*SbrkHook)(const void* result, ptrdiff_t increment); inline static SbrkHook GetSbrkHook() { return sbrk_hook_; } inline static SbrkHook SetSbrkHook(SbrkHook hook) { SbrkHook result = sbrk_hook_; sbrk_hook_ = hook; return result; } inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment) { if (sbrk_hook_ != NULL && increment != 0) (*sbrk_hook_)(result, increment); } // Get the current stack trace. Try to skip all routines up to and // and including the caller of MallocHook::Invoke*. // Use "skip_count" (similarly to GetStackTrace from stacktrace.h) // as a hint about how many routines to skip if better information // is not available. static int GetCallerStackTrace(void** result, int max_depth, int skip_count); private: static NewHook new_hook_; static DeleteHook delete_hook_; static MmapHook mmap_hook_; static MunmapHook munmap_hook_; static MremapHook mremap_hook_; static SbrkHook sbrk_hook_; }; #endif /* _MALLOC_HOOK_H */