• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------------
2 Copyright (c) 2018-2023, Microsoft Research, Daan Leijen
3 This is free software; you can redistribute it and/or modify it under the
4 terms of the MIT license. A copy of the license can be found in the file
5 "LICENSE" at the root of this distribution.
6 -----------------------------------------------------------------------------*/
7 #pragma once
8 #ifndef MIMALLOC_TRACK_H
9 #define MIMALLOC_TRACK_H
10 
11 /* ------------------------------------------------------------------------------------------------------
12 Track memory ranges with macros for tools like Valgrind address sanitizer, or other memory checkers.
13 These can be defined for tracking allocation:
14 
15   #define mi_track_malloc_size(p,reqsize,size,zero)
16   #define mi_track_free_size(p,_size)
17 
18 The macros are set up such that the size passed to `mi_track_free_size`
19 always matches the size of `mi_track_malloc_size`. (currently, `size == mi_usable_size(p)`).
20 The `reqsize` is what the user requested, and `size >= reqsize`.
21 The `size` is either byte precise (and `size==reqsize`) if `MI_PADDING` is enabled,
22 or otherwise it is the usable block size which may be larger than the original request.
23 Use `_mi_block_size_of(void* p)` to get the full block size that was allocated (including padding etc).
24 The `zero` parameter is `true` if the allocated block is zero initialized.
25 
26 Optional:
27 
28   #define mi_track_align(p,alignedp,offset,size)
29   #define mi_track_resize(p,oldsize,newsize)
30   #define mi_track_init()
31 
32 The `mi_track_align` is called right after a `mi_track_malloc` for aligned pointers in a block.
33 The corresponding `mi_track_free` still uses the block start pointer and original size (corresponding to the `mi_track_malloc`).
34 The `mi_track_resize` is currently unused but could be called on reallocations within a block.
35 `mi_track_init` is called at program start.
36 
37 The following macros are for tools like asan and valgrind to track whether memory is
38 defined, undefined, or not accessible at all:
39 
40   #define mi_track_mem_defined(p,size)
41   #define mi_track_mem_undefined(p,size)
42   #define mi_track_mem_noaccess(p,size)
43 
44 -------------------------------------------------------------------------------------------------------*/
45 
46 #if MI_TRACK_VALGRIND
47 // valgrind tool
48 
49 #define MI_TRACK_ENABLED      1
50 #define MI_TRACK_HEAP_DESTROY 1           // track free of individual blocks on heap_destroy
51 #define MI_TRACK_TOOL         "valgrind"
52 
53 #include <valgrind/valgrind.h>
54 #include <valgrind/memcheck.h>
55 
56 #define mi_track_malloc_size(p,reqsize,size,zero) VALGRIND_MALLOCLIKE_BLOCK(p,size,MI_PADDING_SIZE /*red zone*/,zero)
57 #define mi_track_free_size(p,_size)               VALGRIND_FREELIKE_BLOCK(p,MI_PADDING_SIZE /*red zone*/)
58 #define mi_track_resize(p,oldsize,newsize)        VALGRIND_RESIZEINPLACE_BLOCK(p,oldsize,newsize,MI_PADDING_SIZE /*red zone*/)
59 #define mi_track_mem_defined(p,size)              VALGRIND_MAKE_MEM_DEFINED(p,size)
60 #define mi_track_mem_undefined(p,size)            VALGRIND_MAKE_MEM_UNDEFINED(p,size)
61 #define mi_track_mem_noaccess(p,size)             VALGRIND_MAKE_MEM_NOACCESS(p,size)
62 
63 #elif MI_TRACK_ASAN
64 // address sanitizer
65 
66 #define MI_TRACK_ENABLED      1
67 #define MI_TRACK_HEAP_DESTROY 0
68 #define MI_TRACK_TOOL         "asan"
69 
70 #include <sanitizer/asan_interface.h>
71 
72 #define mi_track_malloc_size(p,reqsize,size,zero) ASAN_UNPOISON_MEMORY_REGION(p,size)
73 #define mi_track_free_size(p,size)                ASAN_POISON_MEMORY_REGION(p,size)
74 #define mi_track_mem_defined(p,size)              ASAN_UNPOISON_MEMORY_REGION(p,size)
75 #define mi_track_mem_undefined(p,size)            ASAN_UNPOISON_MEMORY_REGION(p,size)
76 #define mi_track_mem_noaccess(p,size)             ASAN_POISON_MEMORY_REGION(p,size)
77 
78 #elif MI_TRACK_ETW
79 // windows event tracing
80 
81 #define MI_TRACK_ENABLED      1
82 #define MI_TRACK_HEAP_DESTROY 1
83 #define MI_TRACK_TOOL         "ETW"
84 
85 #define WIN32_LEAN_AND_MEAN
86 #include <windows.h>
87 #include "../src/prim/windows/etw.h"
88 
89 #define mi_track_init()                           EventRegistermicrosoft_windows_mimalloc();
90 #define mi_track_malloc_size(p,reqsize,size,zero) EventWriteETW_MI_ALLOC((UINT64)(p), size)
91 #define mi_track_free_size(p,size)                EventWriteETW_MI_FREE((UINT64)(p), size)
92 
93 #else
94 // no tracking
95 
96 #define MI_TRACK_ENABLED      0
97 #define MI_TRACK_HEAP_DESTROY 0
98 #define MI_TRACK_TOOL         "none"
99 
100 #define mi_track_malloc_size(p,reqsize,size,zero)
101 #define mi_track_free_size(p,_size)
102 
103 #endif
104 
105 // -------------------
106 // Utility definitions
107 
108 #ifndef mi_track_resize
109 #define mi_track_resize(p,oldsize,newsize)      mi_track_free_size(p,oldsize); mi_track_malloc(p,newsize,false)
110 #endif
111 
112 #ifndef mi_track_align
113 #define mi_track_align(p,alignedp,offset,size)  mi_track_mem_noaccess(p,offset)
114 #endif
115 
116 #ifndef mi_track_init
117 #define mi_track_init()
118 #endif
119 
120 #ifndef mi_track_mem_defined
121 #define mi_track_mem_defined(p,size)
122 #endif
123 
124 #ifndef mi_track_mem_undefined
125 #define mi_track_mem_undefined(p,size)
126 #endif
127 
128 #ifndef mi_track_mem_noaccess
129 #define mi_track_mem_noaccess(p,size)
130 #endif
131 
132 
133 #if MI_PADDING
134 #define mi_track_malloc(p,reqsize,zero) \
135   if ((p)!=NULL) { \
136     mi_assert_internal(mi_usable_size(p)==(reqsize)); \
137     mi_track_malloc_size(p,reqsize,reqsize,zero); \
138   }
139 #else
140 #define mi_track_malloc(p,reqsize,zero) \
141   if ((p)!=NULL) { \
142     mi_assert_internal(mi_usable_size(p)>=(reqsize)); \
143     mi_track_malloc_size(p,reqsize,mi_usable_size(p),zero); \
144   }
145 #endif
146 
147 #endif
148