malloc_hook.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. // Copyright (c) 2005, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // ---
  31. // Author: Sanjay Ghemawat
  32. //
  33. // Some of our malloc implementations can invoke the following hooks whenever
  34. // memory is allocated or deallocated. MallocHook is thread-safe, and things
  35. // you do before calling AddFooHook(MyHook) are visible to any resulting calls
  36. // to MyHook. Hooks must be thread-safe. If you write:
  37. //
  38. // CHECK(MallocHook::AddNewHook(&MyNewHook));
  39. //
  40. // MyNewHook will be invoked in subsequent calls in the current thread, but
  41. // there are no guarantees on when it might be invoked in other threads.
  42. //
  43. // There are a limited number of slots available for each hook type. Add*Hook
  44. // will return false if there are no slots available. Remove*Hook will return
  45. // false if the given hook was not already installed.
  46. //
  47. // The order in which individual hooks are called in Invoke*Hook is undefined.
  48. //
  49. // It is safe for a hook to remove itself within Invoke*Hook and add other
  50. // hooks. Any hooks added inside a hook invocation (for the same hook type)
  51. // will not be invoked for the current invocation.
  52. //
  53. // One important user of these hooks is the heap profiler.
  54. //
  55. // CAVEAT: If you add new MallocHook::Invoke* calls then those calls must be
  56. // directly in the code of the (de)allocation function that is provided to the
  57. // user and that function must have an ATTRIBUTE_SECTION(malloc_hook) attribute.
  58. //
  59. // Note: the Invoke*Hook() functions are defined in malloc_hook-inl.h. If you
  60. // need to invoke a hook (which you shouldn't unless you're part of tcmalloc),
  61. // be sure to #include malloc_hook-inl.h in addition to malloc_hook.h.
  62. //
  63. // NOTE FOR C USERS: If you want to use malloc_hook functionality from
  64. // a C program, #include malloc_hook_c.h instead of this file.
  65. #ifndef _MALLOC_HOOK_H_
  66. #define _MALLOC_HOOK_H_
  67. #include <stddef.h>
  68. #include <sys/types.h>
  69. extern "C" {
  70. #include "malloc_hook_c.h" // a C version of the malloc_hook interface
  71. }
  72. // Annoying stuff for windows -- makes sure clients can import these functions
  73. #ifndef PERFTOOLS_DLL_DECL
  74. # ifdef _WIN32
  75. # define PERFTOOLS_DLL_DECL __declspec(dllimport)
  76. # else
  77. # define PERFTOOLS_DLL_DECL
  78. # endif
  79. #endif
  80. // The C++ methods below call the C version (MallocHook_*), and thus
  81. // convert between an int and a bool. Windows complains about this
  82. // (a "performance warning") which we don't care about, so we suppress.
  83. #ifdef _MSC_VER
  84. #pragma warning(push)
  85. #pragma warning(disable:4800)
  86. #endif
  87. // Note: malloc_hook_c.h defines MallocHook_*Hook and
  88. // MallocHook_{Add,Remove}*Hook. The version of these inside the MallocHook
  89. // class are defined in terms of the malloc_hook_c version. See malloc_hook_c.h
  90. // for details of these types/functions.
  91. class PERFTOOLS_DLL_DECL MallocHook {
  92. public:
  93. // The NewHook is invoked whenever an object is allocated.
  94. // It may be passed NULL if the allocator returned NULL.
  95. typedef MallocHook_NewHook NewHook;
  96. inline static bool AddNewHook(NewHook hook) {
  97. return MallocHook_AddNewHook(hook);
  98. }
  99. inline static bool RemoveNewHook(NewHook hook) {
  100. return MallocHook_RemoveNewHook(hook);
  101. }
  102. inline static void InvokeNewHook(const void* p, size_t s);
  103. // The DeleteHook is invoked whenever an object is deallocated.
  104. // It may be passed NULL if the caller is trying to delete NULL.
  105. typedef MallocHook_DeleteHook DeleteHook;
  106. inline static bool AddDeleteHook(DeleteHook hook) {
  107. return MallocHook_AddDeleteHook(hook);
  108. }
  109. inline static bool RemoveDeleteHook(DeleteHook hook) {
  110. return MallocHook_RemoveDeleteHook(hook);
  111. }
  112. inline static void InvokeDeleteHook(const void* p);
  113. // The PreMmapHook is invoked with mmap or mmap64 arguments just
  114. // before the call is actually made. Such a hook may be useful
  115. // in memory limited contexts, to catch allocations that will exceed
  116. // a memory limit, and take outside actions to increase that limit.
  117. typedef MallocHook_PreMmapHook PreMmapHook;
  118. inline static bool AddPreMmapHook(PreMmapHook hook) {
  119. return MallocHook_AddPreMmapHook(hook);
  120. }
  121. inline static bool RemovePreMmapHook(PreMmapHook hook) {
  122. return MallocHook_RemovePreMmapHook(hook);
  123. }
  124. inline static void InvokePreMmapHook(const void* start,
  125. size_t size,
  126. int protection,
  127. int flags,
  128. int fd,
  129. off_t offset);
  130. // The MmapReplacement is invoked after the PreMmapHook but before
  131. // the call is actually made. The MmapReplacement should return true
  132. // if it handled the call, or false if it is still necessary to
  133. // call mmap/mmap64.
  134. // This should be used only by experts, and users must be be
  135. // extremely careful to avoid recursive calls to mmap. The replacement
  136. // should be async signal safe.
  137. // Only one MmapReplacement is supported. After setting an MmapReplacement
  138. // you must call RemoveMmapReplacement before calling SetMmapReplacement
  139. // again.
  140. typedef MallocHook_MmapReplacement MmapReplacement;
  141. inline static bool SetMmapReplacement(MmapReplacement hook) {
  142. return MallocHook_SetMmapReplacement(hook);
  143. }
  144. inline static bool RemoveMmapReplacement(MmapReplacement hook) {
  145. return MallocHook_RemoveMmapReplacement(hook);
  146. }
  147. inline static bool InvokeMmapReplacement(const void* start,
  148. size_t size,
  149. int protection,
  150. int flags,
  151. int fd,
  152. off_t offset,
  153. void** result);
  154. // The MmapHook is invoked whenever a region of memory is mapped.
  155. // It may be passed MAP_FAILED if the mmap failed.
  156. typedef MallocHook_MmapHook MmapHook;
  157. inline static bool AddMmapHook(MmapHook hook) {
  158. return MallocHook_AddMmapHook(hook);
  159. }
  160. inline static bool RemoveMmapHook(MmapHook hook) {
  161. return MallocHook_RemoveMmapHook(hook);
  162. }
  163. inline static void InvokeMmapHook(const void* result,
  164. const void* start,
  165. size_t size,
  166. int protection,
  167. int flags,
  168. int fd,
  169. off_t offset);
  170. // The MunmapReplacement is invoked with munmap arguments just before
  171. // the call is actually made. The MunmapReplacement should return true
  172. // if it handled the call, or false if it is still necessary to
  173. // call munmap.
  174. // This should be used only by experts. The replacement should be
  175. // async signal safe.
  176. // Only one MunmapReplacement is supported. After setting an
  177. // MunmapReplacement you must call RemoveMunmapReplacement before
  178. // calling SetMunmapReplacement again.
  179. typedef MallocHook_MunmapReplacement MunmapReplacement;
  180. inline static bool SetMunmapReplacement(MunmapReplacement hook) {
  181. return MallocHook_SetMunmapReplacement(hook);
  182. }
  183. inline static bool RemoveMunmapReplacement(MunmapReplacement hook) {
  184. return MallocHook_RemoveMunmapReplacement(hook);
  185. }
  186. inline static bool InvokeMunmapReplacement(const void* p,
  187. size_t size,
  188. int* result);
  189. // The MunmapHook is invoked whenever a region of memory is unmapped.
  190. typedef MallocHook_MunmapHook MunmapHook;
  191. inline static bool AddMunmapHook(MunmapHook hook) {
  192. return MallocHook_AddMunmapHook(hook);
  193. }
  194. inline static bool RemoveMunmapHook(MunmapHook hook) {
  195. return MallocHook_RemoveMunmapHook(hook);
  196. }
  197. inline static void InvokeMunmapHook(const void* p, size_t size);
  198. // The MremapHook is invoked whenever a region of memory is remapped.
  199. typedef MallocHook_MremapHook MremapHook;
  200. inline static bool AddMremapHook(MremapHook hook) {
  201. return MallocHook_AddMremapHook(hook);
  202. }
  203. inline static bool RemoveMremapHook(MremapHook hook) {
  204. return MallocHook_RemoveMremapHook(hook);
  205. }
  206. inline static void InvokeMremapHook(const void* result,
  207. const void* old_addr,
  208. size_t old_size,
  209. size_t new_size,
  210. int flags,
  211. const void* new_addr);
  212. // The PreSbrkHook is invoked just before sbrk is called -- except when
  213. // the increment is 0. This is because sbrk(0) is often called
  214. // to get the top of the memory stack, and is not actually a
  215. // memory-allocation call. It may be useful in memory-limited contexts,
  216. // to catch allocations that will exceed the limit and take outside
  217. // actions to increase such a limit.
  218. typedef MallocHook_PreSbrkHook PreSbrkHook;
  219. inline static bool AddPreSbrkHook(PreSbrkHook hook) {
  220. return MallocHook_AddPreSbrkHook(hook);
  221. }
  222. inline static bool RemovePreSbrkHook(PreSbrkHook hook) {
  223. return MallocHook_RemovePreSbrkHook(hook);
  224. }
  225. inline static void InvokePreSbrkHook(ptrdiff_t increment);
  226. // The SbrkHook is invoked whenever sbrk is called -- except when
  227. // the increment is 0. This is because sbrk(0) is often called
  228. // to get the top of the memory stack, and is not actually a
  229. // memory-allocation call.
  230. typedef MallocHook_SbrkHook SbrkHook;
  231. inline static bool AddSbrkHook(SbrkHook hook) {
  232. return MallocHook_AddSbrkHook(hook);
  233. }
  234. inline static bool RemoveSbrkHook(SbrkHook hook) {
  235. return MallocHook_RemoveSbrkHook(hook);
  236. }
  237. inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment);
  238. // Get the current stack trace. Try to skip all routines up to and
  239. // and including the caller of MallocHook::Invoke*.
  240. // Use "skip_count" (similarly to GetStackTrace from stacktrace.h)
  241. // as a hint about how many routines to skip if better information
  242. // is not available.
  243. inline static int GetCallerStackTrace(void** result, int max_depth,
  244. int skip_count) {
  245. return MallocHook_GetCallerStackTrace(result, max_depth, skip_count);
  246. }
  247. // Unhooked versions of mmap() and munmap(). These should be used
  248. // only by experts, since they bypass heapchecking, etc.
  249. // Note: These do not run hooks, but they still use the MmapReplacement
  250. // and MunmapReplacement.
  251. static void* UnhookedMMap(void *start, size_t length, int prot, int flags,
  252. int fd, off_t offset);
  253. static int UnhookedMUnmap(void *start, size_t length);
  254. // The following are DEPRECATED.
  255. inline static NewHook GetNewHook();
  256. inline static NewHook SetNewHook(NewHook hook) {
  257. return MallocHook_SetNewHook(hook);
  258. }
  259. inline static DeleteHook GetDeleteHook();
  260. inline static DeleteHook SetDeleteHook(DeleteHook hook) {
  261. return MallocHook_SetDeleteHook(hook);
  262. }
  263. inline static PreMmapHook GetPreMmapHook();
  264. inline static PreMmapHook SetPreMmapHook(PreMmapHook hook) {
  265. return MallocHook_SetPreMmapHook(hook);
  266. }
  267. inline static MmapHook GetMmapHook();
  268. inline static MmapHook SetMmapHook(MmapHook hook) {
  269. return MallocHook_SetMmapHook(hook);
  270. }
  271. inline static MunmapHook GetMunmapHook();
  272. inline static MunmapHook SetMunmapHook(MunmapHook hook) {
  273. return MallocHook_SetMunmapHook(hook);
  274. }
  275. inline static MremapHook GetMremapHook();
  276. inline static MremapHook SetMremapHook(MremapHook hook) {
  277. return MallocHook_SetMremapHook(hook);
  278. }
  279. inline static PreSbrkHook GetPreSbrkHook();
  280. inline static PreSbrkHook SetPreSbrkHook(PreSbrkHook hook) {
  281. return MallocHook_SetPreSbrkHook(hook);
  282. }
  283. inline static SbrkHook GetSbrkHook();
  284. inline static SbrkHook SetSbrkHook(SbrkHook hook) {
  285. return MallocHook_SetSbrkHook(hook);
  286. }
  287. // End of DEPRECATED methods.
  288. private:
  289. // Slow path versions of Invoke*Hook.
  290. static void InvokeNewHookSlow(const void* p, size_t s);
  291. static void InvokeDeleteHookSlow(const void* p);
  292. static void InvokePreMmapHookSlow(const void* start,
  293. size_t size,
  294. int protection,
  295. int flags,
  296. int fd,
  297. off_t offset);
  298. static void InvokeMmapHookSlow(const void* result,
  299. const void* start,
  300. size_t size,
  301. int protection,
  302. int flags,
  303. int fd,
  304. off_t offset);
  305. static bool InvokeMmapReplacementSlow(const void* start,
  306. size_t size,
  307. int protection,
  308. int flags,
  309. int fd,
  310. off_t offset,
  311. void** result);
  312. static void InvokeMunmapHookSlow(const void* p, size_t size);
  313. static bool InvokeMunmapReplacementSlow(const void* p,
  314. size_t size,
  315. int* result);
  316. static void InvokeMremapHookSlow(const void* result,
  317. const void* old_addr,
  318. size_t old_size,
  319. size_t new_size,
  320. int flags,
  321. const void* new_addr);
  322. static void InvokePreSbrkHookSlow(ptrdiff_t increment);
  323. static void InvokeSbrkHookSlow(const void* result, ptrdiff_t increment);
  324. };
  325. #ifdef _MSC_VER
  326. #pragma warning(pop)
  327. #endif
  328. #endif /* _MALLOC_HOOK_H_ */