My Project
Loading...
Searching...
No Matches
mem_track.h
1/* mem_track.h
2 *
3 * Copyright (C) 2006-2020 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23/* The memory tracker overrides the wolfSSL memory callback system and uses a
24 * static to track the total, peak and currently allocated bytes.
25 *
26 * If you are already using the memory callbacks then enabling this will
27 * override the memory callbacks and prevent your memory callbacks from
28 * working. This assumes malloc() and free() are available. Feel free to
29 * customize this for your needs.
30
31 * The enable this feature define the following:
32 * #define USE_WOLFSSL_MEMORY
33 * #define WOLFSSL_TRACK_MEMORY
34 *
35 * On startup call:
36 * InitMemoryTracker();
37 *
38 * When ready to dump the memory report call:
39 * ShowMemoryTracker();
40 *
41 * Report example:
42 * total Allocs = 228
43 * total Bytes = 93442
44 * peak Bytes = 8840
45 * current Bytes = 0
46 *
47 *
48 * You can also:
49 * #define WOLFSSL_DEBUG_MEMORY
50 *
51 * To print every alloc/free along with the function and line number.
52 * Example output:
53 * Alloc: 0x7fa14a500010 -> 120 at wc_InitRng:496
54 * Free: 0x7fa14a500010 -> 120 at wc_FreeRng:606
55 */
56
57
58#ifndef WOLFSSL_MEM_TRACK_H
59#define WOLFSSL_MEM_TRACK_H
60
61#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
62
64
65 #if defined(WOLFSSL_TRACK_MEMORY)
66 #define DO_MEM_STATS
67 #if defined(__linux__) || defined(__MACH__)
68 #define DO_MEM_LIST
69 #endif
70 #endif
71
72
73 typedef struct memoryStats {
74 long totalAllocs; /* number of allocations */
75 long totalDeallocs; /* number of deallocations */
76 long totalBytes; /* total number of bytes allocated */
77 long peakBytes; /* concurrent max bytes */
78 long currentBytes; /* total current bytes in use */
80
81 typedef struct memHint {
82 size_t thisSize; /* size of this memory */
83
84 #ifdef DO_MEM_LIST
85 struct memHint* next;
86 struct memHint* prev;
87 #ifdef WOLFSSL_DEBUG_MEMORY
88 const char* func;
89 unsigned int line;
90 #endif
91 #endif
92 void* thisMemory; /* actual memory for user */
93 } memHint;
94
95 typedef struct memoryTrack {
96 union {
97 memHint hint;
98 byte alignit[sizeof(memHint) + ((16-1) & ~(16-1))]; /* make sure we have strong alignment */
99 } u;
100 } memoryTrack;
101
102#ifdef DO_MEM_LIST
103 /* track allocations and report at end */
104 typedef struct memoryList {
105 memHint* head;
106 memHint* tail;
107 word32 count;
108 } memoryList;
109#endif
110
111#if defined(WOLFSSL_TRACK_MEMORY)
112 static memoryStats ourMemStats;
113
114 #ifdef DO_MEM_LIST
115 #include <pthread.h>
116 static memoryList ourMemList;
117 static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER;
118 #endif
119#endif
120
121
122 /* if defined to not using inline then declare function prototypes */
123 #ifdef NO_INLINE
124 #define WC_STATIC
125 #ifdef WOLFSSL_DEBUG_MEMORY
126 WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line);
127 WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line);
128 WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line);
129 #else
130 WOLFSSL_LOCAL void* TrackMalloc(size_t sz);
131 WOLFSSL_LOCAL void TrackFree(void* ptr);
132 WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz);
133 #endif
134 WOLFSSL_LOCAL int InitMemoryTracker(void);
135 WOLFSSL_LOCAL void ShowMemoryTracker(void);
136 #else
137 #define WC_STATIC static
138 #endif
139
140#ifdef WOLFSSL_DEBUG_MEMORY
141 WC_STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line)
142#else
143 WC_STATIC WC_INLINE void* TrackMalloc(size_t sz)
144#endif
145 {
146 memoryTrack* mt;
147 memHint* header;
148
149 if (sz == 0)
150 return NULL;
151
152 mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz);
153 if (mt == NULL)
154 return NULL;
155
156 header = &mt->u.hint;
157 header->thisSize = sz;
158 header->thisMemory = (byte*)mt + sizeof(memoryTrack);
159
160 #ifdef WOLFSSL_DEBUG_MEMORY
161 #ifdef WOLFSSL_DEBUG_MEMORY_PRINT
162 printf("Alloc: %p -> %u at %s:%d\n", header->thisMemory, (word32)sz, func, line);
163 #else
164 (void)func;
165 (void)line;
166 #endif
167 #endif
168
169 #ifdef DO_MEM_STATS
170 ourMemStats.totalAllocs++;
171 ourMemStats.totalBytes += sz;
172 ourMemStats.currentBytes += sz;
173 if (ourMemStats.currentBytes > ourMemStats.peakBytes)
174 ourMemStats.peakBytes = ourMemStats.currentBytes;
175 #endif
176 #ifdef DO_MEM_LIST
177 if (pthread_mutex_lock(&memLock) == 0) {
178 #ifdef WOLFSSL_DEBUG_MEMORY
179 header->func = func;
180 header->line = line;
181 #endif
182
183 /* Setup event */
184 header->next = NULL;
185 if (ourMemList.tail == NULL) {
186 ourMemList.head = header;
187 header->prev = NULL;
188 }
189 else {
190 ourMemList.tail->next = header;
191 header->prev = ourMemList.tail;
192 }
193 ourMemList.tail = header; /* add to the end either way */
194 ourMemList.count++;
195
196 pthread_mutex_unlock(&memLock);
197 }
198 #endif
199
200 return header->thisMemory;
201 }
202
203
204#ifdef WOLFSSL_DEBUG_MEMORY
205 WC_STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line)
206#else
207 WC_STATIC WC_INLINE void TrackFree(void* ptr)
208#endif
209 {
210 memoryTrack* mt;
211 memHint* header;
212 size_t sz;
213
214 if (ptr == NULL) {
215 return;
216 }
217
218 mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack));
219 header = &mt->u.hint;
220 sz = header->thisSize;
221
222 #ifdef DO_MEM_LIST
223 if (pthread_mutex_lock(&memLock) == 0)
224 {
225 #endif
226
227 #ifdef DO_MEM_STATS
228 ourMemStats.currentBytes -= header->thisSize;
229 ourMemStats.totalDeallocs++;
230 #endif
231
232 #ifdef DO_MEM_LIST
233 if (header == ourMemList.head && header == ourMemList.tail) {
234 ourMemList.head = NULL;
235 ourMemList.tail = NULL;
236 }
237 else if (header == ourMemList.head) {
238 ourMemList.head = header->next;
239 ourMemList.head->prev = NULL;
240 }
241 else if (header == ourMemList.tail) {
242 ourMemList.tail = header->prev;
243 ourMemList.tail->next = NULL;
244 }
245 else {
246 memHint* next = header->next;
247 memHint* prev = header->prev;
248 if (next)
249 next->prev = prev;
250 if (prev)
251 prev->next = next;
252 }
253 ourMemList.count--;
254
255 pthread_mutex_unlock(&memLock);
256 }
257 #endif
258
259#ifdef WOLFSSL_DEBUG_MEMORY
260#ifdef WOLFSSL_DEBUG_MEMORY_PRINT
261 printf("Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line);
262#else
263 (void)func;
264 (void)line;
265#endif
266#endif
267 (void)sz;
268
269 free(mt);
270 }
271
272
273#ifdef WOLFSSL_DEBUG_MEMORY
274 WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line)
275#else
276 WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz)
277#endif
278 {
279 #ifdef WOLFSSL_DEBUG_MEMORY
280 void* ret = TrackMalloc(sz, func, line);
281 #else
282 void* ret = TrackMalloc(sz);
283 #endif
284
285 if (ptr) {
286 /* if realloc is bigger, don't overread old ptr */
287 memoryTrack* mt;
288 memHint* header;
289
290 mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack));
291 header = &mt->u.hint;
292
293 if (header->thisSize < sz)
294 sz = header->thisSize;
295 }
296
297 if (ret && ptr)
298 XMEMCPY(ret, ptr, sz);
299
300 if (ret) {
301 #ifdef WOLFSSL_DEBUG_MEMORY
302 TrackFree(ptr, func, line);
303 #else
304 TrackFree(ptr);
305 #endif
306 }
307
308 return ret;
309 }
310
311#ifdef WOLFSSL_TRACK_MEMORY
312 static wolfSSL_Malloc_cb mfDefault = NULL;
313 static wolfSSL_Free_cb ffDefault = NULL;
314 static wolfSSL_Realloc_cb rfDefault = NULL;
315
316 WC_STATIC WC_INLINE int InitMemoryTracker(void)
317 {
318 int ret;
319
320 ret = wolfSSL_GetAllocators(&mfDefault, &ffDefault, &rfDefault);
321 if (ret < 0) {
322 printf("wolfSSL GetAllocators failed to get the defaults\n");
323 }
324 ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc);
325 if (ret < 0) {
326 printf("wolfSSL SetAllocators failed for track memory\n");
327 return ret;
328 }
329
330 #ifdef DO_MEM_LIST
331 if (pthread_mutex_lock(&memLock) == 0)
332 {
333 #endif
334
335 #ifdef DO_MEM_STATS
336 ourMemStats.totalAllocs = 0;
337 ourMemStats.totalDeallocs = 0;
338 ourMemStats.totalBytes = 0;
339 ourMemStats.peakBytes = 0;
340 ourMemStats.currentBytes = 0;
341 #endif
342
343 #ifdef DO_MEM_LIST
344 XMEMSET(&ourMemList, 0, sizeof(ourMemList));
345
346 pthread_mutex_unlock(&memLock);
347 }
348 #endif
349
350 return ret;
351 }
352
353 WC_STATIC WC_INLINE void ShowMemoryTracker(void)
354 {
355 #ifdef DO_MEM_LIST
356 if (pthread_mutex_lock(&memLock) == 0)
357 {
358 #endif
359
360 #ifdef DO_MEM_STATS
361 printf("total Allocs = %9ld\n", ourMemStats.totalAllocs);
362 printf("total Deallocs = %9ld\n", ourMemStats.totalDeallocs);
363 printf("total Bytes = %9ld\n", ourMemStats.totalBytes);
364 printf("peak Bytes = %9ld\n", ourMemStats.peakBytes);
365 printf("current Bytes = %9ld\n", ourMemStats.currentBytes);
366 #endif
367
368 #ifdef DO_MEM_LIST
369 if (ourMemList.count > 0) {
370 /* print list of allocations */
371 memHint* header;
372 for (header = ourMemList.head; header != NULL; header = header->next) {
373 printf("Leak: Ptr %p, Size %u"
374 #ifdef WOLFSSL_DEBUG_MEMORY
375 ", Func %s, Line %d"
376 #endif
377 "\n",
378 (byte*)header + sizeof(memHint), (unsigned int)header->thisSize
379 #ifdef WOLFSSL_DEBUG_MEMORY
380 , header->func, header->line
381 #endif
382 );
383 }
384 }
385
386 pthread_mutex_unlock(&memLock);
387 }
388 #endif
389 }
390
391 WC_STATIC WC_INLINE int CleanupMemoryTracker(void)
392 {
393 /* restore default allocators */
394 return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault);
395 }
396#endif
397
398#endif /* USE_WOLFSSL_MEMORY */
399
400#endif /* WOLFSSL_MEM_TRACK_H */
401
WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb, wolfSSL_Free_cb, wolfSSL_Realloc_cb)
This function registers the allocation functions used by wolfSSL. By default, if the system supports ...
Definition memory.c:102
Definition mem_track.h:81
Definition mem_track.h:104
Definition mem_track.h:73
Definition mem_track.h:95