comparison mupdf-source/source/fitz/memento.c @ 3:2c135c81b16c

MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:44:09 +0200
parents b50eed0cc0ef
children
comparison
equal deleted inserted replaced
0:6015a75abc2d 3:2c135c81b16c
1 /* Copyright (C) 2009-2024 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file COPYING in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
13 CA 94129, USA, for further information.
14 */
15
16 #ifndef MEMENTO_CPP_EXTRAS_ONLY
17
18 /* Inspired by Fortify by Simon P Bullen. */
19
20 /* Set the following if we want to do a build specifically for memory
21 * squeezing. We sacrifice some features for speed. */
22 /* #define MEMENTO_SQUEEZEBUILD */
23
24 /* Set the following if you're only looking for leaks, not memory overwrites
25 * to speed the operation */
26 /* #define MEMENTO_LEAKONLY */
27
28 /* Unset the following if you don't want the speed/memory hit of tracking references. */
29 #ifndef MEMENTO_SQUEEZEBUILD
30 #define MEMENTO_TRACKREFS
31 #endif
32
33 /* Set the following to keep extra details about the history of blocks */
34 #ifndef MEMENTO_SQUEEZEBUILD
35 #define MEMENTO_DETAILS
36 #endif
37
38 /* Set what volume of memory blocks we keep around after it's been freed
39 * to check for overwrites. */
40 #define MEMENTO_FREELIST_MAX 0x2000000
41
42 /* Don't keep blocks around if they'd mean losing more than a quarter of
43 * the freelist. */
44 #define MEMENTO_FREELIST_MAX_SINGLE_BLOCK (MEMENTO_FREELIST_MAX/4)
45
46 #define COMPILING_MEMENTO_C
47
48 /* SHUT UP, MSVC. I KNOW WHAT I AM DOING. */
49 #define _CRT_SECURE_NO_WARNINGS
50
51 /* We have some GS specific tweaks; more for the GS build environment than
52 * anything else. */
53 /* #define MEMENTO_GS_HACKS */
54
55 #ifdef MEMENTO_GS_HACKS
56 /* For GS we include malloc_.h. Anyone else would just include memento.h */
57 #include "malloc_.h"
58 #include "memory_.h"
59 int atexit(void (*)(void));
60 #else
61 #ifdef MEMENTO_MUPDF_HACKS
62 #include "mupdf/memento.h"
63 #else
64 #include "memento.h"
65 #endif
66 #include <stdio.h>
67 #endif
68 #ifndef _MSC_VER
69 #include <stdint.h>
70 #include <limits.h>
71 #include <unistd.h>
72 #endif
73
74 #include <errno.h>
75 #include <stdlib.h>
76 #include <stdarg.h>
77 #include <string.h>
78
79 #ifdef __ANDROID__
80 #define MEMENTO_ANDROID
81 #include <stdio.h>
82 #endif
83
84 /* Workaround VS2012 (and earlier) missing va_copy. */
85 #ifdef _MSC_VER
86 # if _MSC_VER < 1800 /* Prior to 2013 */
87 # ifndef va_copy
88 # ifdef __va_copy
89 # define va_copy(dst,src) __va_copy(dst,src)
90 # else
91 # define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
92 # endif /* __va_copy */
93 # endif /* va_copy */
94 # endif
95 #endif
96
97 /* Hacks to portably print large sizes */
98 #ifdef _MSC_VER
99 #define FMTZ "%llu"
100 #define FMTZ_CAST _int64
101 #define FMTP "0x%p"
102 typedef unsigned _int64 mem_uint64_t;
103 #else
104 #define FMTZ "%zu"
105 #define FMTZ_CAST size_t
106 #define FMTP "%p"
107 typedef long long mem_uint64_t;
108 #endif
109
110 #define UB(x) ((intptr_t)((x) & 0xFF))
111 #define B2I(x) (UB(x) | (UB(x)<<8) | (UB(x)<<16) | (UB(x)<<24))
112 #define B2P(x) ((void *)(B2I(x) | ((B2I(x)<<16)<<16)))
113 #define MEMENTO_PREFILL_UBYTE ((unsigned char)(MEMENTO_PREFILL))
114 #define MEMENTO_PREFILL_USHORT (((unsigned short)MEMENTO_PREFILL_UBYTE) | (((unsigned short)MEMENTO_PREFILL_UBYTE)<<8))
115 #define MEMENTO_PREFILL_UINT (((unsigned int)MEMENTO_PREFILL_USHORT) | (((unsigned int)MEMENTO_PREFILL_USHORT)<<16))
116 #define MEMENTO_PREFILL_PTR (void *)(((uintptr_t)MEMENTO_PREFILL_UINT) | ((((uintptr_t)MEMENTO_PREFILL_UINT)<<16)<<16))
117 #define MEMENTO_POSTFILL_UBYTE ((unsigned char)(MEMENTO_POSTFILL))
118 #define MEMENTO_POSTFILL_USHORT (((unsigned short)MEMENTO_POSTFILL_UBYTE) | (((unsigned short)MEMENTO_POSTFILL_UBYTE)<<8))
119 #define MEMENTO_POSTFILL_UINT (((unsigned int)MEMENTO_POSTFILL_USHORT) | (((unsigned int)MEMENTO_POSTFILL_USHORT)<<16))
120 #define MEMENTO_POSTFILL_PTR (void *)(((uintptr_t)MEMENTO_POSTFILL_UINT) | ((((uintptr_t)MEMENTO_POSTFILL_UINT)<<16)<<16))
121 #define MEMENTO_ALLOCFILL_UBYTE ((unsigned char)(MEMENTO_ALLOCFILL))
122 #define MEMENTO_ALLOCFILL_USHORT (((unsigned short)MEMENTO_ALLOCFILL_UBYTE) | (((unsigned short)MEMENTO_ALLOCFILL_UBYTE)<<8))
123 #define MEMENTO_ALLOCFILL_UINT (((unsigned int)MEMENTO_ALLOCFILL_USHORT) | (((unsigned int)MEMENTO_ALLOCFILL_USHORT)<<16))
124 #define MEMENTO_ALLOCFILL_PTR (void *)(((uintptr_t)MEMENTO_ALLOCFILL_UINT) | ((((uintptr_t)MEMENTO_ALLOCFILL_UINT)<<16)<<16))
125 #define MEMENTO_FREEFILL_UBYTE ((unsigned char)(MEMENTO_FREEFILL))
126 #define MEMENTO_FREEFILL_USHORT (((unsigned short)MEMENTO_FREEFILL_UBYTE) | (((unsigned short)MEMENTO_FREEFILL_UBYTE)<<8))
127 #define MEMENTO_FREEFILL_UINT (((unsigned int)MEMENTO_FREEFILL_USHORT) | (((unsigned int)MEMENTO_FREEFILL_USHORT)<<16))
128 #define MEMENTO_FREEFILL_PTR (void *)(((uintptr_t)MEMENTO_FREEFILL_UINT) | ((((uintptr_t)MEMENTO_FREEFILL_UINT)<<16)<<16))
129
130 #ifdef MEMENTO
131
132 #ifdef MEMENTO_ANDROID
133 #include <android/log.h>
134
135 static char log_buffer[4096];
136 static int log_fill = 0;
137
138 static char log_buffer2[4096];
139
140 static int
141 android_fprintf(FILE *file, const char *fmt, ...)
142 {
143 va_list args;
144 char *p, *q;
145
146 va_start(args, fmt);
147 vsnprintf(log_buffer2, sizeof(log_buffer2)-1, fmt, args);
148 va_end(args);
149
150 /* Ensure we are always null terminated */
151 log_buffer2[sizeof(log_buffer2)-1] = 0;
152
153 p = log_buffer2;
154 q = p;
155 do
156 {
157 /* Find the end of the string, or the next \n */
158 while (*p && *p != '\n')
159 p++;
160
161 /* We need to output from q to p. Limit ourselves to what
162 * will fit in the existing */
163 if (p - q >= sizeof(log_buffer)-1 - log_fill)
164 p = q + sizeof(log_buffer)-1 - log_fill;
165
166 memcpy(&log_buffer[log_fill], q, p-q);
167 log_fill += p-q;
168 if (*p == '\n')
169 {
170 log_buffer[log_fill] = 0;
171 __android_log_print(ANDROID_LOG_ERROR, "memento", "%s", log_buffer);
172 usleep(1);
173 log_fill = 0;
174 p++; /* Skip over the \n */
175 }
176 else if (log_fill >= sizeof(log_buffer)-1)
177 {
178 log_buffer[sizeof(log_buffer2)-1] = 0;
179 __android_log_print(ANDROID_LOG_ERROR, "memento", "%s", log_buffer);
180 usleep(1);
181 log_fill = 0;
182 }
183 q = p;
184 }
185 while (*p);
186
187 return 0;
188 }
189
190 #define fprintf android_fprintf
191 #define MEMENTO_STACKTRACE_METHOD 3
192 #endif
193
194 /* _WIN64 defined implies _WIN32 will be */
195 #ifdef _WIN32
196 #include <windows.h>
197
198 static int
199 windows_fprintf(FILE *file, const char *fmt, ...)
200 {
201 va_list args;
202 char text[4096];
203 int ret;
204
205 va_start(args, fmt);
206 ret = vfprintf(file, fmt, args);
207 va_end(args);
208
209 va_start(args, fmt);
210 vsnprintf(text, 4096, fmt, args);
211 OutputDebugStringA(text);
212 va_end(args);
213
214 return ret;
215 }
216
217 #define fprintf windows_fprintf
218 #endif
219
220 #ifndef MEMENTO_STACKTRACE_METHOD
221 #ifdef __GNUC__
222 #define MEMENTO_STACKTRACE_METHOD 1
223 #endif
224 #ifdef _WIN32
225 #define MEMENTO_STACKTRACE_METHOD 2
226 #endif
227 #endif
228
229 #if defined(__linux__) || defined(__OpenBSD__)
230 #define MEMENTO_HAS_FORK
231 #elif defined(__APPLE__) && defined(__MACH__)
232 #define MEMENTO_HAS_FORK
233 #endif
234
235 #if defined(_DLL) && defined(_MSC_VER)
236 #define MEMENTO_CRT_SPEC __declspec(dllimport)
237 #else
238 #define MEMENTO_CRT_SPEC
239 #endif
240
241 /* Define the underlying allocators, just in case */
242 MEMENTO_CRT_SPEC void *MEMENTO_UNDERLYING_MALLOC(size_t);
243 MEMENTO_CRT_SPEC void MEMENTO_UNDERLYING_FREE(void *);
244 MEMENTO_CRT_SPEC void *MEMENTO_UNDERLYING_REALLOC(void *,size_t);
245 MEMENTO_CRT_SPEC void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t);
246
247 /* And some other standard functions we use. We don't include the header
248 * files, just in case they pull in unexpected others. */
249 MEMENTO_CRT_SPEC int atoi(const char *);
250 MEMENTO_CRT_SPEC char *getenv(const char *);
251
252 /* How far to search for pointers in each block when calculating nestings */
253 /* mupdf needs at least 34000ish (sizeof(fz_shade))/ */
254 #define MEMENTO_PTRSEARCH 65536
255
256 #ifndef MEMENTO_MAXPATTERN
257 #define MEMENTO_MAXPATTERN 0
258 #endif
259
260 #ifdef MEMENTO_GS_HACKS
261 #include "valgrind.h"
262 #else
263 #ifdef HAVE_VALGRIND
264 #include "valgrind/memcheck.h"
265 #else
266 #define VALGRIND_MAKE_MEM_NOACCESS(p,s) do { } while (0==1)
267 #define VALGRIND_MAKE_MEM_UNDEFINED(p,s) do { } while (0==1)
268 #define VALGRIND_MAKE_MEM_DEFINED(p,s) do { } while (0==1)
269 #endif
270 #endif
271
272 enum {
273 Memento_PreSize = 16,
274 Memento_PostSize = 16
275 };
276
277 /* Some compile time checks */
278 typedef struct
279 {
280 char MEMENTO_PRESIZE_MUST_BE_A_MULTIPLE_OF_4[Memento_PreSize & 3 ? -1 : 1];
281 char MEMENTO_POSTSIZE_MUST_BE_A_MULTIPLE_OF_4[Memento_PostSize & 3 ? -1 : 1];
282 char MEMENTO_POSTSIZE_MUST_BE_AT_LEAST_4[Memento_PostSize >= 4 ? 1 : -1];
283 char MEMENTO_PRESIZE_MUST_BE_AT_LEAST_4[Memento_PreSize >= 4 ? 1 : -1];
284 } MEMENTO_SANITY_CHECK_STRUCT;
285
286 #define MEMENTO_UINT32 unsigned int
287 #define MEMENTO_UINT16 unsigned short
288
289 #define MEMENTO_PREFILL_UINT32 ((MEMENTO_UINT32)(MEMENTO_PREFILL | (MEMENTO_PREFILL <<8) | (MEMENTO_PREFILL <<16) |(MEMENTO_PREFILL <<24)))
290 #define MEMENTO_POSTFILL_UINT16 ((MEMENTO_UINT16)(MEMENTO_POSTFILL | (MEMENTO_POSTFILL<<8)))
291 #define MEMENTO_POSTFILL_UINT32 ((MEMENTO_UINT32)(MEMENTO_POSTFILL | (MEMENTO_POSTFILL<<8) | (MEMENTO_POSTFILL<<16) |(MEMENTO_POSTFILL<<24)))
292 #define MEMENTO_FREEFILL_UINT16 ((MEMENTO_UINT16)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8)))
293 #define MEMENTO_FREEFILL_UINT32 ((MEMENTO_UINT32)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8) | (MEMENTO_FREEFILL<<16) |(MEMENTO_FREEFILL<<24)))
294
295 enum {
296 Memento_Flag_OldBlock = 1,
297 Memento_Flag_HasParent = 2,
298 Memento_Flag_BreakOnFree = 4,
299 Memento_Flag_BreakOnRealloc = 8,
300 Memento_Flag_Freed = 16,
301 Memento_Flag_KnownLeak = 32,
302 Memento_Flag_Reported = 64,
303 Memento_Flag_LastPhase = 0x80000000,
304 Memento_Flag_PhaseMask = 0xFFFF0000
305 };
306
307 enum {
308 Memento_EventType_malloc = 0,
309 Memento_EventType_calloc = 1,
310 Memento_EventType_realloc = 2,
311 Memento_EventType_free = 3,
312 Memento_EventType_new = 4,
313 Memento_EventType_delete = 5,
314 Memento_EventType_newArray = 6,
315 Memento_EventType_deleteArray = 7,
316 Memento_EventType_takeRef = 8,
317 Memento_EventType_dropRef = 9,
318 Memento_EventType_reference = 10,
319 Memento_EventType_strdup = 11,
320 Memento_EventType_asprintf = 12,
321 Memento_EventType_vasprintf = 13
322 };
323
324 static const char *eventType[] =
325 {
326 "malloc",
327 "calloc",
328 "realloc",
329 "free",
330 "new",
331 "delete",
332 "new[]",
333 "delete[]",
334 "takeRef",
335 "dropRef",
336 "reference",
337 "strdup",
338 "asprintf",
339 "vasprintf"
340 };
341
342 /* When we list leaked blocks at the end of execution, we search for pointers
343 * between blocks in order to be able to give a nice nested view.
344 * Unfortunately, if you have are running your own allocator (such as
345 * postscript's chunk allocator) you can often find that the header of the
346 * block always contains pointers to next or previous blocks. This tends to
347 * mean the nesting displayed is "uninteresting" at best :)
348 *
349 * As a hack to get around this, we have a define MEMENTO_SKIP_SEARCH that
350 * indicates how many bytes to skip over at the start of the chunk.
351 * This may cause us to miss true nestings, but such is life...
352 */
353 #ifndef MEMENTO_SEARCH_SKIP
354 #ifdef MEMENTO_GS_HACKS
355 #define MEMENTO_SEARCH_SKIP (2*sizeof(void *))
356 #else
357 #define MEMENTO_SEARCH_SKIP 0
358 #endif
359 #endif
360
361 #define MEMENTO_CHILD_MAGIC ((Memento_BlkHeader *)('M' | ('3' << 8) | ('m' << 16) | ('3' << 24)))
362 #define MEMENTO_SIBLING_MAGIC ((Memento_BlkHeader *)('n' | ('t' << 8) | ('0' << 16) | ('!' << 24)))
363
364 #ifdef MEMENTO_DETAILS
365 typedef struct Memento_hashedST Memento_hashedST;
366
367 struct Memento_hashedST
368 {
369 Memento_hashedST *next;
370 MEMENTO_UINT32 hash;
371 int count;
372 void *trace[1];
373 };
374
375 typedef struct Memento_BlkDetails Memento_BlkDetails;
376
377 struct Memento_BlkDetails
378 {
379 Memento_BlkDetails *next;
380 char type;
381 int sequence;
382 Memento_hashedST *trace;
383 };
384 #endif /* MEMENTO_DETAILS */
385
386 typedef struct Memento_BlkHeader Memento_BlkHeader;
387
388 struct Memento_BlkHeader
389 {
390 size_t rawsize;
391 int sequence;
392 int lastCheckedOK;
393 int flags;
394
395 const char *label;
396
397 /* Blocks are held in a linked list for LRU */
398 Memento_BlkHeader *next;
399 Memento_BlkHeader *prev; /* Reused as 'parent' when printing nested list */
400
401 /* Blocks are held in a splay tree for position. */
402 Memento_BlkHeader *parent;
403 Memento_BlkHeader *left;
404 Memento_BlkHeader *right;
405
406 /* Entries for nesting display calculations. Set to magic
407 * values at all other time. */
408 Memento_BlkHeader *child;
409 Memento_BlkHeader *sibling;
410
411 #ifdef MEMENTO_DETAILS
412 Memento_BlkDetails *details;
413 Memento_BlkDetails **details_tail;
414 #endif
415
416 /* On 64bit versions of windows, we need blocks to be returned
417 * from malloc as 128bit aligned due to setjmp. Hence, add a
418 * dummy padding block to make the entire struct a multiple of
419 * 128bits. This has to go before the preblk. */
420 #if defined(WIN64)
421 void *dummy;
422 #endif
423
424 char preblk[Memento_PreSize];
425 };
426
427 /* In future this could (should) be a smarter data structure, like, say,
428 * splay trees. For now, we use a list.
429 */
430 typedef struct Memento_Blocks
431 {
432 Memento_BlkHeader *head;
433 Memento_BlkHeader *tail;
434 Memento_BlkHeader *top;
435 } Memento_Blocks;
436
437 /* What sort of Mutex should we use? */
438 #ifdef MEMENTO_LOCKLESS
439 typedef int Memento_mutex;
440
441 static void Memento_initMutex(Memento_mutex *m)
442 {
443 (void)m;
444 }
445
446 #define MEMENTO_DO_LOCK() do { } while (0)
447 #define MEMENTO_DO_UNLOCK() do { } while (0)
448
449 #else
450 #if defined(_WIN32) || defined(_WIN64)
451 /* Windows */
452 typedef CRITICAL_SECTION Memento_mutex;
453
454 static void Memento_initMutex(Memento_mutex *m)
455 {
456 InitializeCriticalSection(m);
457 }
458
459 #define MEMENTO_DO_LOCK() \
460 EnterCriticalSection(&memento.mutex)
461 #define MEMENTO_DO_UNLOCK() \
462 LeaveCriticalSection(&memento.mutex)
463
464 #else
465 #include <pthread.h>
466 typedef pthread_mutex_t Memento_mutex;
467
468 static void Memento_initMutex(Memento_mutex *m)
469 {
470 pthread_mutex_init(m, NULL);
471 }
472
473 #define MEMENTO_DO_LOCK() \
474 pthread_mutex_lock(&memento.mutex)
475 #define MEMENTO_DO_UNLOCK() \
476 pthread_mutex_unlock(&memento.mutex)
477
478 #endif
479 #endif
480
481 typedef struct {
482 int begin;
483 int end;
484 } Memento_range;
485
486 /* And our global structure */
487 static struct {
488 int inited;
489 Memento_Blocks used;
490 Memento_Blocks free;
491 size_t freeListSize;
492 int sequence;
493 int paranoia;
494 int paranoidAt;
495 int countdown;
496 int lastChecked;
497 int breakAt;
498 int failAt;
499 int failing;
500 int nextFailAt;
501 int squeezeAt;
502 int squeezing;
503 int segv;
504 int pattern;
505 int nextPattern;
506 int patternBit;
507 int leaking;
508 int showDetailedBlocks;
509 int hideMultipleReallocs;
510 int hideRefChangeBacktraces;
511 int abortOnLeak;
512 int abortOnCorruption;
513 size_t maxMemory;
514 size_t alloc;
515 size_t peakAlloc;
516 mem_uint64_t totalAlloc;
517 size_t numMallocs;
518 size_t numFrees;
519 size_t numReallocs;
520 Memento_mutex mutex;
521 Memento_range *squeezes;
522 int squeezes_num;
523 int squeezes_pos;
524 int ignoreNewDelete;
525 int atexitFin;
526 int phasing;
527 int verbose;
528 int verboseNewlineSuppressed;
529 void *lastVerbosePtr;
530 char **backtraceLimitFnnames;
531 int backtraceLimitFnnamesNum;
532 #ifdef MEMENTO_DETAILS
533 Memento_hashedST *stacktraces[256];
534 int hashCollisions;
535 #endif
536 } memento;
537
538 #define MEMENTO_EXTRASIZE (sizeof(Memento_BlkHeader) + Memento_PostSize)
539
540 /* Round up size S to the next multiple of N (where N is a power of 2) */
541 #define MEMENTO_ROUNDUP(S,N) ((S + N-1)&~(N-1))
542
543 #define MEMBLK_SIZE(s) MEMENTO_ROUNDUP(s + MEMENTO_EXTRASIZE, MEMENTO_MAXALIGN)
544
545 #define MEMBLK_FROMBLK(B) (&((Memento_BlkHeader*)(void *)(B))[-1])
546 #define MEMBLK_TOBLK(B) ((void*)(&((Memento_BlkHeader*)(void*)(B))[1]))
547 #define MEMBLK_POSTPTR(B) \
548 (&((unsigned char *)(void *)(B))[(B)->rawsize + sizeof(Memento_BlkHeader)])
549
550 enum
551 {
552 SkipStackBackTraceLevels = 4
553 };
554
555 #if defined(MEMENTO_STACKTRACE_METHOD) && MEMENTO_STACKTRACE_METHOD == 1
556 extern size_t backtrace(void **, int);
557 extern void backtrace_symbols_fd(void **, size_t, int);
558 extern char **backtrace_symbols(void **, size_t);
559
560 #define MEMENTO_BACKTRACE_MAX 256
561 static int (*print_stack_value)(void *address);
562
563 /* Libbacktrace gubbins - relies on us having libdl to load the .so */
564 #ifdef HAVE_LIBDL
565 #include <dlfcn.h>
566
567 typedef void (*backtrace_error_callback) (void *data, const char *msg, int errnum);
568
569 typedef struct backtrace_state *(*backtrace_create_state_type)(
570 const char *filename, int threaded,
571 backtrace_error_callback error_callback, void *data);
572
573 typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
574 const char *filename, int lineno,
575 const char *function);
576
577 typedef int (*backtrace_pcinfo_type)(struct backtrace_state *state,
578 uintptr_t pc,
579 backtrace_full_callback callback,
580 backtrace_error_callback error_callback,
581 void *data);
582
583 typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
584 const char *symname,
585 uintptr_t symval,
586 uintptr_t symsize);
587
588 typedef int (*backtrace_syminfo_type)(struct backtrace_state *state,
589 uintptr_t addr,
590 backtrace_syminfo_callback callback,
591 backtrace_error_callback error_callback,
592 void *data);
593
594 static backtrace_syminfo_type backtrace_syminfo;
595 static backtrace_create_state_type backtrace_create_state;
596 static backtrace_pcinfo_type backtrace_pcinfo;
597 static struct backtrace_state *my_backtrace_state;
598 static void *libbt;
599 static char backtrace_exe[4096];
600 static void *current_addr;
601
602 static void error2_cb(void *data, const char *msg, int errnum)
603 {
604 (void)data;
605 (void)msg;
606 (void)errnum;
607 }
608
609 static void syminfo_cb(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
610 {
611 (void)data;
612 (void)symval;
613 (void)symsize;
614 if (sizeof(void *) == 4)
615 fprintf(stderr, " 0x%08lx %s\n", pc, symname?symname:"?");
616 else
617 fprintf(stderr, " 0x%016lx %s\n", pc, symname?symname:"?");
618 }
619
620 static void error_cb(void *data, const char *msg, int errnum)
621 {
622 (void)data;
623 (void)msg;
624 (void)errnum;
625 backtrace_syminfo(my_backtrace_state,
626 (uintptr_t)current_addr,
627 syminfo_cb,
628 error2_cb,
629 NULL);
630 }
631
632 static int full_cb(void *data, uintptr_t pc, const char *fname, int line, const char *fn)
633 {
634 if (sizeof(void *) == 4)
635 fprintf(stderr, " 0x%08lx %s(%s:%d)\n", pc, fn?fn:"?", fname?fname:"?", line);
636 else
637 fprintf(stderr, " 0x%016lx %s(%s:%d)\n", pc, fn?fn:"?", fname?fname:"?", line);
638 if (fn) {
639 int i;
640 for (i=0; i<memento.backtraceLimitFnnamesNum; ++i) {
641 if (!strcmp(fn, memento.backtraceLimitFnnames[i])) {
642 *(int*) data = 1;
643 }
644 }
645 }
646 return 0;
647 }
648
649 static int print_stack_libbt(void *addr)
650 {
651 int end = 0;
652 current_addr = addr;
653 backtrace_pcinfo(my_backtrace_state,
654 (uintptr_t)addr,
655 full_cb,
656 error_cb,
657 &end);
658 return end;
659 }
660
661 static int print_stack_libbt_failed(void *addr)
662 {
663 char **strings;
664 #if 0
665 /* Let's use a hack from Julian Smith to call gdb to extract the information */
666 /* Disabled for now, as I can't make this work. */
667 static char command[1024];
668 int e;
669 static int gdb_invocation_failed = 0;
670
671 if (gdb_invocation_failed == 0)
672 {
673 snprintf(command, sizeof(command),
674 //"gdb -q --batch -p=%i -ex 'info line *%p' -ex quit 2>/dev/null",
675 "gdb -q --batch -p=%i -ex 'info line *%p' -ex quit 2>/dev/null| egrep -v '(Thread debugging using)|(Using host libthread_db library)|(A debugging session is active)|(will be detached)|(Quit anyway)|(No such file or directory)|(^0x)|(^$)'",
676 getpid(), addr);
677 printf("%s\n", command);
678 e = system(command);
679 if (e == 0)
680 return; /* That'll do! */
681 gdb_invocation_failed = 1; /* If it's failed once, it'll probably keep failing. */
682 }
683 #endif
684
685 /* We couldn't even get gdb! Make do. */
686 strings = backtrace_symbols(&addr, 1);
687
688 if (strings == NULL || strings[0] == NULL)
689 {
690 if (sizeof(void *) == 4)
691 fprintf(stderr, " [0x%08lx]\n", (uintptr_t)addr);
692 else
693 fprintf(stderr, " [0x%016lx]\n", (uintptr_t)addr);
694 }
695 else
696 {
697 fprintf(stderr, " %s\n", strings[0]);
698 }
699 (free)(strings);
700 return 0;
701 }
702
703 static int init_libbt(void)
704 {
705 static int libbt_inited = 0;
706
707 if (libbt_inited)
708 return 0;
709 libbt_inited = 1;
710
711 libbt = dlopen("libbacktrace.so", RTLD_LAZY);
712 if (libbt == NULL)
713 libbt = dlopen("/opt/lib/libbacktrace.so", RTLD_LAZY);
714 if (libbt == NULL)
715 libbt = dlopen("/lib/libbacktrace.so", RTLD_LAZY);
716 if (libbt == NULL)
717 libbt = dlopen("/usr/lib/libbacktrace.so", RTLD_LAZY);
718 if (libbt == NULL)
719 libbt = dlopen("/usr/local/lib/libbacktrace.so", RTLD_LAZY);
720 if (libbt == NULL)
721 goto fail;
722
723 backtrace_create_state = dlsym(libbt, "backtrace_create_state");
724 backtrace_syminfo = dlsym(libbt, "backtrace_syminfo");
725 backtrace_pcinfo = dlsym(libbt, "backtrace_pcinfo");
726
727 if (backtrace_create_state == NULL ||
728 backtrace_syminfo == NULL ||
729 backtrace_pcinfo == NULL)
730 {
731 goto fail;
732 }
733
734 my_backtrace_state = backtrace_create_state(backtrace_exe,
735 1 /*BACKTRACE_SUPPORTS_THREADS*/,
736 error_cb,
737 NULL);
738 if (my_backtrace_state == NULL)
739 goto fail;
740
741 print_stack_value = print_stack_libbt;
742
743 return 1;
744
745 fail:
746 fprintf(stderr,
747 "MEMENTO: libbacktrace.so failed to load; backtraces will be sparse.\n"
748 "MEMENTO: See memento.h for how to rectify this.\n");
749 libbt = NULL;
750 backtrace_create_state = NULL;
751 backtrace_syminfo = NULL;
752 print_stack_value = print_stack_libbt_failed;
753 return 0;
754 }
755 #endif
756
757 static int print_stack_default(void *addr)
758 {
759 char **strings = backtrace_symbols(&addr, 1);
760
761 if (strings == NULL || strings[0] == NULL)
762 {
763 fprintf(stderr, " ["FMTP"]\n", addr);
764 }
765 #ifdef HAVE_LIBDL
766 else if (strchr(strings[0], ':') == NULL)
767 {
768 /* Probably a "path [address]" format string */
769 char *s = strchr(strings[0], ' ');
770
771 if (s != strings[0])
772 {
773 memcpy(backtrace_exe, strings[0], s - strings[0]);
774 backtrace_exe[s-strings[0]] = 0;
775 init_libbt();
776 print_stack_value(addr);
777 }
778 }
779 #endif
780 else
781 {
782 fprintf(stderr, " %s\n", strings[0]);
783 }
784 free(strings);
785 return 0;
786 }
787
788 static void Memento_initStacktracer(void)
789 {
790 print_stack_value = print_stack_default;
791 }
792
793 static int Memento_getStacktrace(void **stack, int *skip)
794 {
795 size_t num;
796
797 num = backtrace(&stack[0], MEMENTO_BACKTRACE_MAX);
798
799 *skip = SkipStackBackTraceLevels;
800 if (num <= SkipStackBackTraceLevels)
801 return 0;
802 return (int)(num-SkipStackBackTraceLevels);
803 }
804
805 static void Memento_showStacktrace(void **stack, int numberOfFrames)
806 {
807 int i;
808
809 for (i = 0; i < numberOfFrames; i++)
810 {
811 if (print_stack_value(stack[i]))
812 break;
813 }
814 }
815 #elif defined(MEMENTO_STACKTRACE_METHOD) && MEMENTO_STACKTRACE_METHOD == 2
816 #include <Windows.h>
817
818 /* We use DbgHelp.dll rather than DbgHelp.lib. This avoids us needing
819 * extra link time complications, and enables us to fall back gracefully
820 * if the DLL cannot be found.
821 *
822 * To achieve this we have our own potted versions of the required types
823 * inline here.
824 */
825 #ifdef _WIN64
826 typedef DWORD64 DWORD_NATIVESIZED;
827 #else
828 typedef DWORD DWORD_NATIVESIZED;
829 #endif
830
831 #define MEMENTO_BACKTRACE_MAX 64
832
833 typedef USHORT (__stdcall *My_CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
834
835 typedef struct MY_IMAGEHLP_LINE {
836 DWORD SizeOfStruct;
837 PVOID Key;
838 DWORD LineNumber;
839 PCHAR FileName;
840 DWORD_NATIVESIZED Address;
841 } MY_IMAGEHLP_LINE, *MY_PIMAGEHLP_LINE;
842
843 typedef BOOL (__stdcall *My_SymGetLineFromAddrType)(HANDLE hProcess, DWORD_NATIVESIZED dwAddr, PDWORD pdwDisplacement, MY_PIMAGEHLP_LINE Line);
844
845 typedef struct MY_SYMBOL_INFO {
846 ULONG SizeOfStruct;
847 ULONG TypeIndex; // Type Index of symbol
848 ULONG64 Reserved[2];
849 ULONG info;
850 ULONG Size;
851 ULONG64 ModBase; // Base Address of module containing this symbol
852 ULONG Flags;
853 ULONG64 Value; // Value of symbol, ValuePresent should be 1
854 ULONG64 Address; // Address of symbol including base address of module
855 ULONG Register; // register holding value or pointer to value
856 ULONG Scope; // scope of the symbol
857 ULONG Tag; // pdb classification
858 ULONG NameLen; // Actual length of name
859 ULONG MaxNameLen;
860 CHAR Name[1]; // Name of symbol
861 } MY_SYMBOL_INFO, *MY_PSYMBOL_INFO;
862
863 typedef BOOL (__stdcall *My_SymFromAddrType)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, MY_PSYMBOL_INFO Symbol);
864 typedef BOOL (__stdcall *My_SymInitializeType)(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess);
865
866 static My_CaptureStackBackTraceType Memento_CaptureStackBackTrace;
867 static My_SymGetLineFromAddrType Memento_SymGetLineFromAddr;
868 static My_SymFromAddrType Memento_SymFromAddr;
869 static My_SymInitializeType Memento_SymInitialize;
870 static HANDLE Memento_process;
871
872 static void Memento_initStacktracer(void)
873 {
874 HMODULE mod = LoadLibrary("kernel32.dll");
875
876 if (mod == NULL)
877 return;
878 Memento_CaptureStackBackTrace = (My_CaptureStackBackTraceType)(GetProcAddress(mod, "RtlCaptureStackBackTrace"));
879 if (Memento_CaptureStackBackTrace == NULL)
880 return;
881 mod = LoadLibrary("Dbghelp.dll");
882 if (mod == NULL) {
883 Memento_CaptureStackBackTrace = NULL;
884 return;
885 }
886 Memento_SymGetLineFromAddr =
887 (My_SymGetLineFromAddrType)(GetProcAddress(mod,
888 #ifdef _WIN64
889 "SymGetLineFromAddr64"
890 #else
891 "SymGetLineFromAddr"
892 #endif
893 ));
894 if (Memento_SymGetLineFromAddr == NULL) {
895 Memento_CaptureStackBackTrace = NULL;
896 return;
897 }
898 Memento_SymFromAddr = (My_SymFromAddrType)(GetProcAddress(mod, "SymFromAddr"));
899 if (Memento_SymFromAddr == NULL) {
900 Memento_CaptureStackBackTrace = NULL;
901 return;
902 }
903 Memento_SymInitialize = (My_SymInitializeType)(GetProcAddress(mod, "SymInitialize"));
904 if (Memento_SymInitialize == NULL) {
905 Memento_CaptureStackBackTrace = NULL;
906 return;
907 }
908 Memento_process = GetCurrentProcess();
909 Memento_SymInitialize(Memento_process, NULL, TRUE);
910 }
911
912 static int Memento_getStacktrace(void **stack, int *skip)
913 {
914 if (Memento_CaptureStackBackTrace == NULL)
915 return 0;
916
917 *skip = 0;
918 /* Limit us to 63 levels due to windows bug */
919 return Memento_CaptureStackBackTrace(SkipStackBackTraceLevels, 63-SkipStackBackTraceLevels, stack, NULL);
920 }
921
922 static void Memento_showStacktrace(void **stack, int numberOfFrames)
923 {
924 MY_IMAGEHLP_LINE line;
925 int i, j;
926 char symbol_buffer[sizeof(MY_SYMBOL_INFO) + 1024 + 1];
927 MY_SYMBOL_INFO *symbol = (MY_SYMBOL_INFO *)symbol_buffer;
928 BOOL ok;
929 int prefix = 1; /* Ignore a prefix of 'unknowns' */
930 int suppressed = 0; /* How many unknowns we have suppressed. */
931
932 symbol->MaxNameLen = 1024;
933 symbol->SizeOfStruct = sizeof(MY_SYMBOL_INFO);
934 line.SizeOfStruct = sizeof(MY_IMAGEHLP_LINE);
935 for (i = 0; i < numberOfFrames; i++)
936 {
937 DWORD64 dwDisplacement64;
938 DWORD dwDisplacement;
939 ok = Memento_SymFromAddr(Memento_process, (DWORD64)(stack[i]), &dwDisplacement64, symbol);
940 if (ok == 1)
941 ok = Memento_SymGetLineFromAddr(Memento_process, (DWORD_NATIVESIZED)(stack[i]), &dwDisplacement, &line);
942 if (ok == 1) {
943 for (j = 0; j < suppressed; j++)
944 fprintf(stderr, " unknown\n");
945 suppressed = 0;
946 fprintf(stderr, " %s in %s:%d\n", symbol->Name, line.FileName, line.LineNumber);
947 prefix = 0;
948 } else if (prefix == 0) {
949 suppressed++;
950 }
951 }
952 }
953 #elif defined(MEMENTO_STACKTRACE_METHOD) && MEMENTO_STACKTRACE_METHOD == 3
954
955 #include <unwind.h>
956 #include <dlfcn.h>
957
958 /* From cxxabi.h */
959 extern char* __cxa_demangle(const char* mangled_name,
960 char* output_buffer,
961 size_t* length,
962 int* status);
963
964 static void Memento_initStacktracer(void)
965 {
966 }
967
968 #define MEMENTO_BACKTRACE_MAX 256
969
970 typedef struct
971 {
972 int count;
973 void **addr;
974 } my_unwind_details;
975
976 static _Unwind_Reason_Code unwind_populate_callback(struct _Unwind_Context *context,
977 void *arg)
978 {
979 my_unwind_details *uw = (my_unwind_details *)arg;
980 int count = uw->count;
981
982 if (count >= MEMENTO_BACKTRACE_MAX)
983 return _URC_END_OF_STACK;
984
985 uw->addr[count] = (void *)_Unwind_GetIP(context);
986 uw->count++;
987
988 return _URC_NO_REASON;
989 }
990
991 static int Memento_getStacktrace(void **stack, int *skip)
992 {
993 my_unwind_details uw = { 0, stack };
994
995 *skip = 0;
996
997 /* Collect the backtrace. Deliberately only unwind once,
998 * and avoid using malloc etc until this completes just
999 * in case. */
1000 _Unwind_Backtrace(unwind_populate_callback, &uw);
1001 if (uw.count <= SkipStackBackTraceLevels)
1002 return 0;
1003
1004 *skip = SkipStackBackTraceLevels;
1005 return uw.count-SkipStackBackTraceLevels;
1006 }
1007
1008 static void Memento_showStacktrace(void **stack, int numberOfFrames)
1009 {
1010 int i;
1011
1012 for (i = 0; i < numberOfFrames; i++)
1013 {
1014 Dl_info info;
1015 if (dladdr(stack[i], &info))
1016 {
1017 int status = 0;
1018 const char *sym = info.dli_sname ? info.dli_sname : "<unknown>";
1019 char *demangled = __cxa_demangle(sym, NULL, 0, &status);
1020 int offset = stack[i] - info.dli_saddr;
1021 fprintf(stderr, " ["FMTP"]%s(+0x%x)\n", stack[i], demangled && status == 0 ? demangled : sym, offset);
1022 free(demangled);
1023 }
1024 else
1025 {
1026 fprintf(stderr, " ["FMTP"]\n", stack[i]);
1027 }
1028 }
1029 }
1030
1031 #else
1032 static void Memento_initStacktracer(void)
1033 {
1034 }
1035
1036 static int Memento_getStacktrace(void **stack, int *skip)
1037 {
1038 *skip = 0;
1039 return 0;
1040 }
1041
1042 static void Memento_showStacktrace(void **stack, int numberOfFrames)
1043 {
1044 }
1045 #endif /* MEMENTO_STACKTRACE_METHOD */
1046
1047 #ifndef MEMENTO_BACKTRACE_MAX
1048 #define MEMENTO_BACKTRACE_MAX 1
1049 #endif
1050
1051 #ifdef MEMENTO_DETAILS
1052 static MEMENTO_UINT32
1053 hashStackTrace(void **stack, int count)
1054 {
1055 int i;
1056 MEMENTO_UINT32 hash = 0;
1057
1058 count *= sizeof(void *)/sizeof(unsigned int);
1059 for (i = 0; i < count; i++)
1060 hash = (hash>>5) ^ (hash<<27) ^ ((unsigned int *)stack)[i];
1061
1062 return hash;
1063 }
1064
1065 static Memento_hashedST oom_hashed_st =
1066 {
1067 NULL, /* next */
1068 0, /* hash */
1069 0, /* count */
1070 {NULL}/* trace[0] */
1071 };
1072
1073 static Memento_hashedST *Memento_getHashedStacktrace(void)
1074 {
1075 void *stack[MEMENTO_BACKTRACE_MAX];
1076 MEMENTO_UINT32 hash;
1077 int count, skip;
1078 Memento_hashedST **h;
1079
1080 #ifdef MEMENTO_STACKTRACE_METHOD
1081 count = Memento_getStacktrace(stack, &skip);
1082 #else
1083 skip = 0;
1084 count = 0;
1085 #endif
1086
1087 count -= skip;
1088 hash = hashStackTrace(&stack[skip], count);
1089 while (1) {
1090 h = &memento.stacktraces[hash & 0xff];
1091 while (*h) {
1092 if ((*h)->hash == hash)
1093 break;
1094 h = &(*h)->next;
1095 }
1096 if ((*h) == NULL)
1097 break; /* No match, fall through to make a new one. */
1098 if (count == (*h)->count &&
1099 memcmp((*h)->trace, &stack[skip], sizeof(void *) * count) == 0)
1100 return (*h); /* We match! Reuse this one. */
1101 /* Hash collision. */
1102 hash++;
1103 memento.hashCollisions++;
1104 }
1105
1106 (*h) = MEMENTO_UNDERLYING_MALLOC(sizeof(Memento_hashedST) + sizeof(void *) * (count-1));
1107 if (*h == NULL)
1108 return &oom_hashed_st;
1109
1110 (*h)->next = NULL;
1111 (*h)->hash = hash;
1112 (*h)->count = count;
1113 memcpy(&(*h)->trace[0], &stack[skip], count * sizeof(void *));
1114
1115 return *h;
1116 }
1117
1118 static void Memento_showHashedStacktrace(Memento_hashedST *trace)
1119 {
1120 if (trace == NULL)
1121 return;
1122
1123 Memento_showStacktrace(&trace->trace[0], trace->count);
1124 }
1125
1126 static void Memento_storeDetails(Memento_BlkHeader *head, int type, Memento_hashedST *st)
1127 {
1128 Memento_BlkDetails *details;
1129
1130 if (head == NULL)
1131 return;
1132
1133 details = MEMENTO_UNDERLYING_MALLOC(sizeof(*details));
1134 if (details == NULL)
1135 return;
1136
1137 details->type = (char)type;
1138 details->sequence = memento.sequence;
1139 details->next = NULL;
1140 details->trace = st;
1141 VALGRIND_MAKE_MEM_DEFINED(&head->details_tail, sizeof(head->details_tail));
1142 *head->details_tail = details;
1143 head->details_tail = &details->next;
1144 VALGRIND_MAKE_MEM_NOACCESS(&head->details_tail, sizeof(head->details_tail));
1145 }
1146 #endif
1147
1148 void Memento_showHash(MEMENTO_UINT32 hash)
1149 {
1150 #ifdef MEMENTO_DETAILS
1151 Memento_hashedST *h;
1152
1153 h = memento.stacktraces[hash & 0xff];
1154 while (h) {
1155 if (h->hash == hash)
1156 break;
1157 h = h->next;
1158 }
1159
1160 Memento_showHashedStacktrace(h);
1161 #endif
1162 }
1163
1164 static void Memento_bt_internal(int skip2)
1165 {
1166 #ifdef MEMENTO_STACKTRACE_METHOD
1167 void *stack[MEMENTO_BACKTRACE_MAX];
1168 int count;
1169 int skip;
1170
1171 count = Memento_getStacktrace(stack, &skip);
1172 Memento_showStacktrace(&stack[skip+skip2], count-skip-skip2);
1173 #endif
1174 }
1175
1176 void (Memento_bt)(void)
1177 {
1178 Memento_bt_internal(0);
1179 }
1180
1181 static int Memento_checkAllMemoryLocked(void);
1182
1183 void Memento_breakpoint(void)
1184 {
1185 /* A handy externally visible function for breakpointing */
1186 #if 0 /* Enable this to force automatic breakpointing */
1187 #ifndef NDEBUG
1188 #ifdef _MSC_VER
1189 __asm int 3;
1190 #endif
1191 #endif
1192 #endif
1193 }
1194
1195 static void Memento_init(void);
1196
1197 #define MEMENTO_LOCK() \
1198 do { if (!memento.inited) Memento_init(); MEMENTO_DO_LOCK(); } while (0)
1199
1200 #define MEMENTO_UNLOCK() \
1201 do { MEMENTO_DO_UNLOCK(); } while (0)
1202
1203 /* Do this as a macro to prevent another level in the callstack,
1204 * which is annoying while stepping. */
1205 #define Memento_breakpointLocked() \
1206 do { MEMENTO_UNLOCK(); Memento_breakpoint(); MEMENTO_LOCK(); } while (0)
1207
1208 /* Move the given node to the root of the tree, by
1209 * performing a series of the following rotations.
1210 * The key observation here is that all these
1211 * rotations preserve the ordering of the tree, and
1212 * result in 'x' getting higher.
1213 *
1214 * Case 1: z x Case 1b: z x
1215 * # # # # # # # #
1216 * y D A y A y y D
1217 * # # => # # # # => # #
1218 * x C B z B x z C
1219 * # # # # # # # #
1220 * A B C D C D A B
1221 *
1222 * Case 2: z x Case 2b: z x
1223 * # # ## ## # # ## ##
1224 * y D y z A y z y
1225 * # # => # # # # # # => # # # #
1226 * A x A B C D x D A B C D
1227 * # # # #
1228 * B C B C
1229 *
1230 * Case 3: y x Case 3b: y x
1231 * # # # # # # # #
1232 * x C => A y A x => y C
1233 * # # # # # # # #
1234 * A B B C B C A B
1235 */
1236 static void
1237 move_to_root(Memento_BlkHeader *x)
1238 {
1239 Memento_BlkHeader *y, *z;
1240
1241 if (x == NULL)
1242 return;
1243
1244 VALGRIND_MAKE_MEM_DEFINED(x, sizeof(*x));
1245 while ((y = x->parent) != NULL) {
1246 VALGRIND_MAKE_MEM_DEFINED(y, sizeof(*y));
1247 if ((z = y->parent) != NULL) {
1248 VALGRIND_MAKE_MEM_DEFINED(z, sizeof(*z));
1249 x->parent = z->parent;
1250 if (x->parent) {
1251 VALGRIND_MAKE_MEM_DEFINED(x->parent, sizeof(*x->parent));
1252 if (x->parent->left == z)
1253 x->parent->left = x;
1254 else
1255 x->parent->right = x;
1256 VALGRIND_MAKE_MEM_NOACCESS(x->parent, sizeof(*x->parent));
1257 }
1258 y->parent = x;
1259 /* Case 1, 1b, 2 or 2b */
1260 if (y->left == x) {
1261 /* Case 1 or 2b */
1262 if (z->left == y) {
1263 /* Case 1 */
1264 y->left = x->right;
1265 if (y->left) {
1266 VALGRIND_MAKE_MEM_DEFINED(y->left, sizeof(*y->left));
1267 y->left->parent = y;
1268 VALGRIND_MAKE_MEM_NOACCESS(y->left, sizeof(*y->left));
1269 }
1270 z->left = y->right;
1271 if (z->left) {
1272 VALGRIND_MAKE_MEM_DEFINED(z->left, sizeof(*z->left));
1273 z->left->parent = z;
1274 VALGRIND_MAKE_MEM_NOACCESS(z->left, sizeof(*z->left));
1275 }
1276 y->right = z;
1277 z->parent = y;
1278 } else {
1279 /* Case 2b */
1280 z->right = x->left;
1281 if (z->right) {
1282 VALGRIND_MAKE_MEM_DEFINED(z->right, sizeof(*z->right));
1283 z->right->parent = z;
1284 VALGRIND_MAKE_MEM_NOACCESS(z->right, sizeof(*z->right));
1285 }
1286 y->left = x->right;
1287 if (y->left) {
1288 VALGRIND_MAKE_MEM_DEFINED(y->left, sizeof(*y->left));
1289 y->left->parent = y;
1290 VALGRIND_MAKE_MEM_NOACCESS(y->left, sizeof(*y->left));
1291 }
1292 x->left = z;
1293 z->parent = x;
1294 }
1295 x->right = y;
1296 } else {
1297 /* Case 2 or 1b */
1298 if (z->left == y) {
1299 /* Case 2 */
1300 y->right = x->left;
1301 if (y->right) {
1302 VALGRIND_MAKE_MEM_DEFINED(y->right, sizeof(*y->right));
1303 y->right->parent = y;
1304 VALGRIND_MAKE_MEM_NOACCESS(y->right, sizeof(*y->right));
1305 }
1306 z->left = x->right;
1307 if (z->left) {
1308 VALGRIND_MAKE_MEM_DEFINED(z->left, sizeof(*z->left));
1309 z->left->parent = z;
1310 VALGRIND_MAKE_MEM_NOACCESS(z->left, sizeof(*z->left));
1311 }
1312 x->right = z;
1313 z->parent = x;
1314 } else {
1315 /* Case 1b */
1316 z->right = y->left;
1317 if (z->right) {
1318 VALGRIND_MAKE_MEM_DEFINED(z->right, sizeof(*z->right));
1319 z->right->parent = z;
1320 VALGRIND_MAKE_MEM_NOACCESS(z->right, sizeof(*z->right));
1321 }
1322 y->right = x->left;
1323 if (y->right) {
1324 VALGRIND_MAKE_MEM_DEFINED(y->right, sizeof(*y->right));
1325 y->right->parent = y;
1326 VALGRIND_MAKE_MEM_NOACCESS(y->right, sizeof(*y->right));
1327 }
1328 y->left = z;
1329 z->parent = y;
1330 }
1331 x->left = y;
1332 }
1333 VALGRIND_MAKE_MEM_NOACCESS(z, sizeof(*z));
1334 } else {
1335 /* Case 3 or 3b */
1336 x->parent = NULL;
1337 y->parent = x;
1338 if (y->left == x) {
1339 /* Case 3 */
1340 y->left = x->right;
1341 if (y->left) {
1342 VALGRIND_MAKE_MEM_DEFINED(y->left, sizeof(*y->left));
1343 y->left->parent = y;
1344 VALGRIND_MAKE_MEM_NOACCESS(y->left, sizeof(*y->left));
1345 }
1346 x->right = y;
1347 } else {
1348 /* Case 3b */
1349 y->right = x->left;
1350 if (y->right) {
1351 VALGRIND_MAKE_MEM_DEFINED(y->right, sizeof(*y->right));
1352 y->right->parent = y;
1353 VALGRIND_MAKE_MEM_NOACCESS(y->right, sizeof(*y->right));
1354 }
1355 x->left = y;
1356 }
1357 }
1358 VALGRIND_MAKE_MEM_NOACCESS(y, sizeof(*y));
1359 }
1360 VALGRIND_MAKE_MEM_NOACCESS(x, sizeof(*x));
1361 }
1362
1363 static void Memento_removeBlockSplay(Memento_Blocks *blks,
1364 Memento_BlkHeader *b)
1365 {
1366 Memento_BlkHeader *replacement;
1367
1368 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1369 if (b->left == NULL)
1370 {
1371 /* At most one child - easy */
1372 replacement = b->right;
1373 }
1374 else if (b->right == NULL)
1375 {
1376 /* Strictly one child - easy */
1377 replacement = b->left;
1378 }
1379 else
1380 {
1381 /* 2 Children - tricky */
1382 /* Find in-order predecessor to b */
1383 replacement = b->left;
1384 VALGRIND_MAKE_MEM_DEFINED(replacement, sizeof(*replacement));
1385 while (replacement->right)
1386 {
1387 Memento_BlkHeader *o = replacement;
1388 replacement = o->right;
1389 VALGRIND_MAKE_MEM_DEFINED(replacement, sizeof(*replacement));
1390 VALGRIND_MAKE_MEM_NOACCESS(o, sizeof(*o));
1391 }
1392 /* Remove replacement - easy as just one child */
1393 (void)Memento_removeBlockSplay(NULL, replacement);
1394 /* Replace b with replacement */
1395 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1396 if (b->left) {
1397 VALGRIND_MAKE_MEM_DEFINED(b->left, sizeof(*b->left));
1398 b->left->parent = replacement;
1399 VALGRIND_MAKE_MEM_NOACCESS(b->left, sizeof(*b->left));
1400 }
1401 VALGRIND_MAKE_MEM_DEFINED(b->right, sizeof(*b->right));
1402 b->right->parent = replacement;
1403 VALGRIND_MAKE_MEM_NOACCESS(b->right, sizeof(*b->right));
1404 VALGRIND_MAKE_MEM_DEFINED(replacement, sizeof(*replacement));
1405 replacement->left = b->left;
1406 replacement->right = b->right;
1407 }
1408 if (b->parent)
1409 {
1410 VALGRIND_MAKE_MEM_DEFINED(b->parent, sizeof(*b->parent));
1411 if (b->parent->left == b)
1412 b->parent->left = replacement;
1413 else
1414 b->parent->right = replacement;
1415 VALGRIND_MAKE_MEM_NOACCESS(b->parent, sizeof(*b->parent));
1416 } else {
1417 VALGRIND_MAKE_MEM_DEFINED(&blks->top, sizeof(blks->top));
1418 blks->top = replacement;
1419 VALGRIND_MAKE_MEM_NOACCESS(&blks->top, sizeof(blks->top));
1420 }
1421 if (replacement)
1422 {
1423 VALGRIND_MAKE_MEM_DEFINED(replacement, sizeof(*replacement));
1424 replacement->parent = b->parent;
1425 VALGRIND_MAKE_MEM_NOACCESS(replacement, sizeof(*replacement));
1426 }
1427 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(*b));
1428 }
1429
1430 static void Memento_addBlockSplay(Memento_Blocks *blks,
1431 Memento_BlkHeader *b)
1432 {
1433 Memento_BlkHeader *parent = NULL;
1434 Memento_BlkHeader **n = &blks->top;
1435
1436 /* Walk down, looking for a place to put b. */
1437 VALGRIND_MAKE_MEM_DEFINED(&blks->top, sizeof(blks->top));
1438 while (*n != NULL) {
1439 Memento_BlkHeader *o = parent;
1440 VALGRIND_MAKE_MEM_DEFINED(*n, sizeof(**n));
1441 parent = *n;
1442 if (o) VALGRIND_MAKE_MEM_NOACCESS(o, sizeof(*o));
1443 VALGRIND_MAKE_MEM_DEFINED(parent, sizeof(*parent));
1444 if (b < parent)
1445 n = &parent->left;
1446 else
1447 n = &parent->right;
1448 }
1449 /* Place b */
1450 *n = b;
1451 if (parent) VALGRIND_MAKE_MEM_NOACCESS(parent, sizeof(*parent));
1452 b->parent = parent;
1453 b->left = NULL;
1454 b->right = NULL;
1455 /* Now perform the splay magic */
1456 move_to_root(b);
1457 /* This always leaves b at the top. */
1458 blks->top = b;
1459 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1460 b->parent = NULL;
1461 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(*b));
1462 VALGRIND_MAKE_MEM_NOACCESS(&blks->top, sizeof(blks->top));
1463 }
1464
1465 static void Memento_addBlockHead(Memento_Blocks *blks,
1466 Memento_BlkHeader *b,
1467 int type)
1468 {
1469 Memento_addBlockSplay(blks, b);
1470 if (blks->tail == NULL)
1471 blks->tail = b;
1472 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1473 b->next = blks->head;
1474 b->prev = NULL;
1475 if (blks->head)
1476 {
1477 VALGRIND_MAKE_MEM_DEFINED(&blks->head->prev, sizeof(blks->head->prev));
1478 blks->head->prev = b;
1479 VALGRIND_MAKE_MEM_NOACCESS(&blks->head->prev, sizeof(blks->head->prev));
1480 }
1481 blks->head = b;
1482 #ifndef MEMENTO_LEAKONLY
1483 memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize);
1484 memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize);
1485 #endif
1486 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
1487 if (type == 0) { /* malloc */
1488 VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize);
1489 } else if (type == 1) { /* free */
1490 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize);
1491 }
1492 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1493 }
1494
1495 static void Memento_addBlockTail(Memento_Blocks *blks,
1496 Memento_BlkHeader *b,
1497 int type)
1498 {
1499 Memento_addBlockSplay(blks, b);
1500 VALGRIND_MAKE_MEM_DEFINED(&blks->tail, sizeof(Memento_BlkHeader *));
1501 if (blks->head == NULL)
1502 blks->head = b;
1503 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1504 b->prev = blks->tail;
1505 b->next = NULL;
1506 if (blks->tail) {
1507 VALGRIND_MAKE_MEM_DEFINED(&blks->tail->next, sizeof(blks->tail->next));
1508 blks->tail->next = b;
1509 VALGRIND_MAKE_MEM_NOACCESS(&blks->tail->next, sizeof(blks->tail->next));
1510 }
1511 blks->tail = b;
1512 #ifndef MEMENTO_LEAKONLY
1513 memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize);
1514 memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize);
1515 #endif
1516 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
1517 if (type == 0) { /* malloc */
1518 VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize);
1519 } else if (type == 1) { /* free */
1520 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize);
1521 }
1522 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1523 VALGRIND_MAKE_MEM_NOACCESS(&blks->tail, sizeof(Memento_BlkHeader *));
1524 }
1525
1526 typedef struct BlkCheckData {
1527 /* found holds some bits:
1528 * Bit 0 (1) -> At least one block has been checked.
1529 * Bit 1 (2) -> We have found an "Allocated block".
1530 * Bit 2 (4) -> We have found a "Freed block".
1531 * Bit 3 (8) -> Trigger a breakpoint on completion.
1532 */
1533 int found;
1534 int preCorrupt;
1535 int postCorrupt;
1536 int freeCorrupt;
1537 size_t index;
1538 } BlkCheckData;
1539
1540 #ifndef MEMENTO_LEAKONLY
1541 static int Memento_Internal_checkAllocedBlock(Memento_BlkHeader *b, void *arg)
1542 {
1543 int i;
1544 MEMENTO_UINT32 *ip;
1545 unsigned char *p;
1546 BlkCheckData *data = (BlkCheckData *)arg;
1547
1548 ip = (MEMENTO_UINT32 *)(void *)(b->preblk);
1549 i = Memento_PreSize>>2;
1550 do {
1551 if (*ip++ != MEMENTO_PREFILL_UINT32)
1552 goto pre_corrupt;
1553 } while (--i);
1554 if (0) {
1555 pre_corrupt:
1556 data->preCorrupt = 1;
1557 }
1558 /* Postfill may not be aligned, so have to be slower */
1559 p = MEMBLK_POSTPTR(b);
1560 i = Memento_PostSize-4;
1561 if ((intptr_t)p & 1)
1562 {
1563 if (*p++ != MEMENTO_POSTFILL)
1564 goto post_corrupt;
1565 i--;
1566 }
1567 if ((intptr_t)p & 2)
1568 {
1569 if (*(MEMENTO_UINT16 *)p != MEMENTO_POSTFILL_UINT16)
1570 goto post_corrupt;
1571 p += 2;
1572 i -= 2;
1573 }
1574 do {
1575 if (*(MEMENTO_UINT32 *)p != MEMENTO_POSTFILL_UINT32)
1576 goto post_corrupt;
1577 p += 4;
1578 i -= 4;
1579 } while (i >= 0);
1580 if (i & 2)
1581 {
1582 if (*(MEMENTO_UINT16 *)p != MEMENTO_POSTFILL_UINT16)
1583 goto post_corrupt;
1584 p += 2;
1585 }
1586 if (i & 1)
1587 {
1588 if (*p != MEMENTO_POSTFILL)
1589 goto post_corrupt;
1590 }
1591 if (0) {
1592 post_corrupt:
1593 data->postCorrupt = 1;
1594 }
1595 if ((data->freeCorrupt | data->preCorrupt | data->postCorrupt) == 0) {
1596 b->lastCheckedOK = memento.sequence;
1597 }
1598 data->found |= 1;
1599 return 0;
1600 }
1601
1602 static int Memento_Internal_checkFreedBlock(Memento_BlkHeader *b, void *arg)
1603 {
1604 size_t i;
1605 unsigned char *p;
1606 BlkCheckData *data = (BlkCheckData *)arg;
1607
1608 p = MEMBLK_TOBLK(b); /* p will always be aligned */
1609 i = b->rawsize;
1610 /* Attempt to speed this up by checking an (aligned) int at a time */
1611 if (i >= 4) {
1612 i -= 4;
1613 do {
1614 if (*(MEMENTO_UINT32 *)p != MEMENTO_FREEFILL_UINT32)
1615 goto mismatch4;
1616 p += 4;
1617 i -= 4;
1618 } while (i > 0);
1619 i += 4;
1620 }
1621 if (i & 2) {
1622 if (*(MEMENTO_UINT16 *)p != MEMENTO_FREEFILL_UINT16)
1623 goto mismatch;
1624 p += 2;
1625 i -= 2;
1626 }
1627 if (0) {
1628 mismatch4:
1629 i += 4;
1630 }
1631 mismatch:
1632 while (i) {
1633 if (*p++ != (unsigned char)MEMENTO_FREEFILL)
1634 break;
1635 i--;
1636 }
1637 if (i) {
1638 data->freeCorrupt = 1;
1639 data->index = b->rawsize-i;
1640 }
1641 return Memento_Internal_checkAllocedBlock(b, arg);
1642 }
1643 #endif /* MEMENTO_LEAKONLY */
1644
1645 static void Memento_removeBlock(Memento_Blocks *blks,
1646 Memento_BlkHeader *b)
1647 {
1648 Memento_removeBlockSplay(blks, b);
1649 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1650 if (b->next) {
1651 VALGRIND_MAKE_MEM_DEFINED(&b->next->prev, sizeof(b->next->prev));
1652 b->next->prev = b->prev;
1653 VALGRIND_MAKE_MEM_NOACCESS(&b->next->prev, sizeof(b->next->prev));
1654 }
1655 if (b->prev) {
1656 VALGRIND_MAKE_MEM_DEFINED(&b->prev->next, sizeof(b->prev->next));
1657 b->prev->next = b->next;
1658 VALGRIND_MAKE_MEM_NOACCESS(&b->prev->next, sizeof(b->prev->next));
1659 }
1660 if (blks->tail == b)
1661 blks->tail = b->prev;
1662 if (blks->head == b)
1663 blks->head = b->next;
1664 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(*b));
1665 }
1666
1667 static void free_block(Memento_BlkHeader *head)
1668 {
1669 #ifdef MEMENTO_DETAILS
1670 Memento_BlkDetails *details = head->details;
1671
1672 while (details)
1673 {
1674 Memento_BlkDetails *next = details->next;
1675 MEMENTO_UNDERLYING_FREE(details);
1676 details = next;
1677 }
1678 #endif
1679 MEMENTO_UNDERLYING_FREE(head);
1680 }
1681
1682 static int Memento_Internal_makeSpace(size_t space)
1683 {
1684 /* If too big, it can never go on the freelist */
1685 if (space > MEMENTO_FREELIST_MAX_SINGLE_BLOCK)
1686 return 0;
1687 /* Pretend we added it on. */
1688 memento.freeListSize += space;
1689 /* Ditch blocks until it fits within our limit */
1690 while (memento.freeListSize > MEMENTO_FREELIST_MAX) {
1691 Memento_BlkHeader *head = memento.free.head;
1692 VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
1693 memento.free.head = head->next;
1694 memento.freeListSize -= MEMBLK_SIZE(head->rawsize);
1695 Memento_removeBlockSplay(&memento.free, head);
1696 VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
1697 free_block(head);
1698 }
1699 /* Make sure we haven't just completely emptied the free list */
1700 /* (This should never happen, but belt and braces... */
1701 if (memento.free.head == NULL)
1702 memento.free.tail = NULL;
1703 return 1;
1704 }
1705
1706 static int Memento_appBlocks(Memento_Blocks *blks,
1707 int (*app)(Memento_BlkHeader *,
1708 void *),
1709 void *arg)
1710 {
1711 Memento_BlkHeader *head = blks->head;
1712 Memento_BlkHeader *next;
1713 int result;
1714 while (head) {
1715 VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
1716 VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
1717 head->rawsize + Memento_PostSize);
1718 result = app(head, arg);
1719 next = head->next;
1720 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
1721 VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
1722 if (result)
1723 return result;
1724 head = next;
1725 }
1726 return 0;
1727 }
1728
1729 static Memento_BlkHeader *
1730 find_enclosing_block(Memento_Blocks *blks,
1731 void *addr,
1732 int *flags)
1733 {
1734 Memento_BlkHeader *blk;
1735
1736 VALGRIND_MAKE_MEM_DEFINED(&blks->top, sizeof(blks->top));
1737 blk = blks->top;
1738 while (blk)
1739 {
1740 Memento_BlkHeader *oblk = blk;
1741 char *blkstart;
1742 char *blkend;
1743 VALGRIND_MAKE_MEM_DEFINED(blk, sizeof(Memento_BlkHeader));
1744 if (addr < (void *)oblk) {
1745 blk = blk->left;
1746 VALGRIND_MAKE_MEM_UNDEFINED(oblk, sizeof(Memento_BlkHeader));
1747 continue;
1748 }
1749 blkstart = (char *)MEMBLK_TOBLK(blk);
1750 blkend = &blkstart[blk->rawsize];
1751 if (addr >= (void *)(blkend + Memento_PostSize)) {
1752 blk = blk->right;
1753 VALGRIND_MAKE_MEM_UNDEFINED(oblk, sizeof(Memento_BlkHeader));
1754 continue;
1755 }
1756 if (flags) {
1757 if (((void *)blkstart <= addr) && (addr < (void *)blkend))
1758 *flags = 1;
1759 else if (((void *)blk <= addr) && (addr < (void *)blkstart))
1760 *flags = 2;
1761 else
1762 *flags = 3;
1763 }
1764 VALGRIND_MAKE_MEM_UNDEFINED(oblk, sizeof(Memento_BlkHeader));
1765 return blk;
1766 }
1767 return NULL;
1768 }
1769
1770 #ifndef MEMENTO_LEAKONLY
1771 /* Distrustful - check the block is a real one */
1772 static int Memento_appBlockUser(Memento_Blocks *blks,
1773 int (*app)(Memento_BlkHeader *,
1774 void *),
1775 void *arg,
1776 Memento_BlkHeader *b)
1777 {
1778 int result;
1779 Memento_BlkHeader *head = find_enclosing_block(blks, b, NULL);
1780 if (head == NULL)
1781 return 0;
1782
1783 VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
1784 VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
1785 head->rawsize + Memento_PostSize);
1786 result = app(head, arg);
1787 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
1788 VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
1789 return result;
1790 }
1791
1792 static int Memento_appBlock(Memento_Blocks *blks,
1793 int (*app)(Memento_BlkHeader *,
1794 void *),
1795 void *arg,
1796 Memento_BlkHeader *b)
1797 {
1798 int result;
1799 (void)blks;
1800 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(Memento_BlkHeader));
1801 VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(b),
1802 b->rawsize + Memento_PostSize);
1803 result = app(b, arg);
1804 VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
1805 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1806 return result;
1807 }
1808 #endif /* MEMENTO_LEAKONLY */
1809
1810 static int showBlock(Memento_BlkHeader *b, int space)
1811 {
1812 int seq;
1813 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(Memento_BlkHeader));
1814 fprintf(stderr, FMTP":(size=" FMTZ ",num=%d)",
1815 MEMBLK_TOBLK(b), (FMTZ_CAST)b->rawsize, b->sequence);
1816 if (b->label)
1817 fprintf(stderr, "%c(%s)", space, b->label);
1818 if (b->flags & Memento_Flag_KnownLeak)
1819 fprintf(stderr, "(Known Leak)");
1820 seq = b->sequence;
1821 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1822 return seq;
1823 }
1824
1825 static void blockDisplay(Memento_BlkHeader *b, int n)
1826 {
1827 n++;
1828 while (n > 40)
1829 {
1830 fprintf(stderr, "*");
1831 n -= 40;
1832 }
1833 while(n > 0)
1834 {
1835 int i = n;
1836 if (i > 32)
1837 i = 32;
1838 n -= i;
1839 fprintf(stderr, "%s", &" "[32-i]);
1840 }
1841 showBlock(b, '\t');
1842 fprintf(stderr, "\n");
1843 }
1844
1845 static int Memento_listBlock(Memento_BlkHeader *b,
1846 void *arg)
1847 {
1848 size_t *counts = (size_t *)arg;
1849 blockDisplay(b, 0);
1850 counts[0]++;
1851 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(Memento_BlkHeader));
1852 counts[1]+= b->rawsize;
1853 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1854 return 0;
1855 }
1856
1857 static void doNestedDisplay(Memento_BlkHeader *b,
1858 int depth,
1859 int include_known_leaks
1860 )
1861 {
1862 /* Try and avoid recursion if we can help it */
1863 do {
1864 Memento_BlkHeader *c = NULL;
1865 if (!include_known_leaks && (b->flags & Memento_Flag_KnownLeak))
1866 ;
1867 else
1868 blockDisplay(b, depth);
1869 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(Memento_BlkHeader));
1870 if (b->sibling) {
1871 c = b->child;
1872 b = b->sibling;
1873 } else {
1874 b = b->child;
1875 depth++;
1876 }
1877 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
1878 if (c)
1879 doNestedDisplay(c, depth+1, include_known_leaks);
1880 } while (b);
1881 }
1882
1883 static int ptrcmp(const void *a_, const void *b_)
1884 {
1885 const char **a = (const char **)a_;
1886 const char **b = (const char **)b_;
1887 return (int)(*a-*b);
1888 }
1889
1890 static
1891 int Memento_listBlocksNested(int include_known_leaks)
1892 {
1893 int count, i, count_excluding_known_leaks, count_known_leaks;
1894 size_t size;
1895 size_t size_excluding_known_leaks, size_known_leaks;
1896 Memento_BlkHeader *b, *prev;
1897 void **blocks, *minptr, *maxptr;
1898 intptr_t mask;
1899
1900 /* Count the blocks */
1901 count = 0;
1902 size = 0;
1903 count_excluding_known_leaks = 0;
1904 size_excluding_known_leaks = 0;
1905 count_known_leaks = 0;
1906 size_known_leaks = 0;
1907 for (b = memento.used.head; b; b = b->next) {
1908 VALGRIND_MAKE_MEM_DEFINED(b, sizeof(*b));
1909 count++;
1910 size += b->rawsize;
1911 if (b->flags & Memento_Flag_KnownLeak) {
1912 count_known_leaks += 1;
1913 size_known_leaks += b->rawsize;
1914 }
1915 else {
1916 count_excluding_known_leaks += 1;
1917 size_excluding_known_leaks += b->rawsize;
1918 }
1919 }
1920
1921 if (memento.showDetailedBlocks)
1922 {
1923 /* Make our block list */
1924 blocks = MEMENTO_UNDERLYING_MALLOC(sizeof(void *) * count);
1925 if (blocks == NULL)
1926 return 1;
1927
1928 /* Populate our block list */
1929 b = memento.used.head;
1930 minptr = maxptr = MEMBLK_TOBLK(b);
1931 mask = (intptr_t)minptr;
1932 for (i = 0; b; b = b->next, i++) {
1933 void *p = MEMBLK_TOBLK(b);
1934 mask &= (intptr_t)p;
1935 if (p < minptr)
1936 minptr = p;
1937 if (p > maxptr)
1938 maxptr = p;
1939 blocks[i] = p;
1940 b->flags &= ~Memento_Flag_HasParent;
1941 b->child = NULL;
1942 b->sibling = NULL;
1943 b->prev = NULL; /* parent */
1944 }
1945 qsort(blocks, count, sizeof(void *), ptrcmp);
1946
1947 /* Now, calculate tree */
1948 for (b = memento.used.head; b; b = b->next) {
1949 char *p = MEMBLK_TOBLK(b);
1950 size_t end = (b->rawsize < MEMENTO_PTRSEARCH ? b->rawsize : MEMENTO_PTRSEARCH);
1951 size_t z;
1952 VALGRIND_MAKE_MEM_DEFINED(p, end);
1953 if (end > sizeof(void *)-1)
1954 end -= sizeof(void *)-1;
1955 else
1956 end = 0;
1957 for (z = MEMENTO_SEARCH_SKIP; z < end; z += sizeof(void *)) {
1958 void *q = *(void **)(&p[z]);
1959 void **r;
1960
1961 /* Do trivial checks on pointer */
1962 if ((mask & (intptr_t)q) != mask || q < minptr || q > maxptr)
1963 continue;
1964
1965 /* Search for pointer */
1966 r = bsearch(&q, blocks, count, sizeof(void *), ptrcmp);
1967 if (r) {
1968 /* Found child */
1969 Memento_BlkHeader *child = MEMBLK_FROMBLK(*r);
1970 Memento_BlkHeader *parent;
1971
1972 /* We're assuming tree structure, not graph - ignore second
1973 * and subsequent pointers. */
1974 if (child->prev != NULL) /* parent */
1975 continue;
1976 if (child->flags & Memento_Flag_HasParent)
1977 continue;
1978
1979 /* Not interested in pointers to ourself! */
1980 if (child == b)
1981 continue;
1982
1983 /* We're also assuming acyclicness here. If this is one of
1984 * our parents, ignore it. */
1985 parent = b->prev; /* parent */
1986 while (parent != NULL && parent != child)
1987 parent = parent->prev; /* parent */
1988 if (parent == child)
1989 continue;
1990
1991 child->sibling = b->child;
1992 b->child = child;
1993 child->prev = b; /* parent */
1994 child->flags |= Memento_Flag_HasParent;
1995 }
1996 }
1997 }
1998
1999 /* Now display with nesting */
2000 for (b = memento.used.head; b; b = b->next) {
2001 if ((b->flags & Memento_Flag_HasParent) == 0)
2002 doNestedDisplay(b, 0, include_known_leaks);
2003 }
2004
2005 MEMENTO_UNDERLYING_FREE(blocks);
2006
2007 /* Now put the blocks back for valgrind, and restore the prev
2008 * and magic values. */
2009 prev = NULL;
2010 for (b = memento.used.head; b;) {
2011 Memento_BlkHeader *next = b->next;
2012 b->prev = prev;
2013 b->child = MEMENTO_CHILD_MAGIC;
2014 b->sibling = MEMENTO_SIBLING_MAGIC;
2015 prev = b;
2016 VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(*b));
2017 b = next;
2018 }
2019 }
2020
2021 fprintf(stderr, " Total number of blocks = %d\n", count);
2022 fprintf(stderr, " Total size of blocks = "FMTZ"\n", (FMTZ_CAST)size);
2023 if (!include_known_leaks) {
2024 fprintf(stderr, " Excluding known leaks:\n");
2025 fprintf(stderr, " Number of blocks = %d\n", count_excluding_known_leaks);
2026 fprintf(stderr, " Size of blocks = "FMTZ"\n", (FMTZ_CAST) size_excluding_known_leaks);
2027 fprintf(stderr, " Known leaks:\n");
2028 fprintf(stderr, " Number of blocks = %d\n", count_known_leaks);
2029 fprintf(stderr, " Size of blocks = "FMTZ"\n", (FMTZ_CAST) size_known_leaks);
2030 }
2031
2032 return 0;
2033 }
2034
2035 static void Memento_listBlocksInternal(int include_known_leaks)
2036 {
2037 MEMENTO_LOCK();
2038 if (include_known_leaks)
2039 fprintf(stderr, "Allocated blocks:\n");
2040 else
2041 fprintf(stderr, "Allocated blocks (excluding known leaks):\n");
2042 if (Memento_listBlocksNested(include_known_leaks))
2043 {
2044 size_t counts[2];
2045 counts[0] = 0;
2046 counts[1] = 0;
2047 Memento_appBlocks(&memento.used, Memento_listBlock, &counts[0]);
2048 fprintf(stderr, " Total number of blocks = "FMTZ"\n", (FMTZ_CAST)counts[0]);
2049 fprintf(stderr, " Total size of blocks = "FMTZ"\n", (FMTZ_CAST)counts[1]);
2050 }
2051 MEMENTO_UNLOCK();
2052 }
2053
2054 void Memento_listBlocks()
2055 {
2056 Memento_listBlocksInternal(1 /*include_known_leaks*/);
2057 }
2058
2059 void Memento_listLargeBlocks()
2060 {
2061 Memento_BlkHeader *b;
2062 #define LARGE_BLOCKS 100
2063 Memento_BlkHeader *blocks[LARGE_BLOCKS];
2064 int i, n = 0;
2065
2066 MEMENTO_LOCK();
2067
2068 for (b = memento.used.head; b; b = b->next) {
2069 size_t size = b->rawsize;
2070 if (n < LARGE_BLOCKS || size > blocks[n - 1]->rawsize)
2071 {
2072 /* We need to insert this block into our list. */
2073 int l = 0, r = n;
2074 while (l < r)
2075 {
2076 int m = (l + r) >> 1;
2077 if (size > blocks[m]->rawsize)
2078 r = m;
2079 else if (blocks[m]->rawsize > size)
2080 l = m+1;
2081 else
2082 l = r = m+1;
2083 }
2084 if (n < LARGE_BLOCKS)
2085 n++;
2086 if (l < n-1)
2087 memmove(&blocks[l+1], &blocks[l], sizeof(void *) * (n - l - 1));
2088 if (l < LARGE_BLOCKS)
2089 blocks[l] = b;
2090 }
2091 }
2092
2093 for (i = 0; i < n; i++)
2094 blockDisplay(blocks[i], 0);
2095
2096 MEMENTO_UNLOCK();
2097 }
2098
2099 static int Memento_listNewBlock(Memento_BlkHeader *b,
2100 void *arg)
2101 {
2102 if (b->flags & Memento_Flag_OldBlock)
2103 return 0;
2104 b->flags |= Memento_Flag_OldBlock;
2105 return Memento_listBlock(b, arg);
2106 }
2107
2108 void Memento_listNewBlocks(void)
2109 {
2110 size_t counts[2];
2111 MEMENTO_LOCK();
2112 counts[0] = 0;
2113 counts[1] = 0;
2114 fprintf(stderr, "Blocks allocated and still extant since last list:\n");
2115 Memento_appBlocks(&memento.used, Memento_listNewBlock, &counts[0]);
2116 fprintf(stderr, " Total number of blocks = "FMTZ"\n", (FMTZ_CAST)counts[0]);
2117 fprintf(stderr, " Total size of blocks = "FMTZ"\n", (FMTZ_CAST)counts[1]);
2118 MEMENTO_UNLOCK();
2119 }
2120
2121 typedef struct
2122 {
2123 size_t counts[2];
2124 unsigned int phase;
2125 } phased_t;
2126
2127 static int Memento_listPhasedBlock(Memento_BlkHeader *b,
2128 void *arg)
2129 {
2130 phased_t *phase = (phased_t *)arg;
2131 if ((b->flags & phase->phase) == 0)
2132 return 0;
2133 b->flags = (b->flags & ~Memento_Flag_PhaseMask) | ((b->flags >> 1) & Memento_Flag_PhaseMask);
2134 return Memento_listBlock(b, arg);
2135 }
2136
2137 static int Memento_listNewPhasedBlock(Memento_BlkHeader *b,
2138 void *arg)
2139 {
2140 if ((b->flags & Memento_Flag_PhaseMask) != 0)
2141 return 0;
2142 b->flags |= Memento_Flag_LastPhase;
2143 return Memento_listBlock(b, arg);
2144 }
2145
2146 static int Memento_startPhasing(Memento_BlkHeader *b,
2147 void *arg)
2148 {
2149 b->flags |= *(int *)arg;
2150 return 0;
2151 }
2152
2153 /* On the first call to this, we mark all blocks with the
2154 * lowest 'phase' bit, (call this phase m) so they will
2155 * never be reported.
2156 *
2157 * On subsequent calls, we:
2158 * for (n = m-1; n > 0; n--)
2159 * report all blocks in phase n, moving them to n+1.
2160 * report all new blocks, and place them in phase 0.
2161 *
2162 * The upshot of this is that if you call Memento_listPhasedBlocks()
2163 * at a given point in the code, then you can watch for how long blocks
2164 * live between each time the code reaches that point.
2165 *
2166 * This is basically like Memento_listNewBlocks(), but allows for
2167 * the fact that sometimes blocks are freed just after the call.
2168 */
2169 void Memento_listPhasedBlocks(void)
2170 {
2171 phased_t phase;
2172 int num = 0;
2173 MEMENTO_LOCK();
2174 phase.phase = Memento_Flag_LastPhase;
2175 while ((phase.phase>>1) & Memento_Flag_PhaseMask)
2176 num++, phase.phase >>= 1;
2177 if (memento.phasing == 0)
2178 {
2179 fprintf(stderr, "Commencing Phasing:\n");
2180 memento.phasing = 1;
2181 Memento_appBlocks(&memento.used, Memento_startPhasing, &phase.phase);
2182 } else {
2183 phase.phase <<= 1;
2184 do
2185 {
2186 phase.counts[0] = 0;
2187 phase.counts[1] = 0;
2188 fprintf(stderr, "Blocks allocated and still extant: In phase %d (%x):\n", num, phase.phase);
2189 Memento_appBlocks(&memento.used, Memento_listPhasedBlock, &phase);
2190 fprintf(stderr, " Total number of blocks = "FMTZ"\n", (FMTZ_CAST)phase.counts[0]);
2191 fprintf(stderr, " Total size of blocks = "FMTZ"\n", (FMTZ_CAST)phase.counts[1]);
2192 phase.phase = phase.phase<<1;
2193 num--;
2194 }
2195 while (phase.phase != 0);
2196 phase.counts[0] = 0;
2197 phase.counts[1] = 0;
2198 fprintf(stderr, "Blocks allocated and still extant: In phase 0:\n");
2199 Memento_appBlocks(&memento.used, Memento_listNewPhasedBlock, &phase);
2200 fprintf(stderr, " Total number of blocks = "FMTZ"\n", (FMTZ_CAST)phase.counts[0]);
2201 fprintf(stderr, " Total size of blocks = "FMTZ"\n", (FMTZ_CAST)phase.counts[1]);
2202 }
2203 MEMENTO_UNLOCK();
2204 }
2205
2206 static void Memento_endStats(void)
2207 {
2208 fprintf(stderr, "Total memory malloced = "FMTZ" bytes\n", (FMTZ_CAST)memento.totalAlloc);
2209 fprintf(stderr, "Peak memory malloced = "FMTZ" bytes\n", (FMTZ_CAST)memento.peakAlloc);
2210 fprintf(stderr, FMTZ" mallocs, "FMTZ" frees, "FMTZ" reallocs\n", (FMTZ_CAST)memento.numMallocs,
2211 (FMTZ_CAST)memento.numFrees, (FMTZ_CAST)memento.numReallocs);
2212 fprintf(stderr, "Average allocation size "FMTZ" bytes\n", (FMTZ_CAST)
2213 (memento.numMallocs != 0 ? memento.totalAlloc/memento.numMallocs: 0));
2214 #ifdef MEMENTO_DETAILS
2215 if (memento.hashCollisions)
2216 fprintf(stderr, "%d hash collisions\n", memento.hashCollisions);
2217 #endif
2218 }
2219
2220 void Memento_stats(void)
2221 {
2222 MEMENTO_LOCK();
2223 fprintf(stderr, "Current memory malloced = "FMTZ" bytes\n", (FMTZ_CAST)memento.alloc);
2224 Memento_endStats();
2225 MEMENTO_UNLOCK();
2226 }
2227
2228 #ifdef MEMENTO_DETAILS
2229 static int showInfo(Memento_BlkHeader *b, void *arg)
2230 {
2231 Memento_BlkDetails *details;
2232
2233 int include_known_leaks = (arg) ? *(int*) arg : 1;
2234
2235 fprintf(stderr, FMTP":(size="FMTZ",num=%d)",
2236 MEMBLK_TOBLK(b), (FMTZ_CAST)b->rawsize, b->sequence);
2237 if (b->label)
2238 fprintf(stderr, " (%s)", b->label);
2239 if (b->flags & Memento_Flag_KnownLeak)
2240 fprintf(stderr, "(Known Leak)");
2241 fprintf(stderr, "\nEvents:\n");
2242
2243 for (details = b->details; details; details = details->next)
2244 {
2245 if (memento.hideMultipleReallocs &&
2246 details->type == Memento_EventType_realloc &&
2247 details->next &&
2248 details->next->type == Memento_EventType_realloc) {
2249 continue;
2250 }
2251 fprintf(stderr, " Event %d (%s)\n", details->sequence, eventType[(int)details->type]);
2252 if (memento.hideRefChangeBacktraces && (
2253 details->type == Memento_EventType_takeRef
2254 || details->type == Memento_EventType_dropRef))
2255 continue;
2256 if (!include_known_leaks && (b->flags & Memento_Flag_KnownLeak))
2257 continue;
2258 Memento_showHashedStacktrace(details->trace);
2259 if (memento.showDetailedBlocks > 0) {
2260 memento.showDetailedBlocks -= 1;
2261 if (memento.showDetailedBlocks == 0) {
2262 fprintf(stderr, "Stopping display of block details because memento.showDetailedBlocks is now zero.\n");
2263 return 1;
2264 }
2265 }
2266 }
2267 return 0;
2268 }
2269 #endif
2270
2271 static void Memento_listBlockInfoInternal(int include_known_leaks)
2272 {
2273 #ifdef MEMENTO_DETAILS
2274 MEMENTO_LOCK();
2275 fprintf(stderr, "Details of allocated blocks:\n");
2276 Memento_appBlocks(&memento.used, showInfo, &include_known_leaks);
2277 MEMENTO_UNLOCK();
2278 #endif
2279 }
2280
2281 void Memento_listBlockInfo(void)
2282 {
2283 Memento_listBlockInfoInternal(1 /*include_known_leaks*/);
2284 }
2285
2286 void Memento_blockInfo(void *p)
2287 {
2288 #ifdef MEMENTO_DETAILS
2289 Memento_BlkHeader *blk;
2290 MEMENTO_LOCK();
2291 blk = find_enclosing_block(&memento.used, p, NULL);
2292 if (blk == NULL)
2293 blk = find_enclosing_block(&memento.free, p, NULL);
2294 if (blk)
2295 showInfo(blk, NULL);
2296 MEMENTO_UNLOCK();
2297 #endif
2298 }
2299
2300 static int Memento_nonLeakBlocksLeaked(void)
2301 {
2302 Memento_BlkHeader *blk = memento.used.head;
2303 while (blk)
2304 {
2305 Memento_BlkHeader *next;
2306 int leaked;
2307 VALGRIND_MAKE_MEM_DEFINED(blk, sizeof(*blk));
2308 leaked = ((blk->flags & Memento_Flag_KnownLeak) == 0);
2309 next = blk->next;
2310 VALGRIND_MAKE_MEM_DEFINED(blk, sizeof(*blk));
2311 if (leaked)
2312 return 1;
2313 blk = next;
2314 }
2315 return 0;
2316 }
2317
2318 void Memento_fin(void)
2319 {
2320 int leaked = 0;
2321 Memento_checkAllMemory();
2322 if (!memento.segv)
2323 {
2324 Memento_endStats();
2325 if (Memento_nonLeakBlocksLeaked()) {
2326 Memento_listBlocksInternal(0 /*include_known_leaks*/);
2327 #ifdef MEMENTO_DETAILS
2328 fprintf(stderr, "\n");
2329 if (memento.showDetailedBlocks)
2330 Memento_listBlockInfoInternal(0 /*include_known_leaks*/);
2331 #endif
2332 Memento_breakpoint();
2333 leaked = 1;
2334 }
2335 }
2336 if (memento.squeezing) {
2337 if (memento.pattern == 0)
2338 fprintf(stderr, "Memory squeezing @ %d complete%s\n", memento.squeezeAt, memento.segv ? " (with SEGV)" : (leaked ? " (with leaks)" : ""));
2339 else
2340 fprintf(stderr, "Memory squeezing @ %d (%d) complete%s\n", memento.squeezeAt, memento.pattern, memento.segv ? " (with SEGV)" : (leaked ? " (with leaks)" : ""));
2341 } else if (memento.segv) {
2342 fprintf(stderr, "Memento completed (with SEGV)\n");
2343 }
2344 if (memento.failing)
2345 {
2346 fprintf(stderr, "MEMENTO_FAILAT=%d\n", memento.failAt);
2347 fprintf(stderr, "MEMENTO_PATTERN=%d\n", memento.pattern);
2348 }
2349 if (memento.nextFailAt != 0)
2350 {
2351 fprintf(stderr, "MEMENTO_NEXTFAILAT=%d\n", memento.nextFailAt);
2352 fprintf(stderr, "MEMENTO_NEXTPATTERN=%d\n", memento.nextPattern);
2353 }
2354 if (Memento_nonLeakBlocksLeaked() && memento.abortOnLeak) {
2355 fprintf(stderr, "Calling abort() because blocks were leaked and MEMENTO_ABORT_ON_LEAK is set.\n");
2356 abort();
2357 }
2358 }
2359
2360 /* Reads number from <text> using strtol().
2361 *
2362 * Params:
2363 * text:
2364 * text to read.
2365 * out:
2366 * pointer to output value.
2367 * relative:
2368 * *relative set to 1 if <text> starts with '+' or '-', else set to 0.
2369 * end:
2370 * *end is set to point to next unread character after number.
2371 *
2372 * Returns 0 on success, else -1.
2373 */
2374 static int read_number(const char *text, int *out, int *relative, char **end)
2375 {
2376 if (text[0] == '+' || text[0] == '-')
2377 *relative = 1;
2378 else
2379 *relative = 0;
2380 errno = 0;
2381 *out = (int)strtol(text, end, 0 /*base*/);
2382 if (errno || *end == text)
2383 {
2384 fprintf(stderr, "Failed to parse number at start of '%s'.\n", text);
2385 return -1;
2386 }
2387 if (0)
2388 fprintf(stderr, "text='%s': *out=%i *relative=%i\n",
2389 text, *out, *relative);
2390 return 0;
2391 }
2392
2393 /* Reads number plus optional delta value from <text>.
2394 *
2395 * Evaluates <number> or <number>[+|-<delta>]. E.g. text='1234+2' sets *out=1236,
2396 * text='1234-1' sets *out=1233.
2397 *
2398 * Params:
2399 * text:
2400 * text to read.
2401 * out:
2402 * pointer to output value.
2403 * end:
2404 * *end is set to point to next unread character after number.
2405 *
2406 * Returns 0 on success, else -1.
2407 */
2408 static int read_number_delta(const char *text, int *out, char **end)
2409 {
2410 int e;
2411 int relative;
2412
2413 e = read_number(text, out, &relative, end);
2414 if (e)
2415 return e;
2416 if (relative) {
2417 fprintf(stderr, "Base number should not start with '+' or '-' at start of '%s'.\n",
2418 text);
2419 return -1;
2420 }
2421 if (*end) {
2422 if (**end == '-' || **end == '+') {
2423 int delta;
2424 e = read_number(*end, &delta, &relative, end);
2425 if (e)
2426 return e;
2427 *out += delta;
2428 }
2429 }
2430 if (0) fprintf(stderr, "text='%s': *out=%i\n", text, *out);
2431
2432 return 0;
2433 }
2434
2435 /* Reads range.
2436 *
2437 * E.g.:
2438 * text='115867-2' sets *begin=115865 *end=115866.
2439 * text='115867-1..+3' sets *begin=115866 *end=115869.
2440 *
2441 * Supported patterns for text:
2442 * <range>
2443 * <value> - returns *begin=value *end=*begin+1.
2444 * <value1>..<value2> - returns *begin=value1 *end=value2.
2445 * <value>..+<number> - returns *begin=value *end=*begin+number.
2446 * <value>
2447 * <number>
2448 * <number>+<number>
2449 * <number>-<number>
2450 *
2451 * <number>: [0-9]+
2452 *
2453 * If not specified, *end defaults to *begin+1.
2454 *
2455 * Returns 0 on success, else -1, with *string_end pointing to first unused
2456 * character.
2457 */
2458 static int read_number_range(const char *text, int *begin, int *end, char **string_end)
2459 {
2460 int e;
2461 e = read_number_delta(text, begin, string_end);
2462 if (e)
2463 return e;
2464 if (string_end && (*string_end)[0] == '.' && (*string_end)[1] == '.') {
2465 int relative;
2466 e = read_number((*string_end) + 2, end, &relative, string_end);
2467 if (e)
2468 return e;
2469 if (relative)
2470 *end += *begin;
2471 } else {
2472 *end = *begin + 1;
2473 }
2474 if (*end < *begin) {
2475 fprintf(stderr, "Range %i..%i has negative extent, at start of '%s'.\n",
2476 *begin, *end, text);
2477 return -1;
2478 }
2479 if (0) fprintf(stderr, "text='%s': *begin=%i *end=%i\n", text, *begin, *end);
2480
2481 return 0;
2482 }
2483
2484 /* Format: <range>[,<range>]+
2485 *
2486 * For description of <range>, see read_number_range() above.
2487 *
2488 * E.g.:
2489 * MEMENTO_SQUEEZES=1234-2..+4,2345,2350..+2
2490 */
2491 static int Memento_add_squeezes(const char *text)
2492 {
2493 int e = 0;
2494 for(;;) {
2495 int begin;
2496 int end;
2497 char *string_end;
2498 if (!*text)
2499 break;
2500 e = read_number_range(text, &begin, &end, &string_end);
2501 if (e)
2502 break;
2503 if (*string_end && *string_end != ',') {
2504 fprintf(stderr, "Expecting comma at start of '%s'.\n", string_end);
2505 e = -1;
2506 break;
2507 }
2508 fprintf(stderr, "Adding squeeze range %i..%i.\n",
2509 begin, end);
2510 memento.squeezes_num += 1;
2511 memento.squeezes = MEMENTO_UNDERLYING_REALLOC(
2512 memento.squeezes,
2513 memento.squeezes_num * sizeof(*memento.squeezes)
2514 );
2515 if (!memento.squeezes) {
2516 fprintf(stderr, "Failed to allocate memory for memento.squeezes_num=%i\n",
2517 memento.squeezes_num);
2518 e = -1;
2519 break;
2520 }
2521 memento.squeezes[memento.squeezes_num-1].begin = begin;
2522 memento.squeezes[memento.squeezes_num-1].end = end;
2523
2524 if (*string_end == 0)
2525 break;
2526 text = string_end + 1;
2527 }
2528
2529 return e;
2530 }
2531
2532 #if defined(_WIN32) || defined(_WIN64)
2533 static int Memento_fin_win(void)
2534 {
2535 if (memento.atexitFin)
2536 Memento_fin();
2537 return 0;
2538 }
2539 #else
2540 static void Memento_fin_unix(void)
2541 {
2542 if (memento.atexitFin)
2543 Memento_fin();
2544 }
2545 #endif
2546
2547 static void Memento_init(void)
2548 {
2549 char *env;
2550 memset(&memento, 0, sizeof(memento));
2551 memento.inited = 1;
2552 memento.used.head = NULL;
2553 memento.used.tail = NULL;
2554 memento.free.head = NULL;
2555 memento.free.tail = NULL;
2556 memento.sequence = 0;
2557 memento.countdown = 1024;
2558 memento.squeezes = NULL;
2559 memento.squeezes_num = 0;
2560 memento.squeezes_pos = 0;
2561 memento.backtraceLimitFnnames = NULL;
2562 memento.backtraceLimitFnnamesNum = 0;
2563
2564 env = getenv("MEMENTO_FAILAT");
2565 memento.failAt = (env ? atoi(env) : 0);
2566
2567 env = getenv("MEMENTO_BREAKAT");
2568 memento.breakAt = (env ? atoi(env) : 0);
2569
2570 env = getenv("MEMENTO_PARANOIA");
2571 memento.paranoia = (env ? atoi(env) : 0);
2572 if (memento.paranoia == 0)
2573 memento.paranoia = -1024;
2574
2575 env = getenv("MEMENTO_PARANOIDAT");
2576 memento.paranoidAt = (env ? atoi(env) : 0);
2577
2578 env = getenv("MEMENTO_SQUEEZEAT");
2579 memento.squeezeAt = (env ? atoi(env) : 0);
2580
2581 env = getenv("MEMENTO_PATTERN");
2582 memento.pattern = (env ? atoi(env) : 0);
2583
2584 env = getenv("MEMENTO_SHOW_DETAILED_BLOCKS");
2585 memento.showDetailedBlocks = (env ? atoi(env) : -1);
2586
2587 env = getenv("MEMENTO_HIDE_MULTIPLE_REALLOCS");
2588 memento.hideMultipleReallocs = (env ? atoi(env) : 0);
2589
2590 env = getenv("MEMENTO_HIDE_REF_CHANGE_BACKTRACES");
2591 memento.hideRefChangeBacktraces = (env ? atoi(env) : 0);
2592
2593 env = getenv("MEMENTO_ABORT_ON_LEAK");
2594 memento.abortOnLeak = (env ? atoi(env) : 0);
2595
2596 env = getenv("MEMENTO_ABORT_ON_CORRUPTION");
2597 memento.abortOnCorruption = (env ? atoi(env) : 0);
2598
2599 env = getenv("MEMENTO_SQUEEZES");
2600 if (env) {
2601 int e;
2602 fprintf(stderr, "Parsing squeeze ranges in MEMENTO_SQUEEZES=%s\n", env);
2603 e = Memento_add_squeezes(env);
2604 if (e) {
2605 fprintf(stderr, "Failed to parse MEMENTO_SQUEEZES=%s\n", env);
2606 exit(1);
2607 }
2608 }
2609
2610 env = getenv("MEMENTO_MAXMEMORY");
2611 memento.maxMemory = (env ? atoi(env) : 0);
2612
2613 env = getenv("MEMENTO_VERBOSE");
2614 memento.verbose = (env ? atoi(env) : 0);
2615
2616 env = getenv("MEMENTO_IGNORENEWDELETE");
2617 memento.ignoreNewDelete = (env ? atoi(env) : 0);
2618
2619 env = getenv("MEMENTO_ATEXIT_FIN");
2620 memento.atexitFin = (env ? atoi(env) : 1);
2621
2622 if (memento.atexitFin) {
2623 /* For Windows, we can _onexit rather than atexit. This is because
2624 * _onexit registered handlers are called when the DLL that they are
2625 * in is freed, rather than on complete closedown. This gives us a
2626 * higher chance of seeing Memento_fin called in a state when the
2627 * stack backtracing mechanism can still work. */
2628 #if defined(_WIN32) || defined(_WIN64)
2629 _onexit(Memento_fin_win);
2630 #else
2631 atexit(Memento_fin_unix);
2632 #endif
2633 }
2634
2635 Memento_initMutex(&memento.mutex);
2636
2637 Memento_initStacktracer();
2638
2639 Memento_breakpoint();
2640 }
2641
2642 static void Memento_infoLocked(void *addr)
2643 {
2644 #ifdef MEMENTO_DETAILS
2645 Memento_BlkHeader *blk;
2646
2647 blk = find_enclosing_block(&memento.used, addr, NULL);
2648 if (blk == NULL)
2649 blk = find_enclosing_block(&memento.free, addr, NULL);
2650 if (blk != NULL)
2651 showInfo(blk, NULL);
2652 #else
2653 printf("Memento not compiled with details support\n");
2654 #endif
2655 }
2656
2657 void Memento_info(void *addr)
2658 {
2659 MEMENTO_LOCK();
2660 Memento_infoLocked(addr);
2661 MEMENTO_UNLOCK();
2662 }
2663
2664 #ifdef MEMENTO_HAS_FORK
2665 #include <unistd.h>
2666 #include <sys/wait.h>
2667 #include <time.h>
2668 #ifdef MEMENTO_STACKTRACE_METHOD
2669 #if MEMENTO_STACKTRACE_METHOD == 1
2670 #include <signal.h>
2671 #endif
2672 #endif
2673
2674 /* FIXME: Find some portable way of getting this */
2675 /* MacOSX has 10240, Ubuntu seems to have 256 */
2676 #ifndef OPEN_MAX
2677 #define OPEN_MAX 10240
2678 #endif
2679
2680 /* stashed_map[j] = i means that file descriptor i-1 was duplicated to j */
2681 int stashed_map[OPEN_MAX];
2682
2683 static void Memento_signal(int sig)
2684 {
2685 (void)sig;
2686 fprintf(stderr, "SEGV at:\n");
2687 memento.segv = 1;
2688 Memento_bt_internal(0);
2689
2690 exit(1);
2691 }
2692
2693 static int squeeze(void)
2694 {
2695 pid_t pid;
2696 int i, status;
2697
2698 if (memento.patternBit < 0)
2699 return 1;
2700 if (memento.squeezing && memento.patternBit >= MEMENTO_MAXPATTERN)
2701 return 1;
2702
2703 if (memento.patternBit == 0)
2704 memento.squeezeAt = memento.sequence;
2705
2706 if (!memento.squeezing) {
2707 fprintf(stderr, "Memory squeezing @ %d\n", memento.squeezeAt);
2708 } else
2709 fprintf(stderr, "Memory squeezing @ %d (%x,%x)\n", memento.squeezeAt, memento.pattern, memento.patternBit);
2710
2711 /* When we fork below, the child is going to snaffle all our file pointers
2712 * and potentially corrupt them. Let's make copies of all of them before
2713 * we fork, so we can restore them when we restart. */
2714 for (i = 0; i < OPEN_MAX; i++) {
2715 if (stashed_map[i] == 0) {
2716 int j = dup(i);
2717 if (j >= 0) {
2718 stashed_map[j] = i+1;
2719 }
2720 }
2721 }
2722
2723 fprintf(stderr, "Failing at:\n");
2724 Memento_bt_internal(2);
2725 pid = fork();
2726 if (pid == 0) {
2727 /* Child */
2728 signal(SIGSEGV, Memento_signal);
2729 /* Close the dup-licated fds to avoid them getting corrupted by faulty
2730 * code. */
2731 for (i = 0; i < OPEN_MAX; i++) {
2732 if (stashed_map[i] != 0) {
2733 /* We close duplicated fds, just in case child has some bad
2734 * code that modifies/closes random fds. */
2735 close(i);
2736 }
2737 }
2738 /* In the child, we always fail the next allocation. */
2739 if (memento.patternBit == 0) {
2740 memento.patternBit = 1;
2741 } else
2742 memento.patternBit <<= 1;
2743 memento.squeezing = 1;
2744
2745 /* This is necessary to allow Memento_failThisEventLocked() near the
2746 * end to do 'return squeeze();'. */
2747 memento.squeezes_num = 0;
2748
2749 return 1;
2750 }
2751
2752 /* In the parent if we hit another allocation, pass it (and record the
2753 * fact we passed it in the pattern. */
2754 memento.pattern |= memento.patternBit;
2755 memento.patternBit <<= 1;
2756
2757 /* Wait for pid to finish, with a timeout. */
2758 {
2759 struct timespec tm = { 0, 10 * 1000 * 1000 }; /* 10ms = 100th sec */
2760 int timeout = 30 * 1000 * 1000; /* time out in microseconds! */
2761 while (waitpid(pid, &status, WNOHANG) == 0) {
2762 nanosleep(&tm, NULL);
2763 timeout -= (int)(tm.tv_nsec/1000);
2764 tm.tv_nsec *= 2;
2765 if (tm.tv_nsec > 999999999)
2766 tm.tv_nsec = 999999999;
2767 if (timeout <= 0) {
2768 char text[32];
2769 fprintf(stderr, "Child is taking a long time to die. Killing it.\n");
2770 sprintf(text, "kill %d", pid);
2771 system(text);
2772 break;
2773 }
2774 }
2775 }
2776
2777 if (status != 0) {
2778 fprintf(stderr, "Child status=%d\n", status);
2779 }
2780
2781 /* Put the files back */
2782 for (i = 0; i < OPEN_MAX; i++) {
2783 if (stashed_map[i] != 0) {
2784 dup2(i, stashed_map[i]-1);
2785 close(i);
2786 stashed_map[i] = 0;
2787 }
2788 }
2789
2790 return 0;
2791 }
2792 #else
2793 #include <signal.h>
2794
2795 static void Memento_signal(int sig)
2796 {
2797 (void)sig;
2798 memento.segv = 1;
2799 /* If we just return from this function the SEGV will be unhandled, and
2800 * we'll launch into whatever JIT debugging system the OS provides. At
2801 * least fprintf(stderr, something useful first. If MEMENTO_NOJIT is set, then
2802 * just exit to avoid the JIT (and get the usual atexit handling). */
2803 if (getenv("MEMENTO_NOJIT"))
2804 exit(1);
2805 else
2806 Memento_fin();
2807 }
2808
2809 static int squeeze(void)
2810 {
2811 fprintf(stderr, "Memento memory squeezing disabled as no fork!\n");
2812 return 0;
2813 }
2814 #endif
2815
2816 static void Memento_startFailing(void)
2817 {
2818 if (!memento.failing) {
2819 fprintf(stderr, "Starting to fail...\n");
2820 Memento_bt();
2821 fflush(stderr);
2822 memento.failing = 1;
2823 memento.failAt = memento.sequence;
2824 memento.nextFailAt = memento.sequence+1;
2825 memento.patternBit = 0;
2826 signal(SIGSEGV, Memento_signal);
2827 signal(SIGABRT, Memento_signal);
2828 Memento_breakpointLocked();
2829 }
2830 }
2831
2832 static int Memento_event(void)
2833 {
2834 int ret = 0;
2835
2836 memento.sequence++;
2837 if ((memento.sequence >= memento.paranoidAt) && (memento.paranoidAt != 0)) {
2838 memento.paranoia = 1;
2839 memento.countdown = 1;
2840 }
2841 if (--memento.countdown == 0) {
2842 ret = Memento_checkAllMemoryLocked();
2843 ret = (ret & 8) != 0;
2844 if (memento.paranoia > 0)
2845 memento.countdown = memento.paranoia;
2846 else
2847 {
2848 memento.countdown = -memento.paranoia;
2849 if (memento.paranoia > INT_MIN/2)
2850 memento.paranoia *= 2;
2851 }
2852 }
2853
2854 if (memento.sequence == memento.breakAt) {
2855 fprintf(stderr, "Breaking at event %d\n", memento.breakAt);
2856 return 1;
2857 }
2858 return ret;
2859 }
2860
2861 int Memento_sequence(void)
2862 {
2863 return memento.sequence;
2864 }
2865
2866 int Memento_breakAt(int event)
2867 {
2868 MEMENTO_LOCK();
2869 memento.breakAt = event;
2870 MEMENTO_UNLOCK();
2871 return event;
2872 }
2873
2874 static void *safe_find_block(void *ptr)
2875 {
2876 Memento_BlkHeader *block;
2877 int valid;
2878
2879 if (ptr == NULL)
2880 return NULL;
2881
2882 block = MEMBLK_FROMBLK(ptr);
2883 /* Sometimes wrapping allocators can mean Memento_label
2884 * is called with a value within the block, rather than
2885 * at the start of the block. If we detect this, find it
2886 * the slow way. */
2887 VALGRIND_MAKE_MEM_DEFINED(&block->child, sizeof(block->child));
2888 VALGRIND_MAKE_MEM_DEFINED(&block->sibling, sizeof(block->sibling));
2889 valid = (block->child == MEMENTO_CHILD_MAGIC &&
2890 block->sibling == MEMENTO_SIBLING_MAGIC);
2891 if (valid) {
2892 VALGRIND_MAKE_MEM_NOACCESS(&block->child, sizeof(block->child));
2893 VALGRIND_MAKE_MEM_NOACCESS(&block->sibling, sizeof(block->sibling));
2894 }
2895 if (!valid)
2896 {
2897 block = find_enclosing_block(&memento.used, ptr, NULL);
2898 }
2899 return block;
2900 }
2901
2902 void *Memento_label(void *ptr, const char *label)
2903 {
2904 Memento_BlkHeader *block;
2905
2906 if (ptr == NULL)
2907 return NULL;
2908 MEMENTO_LOCK();
2909 block = safe_find_block(ptr);
2910 if (block != NULL)
2911 {
2912 VALGRIND_MAKE_MEM_DEFINED(&block->label, sizeof(block->label));
2913 block->label = label;
2914 VALGRIND_MAKE_MEM_NOACCESS(&block->label, sizeof(block->label));
2915 }
2916 MEMENTO_UNLOCK();
2917
2918 if (memento.verboseNewlineSuppressed) {
2919 if (memento.lastVerbosePtr == block) {
2920 fprintf(stderr, " (%s)", label);
2921 }
2922 }
2923
2924 return ptr;
2925 }
2926
2927 void Memento_tick(void)
2928 {
2929 MEMENTO_LOCK();
2930 if (Memento_event()) Memento_breakpointLocked();
2931 MEMENTO_UNLOCK();
2932 }
2933
2934 static int Memento_failThisEventLocked(void)
2935 {
2936 int failThisOne;
2937
2938 if (Memento_event()) Memento_breakpointLocked();
2939
2940 if (!memento.squeezing && memento.squeezes_num) {
2941 /* Move to next relevant squeeze region if appropriate. */
2942 for ( ; memento.squeezes_pos != memento.squeezes_num; memento.squeezes_pos++) {
2943 if (memento.sequence < memento.squeezes[memento.squeezes_pos].end)
2944 break;
2945 }
2946
2947 /* See whether memento.sequence is within this squeeze region. */
2948 if (memento.squeezes_pos < memento.squeezes_num) {
2949 int begin = memento.squeezes[memento.squeezes_pos].begin;
2950 int end = memento.squeezes[memento.squeezes_pos].end;
2951 if (memento.sequence >= begin && memento.sequence < end) {
2952 if (1) {
2953 fprintf(stderr,
2954 "squeezes match memento.sequence=%i: memento.squeezes_pos=%i/%i %i..%i\n",
2955 memento.sequence,
2956 memento.squeezes_pos,
2957 memento.squeezes_num,
2958 memento.squeezes[memento.squeezes_pos].begin,
2959 memento.squeezes[memento.squeezes_pos].end
2960 );
2961 }
2962 return squeeze();
2963 }
2964 }
2965 }
2966
2967 if ((memento.sequence >= memento.failAt) && (memento.failAt != 0))
2968 Memento_startFailing();
2969 if ((memento.squeezes_num==0) && (memento.sequence >= memento.squeezeAt) && (memento.squeezeAt != 0))
2970 return squeeze();
2971
2972 if (!memento.failing)
2973 return 0;
2974 failThisOne = ((memento.patternBit & memento.pattern) == 0);
2975 /* If we are failing, and we've reached the end of the pattern and we've
2976 * still got bits available in the pattern word, and we haven't already
2977 * set a nextPattern, then extend the pattern. */
2978 if (memento.failing &&
2979 ((~(memento.patternBit-1) & memento.pattern) == 0) &&
2980 (memento.patternBit != 0) &&
2981 memento.nextPattern == 0)
2982 {
2983 /* We'll fail this one, and set the 'next' one to pass it. */
2984 memento.nextFailAt = memento.failAt;
2985 memento.nextPattern = memento.pattern | memento.patternBit;
2986 }
2987 memento.patternBit = (memento.patternBit ? memento.patternBit << 1 : 1);
2988
2989 return failThisOne;
2990 }
2991
2992 int Memento_failThisEvent(void)
2993 {
2994 int ret;
2995
2996 if (!memento.inited)
2997 Memento_init();
2998
2999 MEMENTO_LOCK();
3000 ret = Memento_failThisEventLocked();
3001 MEMENTO_UNLOCK();
3002 return ret;
3003 }
3004
3005 static void *do_malloc(size_t s, int et)
3006 {
3007 Memento_BlkHeader *memblk;
3008 size_t smem = MEMBLK_SIZE(s);
3009 #ifdef MEMENTO_DETAILS
3010 Memento_hashedST *st;
3011 #endif
3012
3013 if (Memento_failThisEventLocked()) {
3014 errno = ENOMEM;
3015 return NULL;
3016 }
3017
3018 if (s == 0)
3019 return NULL;
3020
3021 memento.numMallocs++;
3022
3023 if (memento.maxMemory != 0 && memento.alloc + s > memento.maxMemory) {
3024 errno = ENOMEM;
3025 return NULL;
3026 }
3027
3028 #ifdef MEMENTO_DETAILS
3029 st = Memento_getHashedStacktrace();
3030 #endif
3031
3032 memblk = MEMENTO_UNDERLYING_MALLOC(smem);
3033 if (memblk == NULL) {
3034 switch (memento.verbose) {
3035 default:
3036 if (memento.verboseNewlineSuppressed)
3037 fprintf(stderr, "\n");
3038 fprintf(stderr, "%s failed (size="FMTZ",num=%d",
3039 eventType[et], (FMTZ_CAST)s, memento.sequence);
3040 #ifdef MEMENTO_DETAILS
3041 fprintf(stderr, ",st=%x", st->hash);
3042 #endif
3043 fprintf(stderr, ")");
3044 memento.verboseNewlineSuppressed = 1;
3045 memento.lastVerbosePtr = memblk;
3046 break;
3047 case 2:
3048 if (memento.verboseNewlineSuppressed)
3049 fprintf(stderr, "\n");
3050 fprintf(stderr, "%s failed (size="FMTZ"",
3051 eventType[et], (FMTZ_CAST)s);
3052 #ifdef MEMENTO_DETAILS
3053 fprintf(stderr, ",st=%x", st->hash);
3054 #endif
3055 fprintf(stderr, ")");
3056 memento.verboseNewlineSuppressed = 1;
3057 memento.lastVerbosePtr = memblk;
3058 break;
3059 case 0:
3060 break;
3061 }
3062 return NULL;
3063 }
3064
3065 memento.alloc += s;
3066 memento.totalAlloc += s;
3067 if (memento.peakAlloc < memento.alloc)
3068 memento.peakAlloc = memento.alloc;
3069 #ifndef MEMENTO_LEAKONLY
3070 memset(MEMBLK_TOBLK(memblk), MEMENTO_ALLOCFILL, s);
3071 #endif
3072 memblk->rawsize = s;
3073 memblk->sequence = memento.sequence;
3074 memblk->lastCheckedOK = memblk->sequence;
3075 memblk->flags = 0;
3076 memblk->label = 0;
3077 memblk->child = MEMENTO_CHILD_MAGIC;
3078 memblk->sibling = MEMENTO_SIBLING_MAGIC;
3079 #ifdef MEMENTO_DETAILS
3080 memblk->details = NULL;
3081 memblk->details_tail = &memblk->details;
3082 Memento_storeDetails(memblk, et, st);
3083 #endif /* MEMENTO_DETAILS */
3084 Memento_addBlockHead(&memento.used, memblk, 0);
3085
3086 if (memento.leaking > 0)
3087 memblk->flags |= Memento_Flag_KnownLeak;
3088
3089 switch (memento.verbose) {
3090 default:
3091 if (memento.verboseNewlineSuppressed)
3092 fprintf(stderr, "\n");
3093 fprintf(stderr, "%s "FMTP":(size="FMTZ",num=%d",
3094 eventType[et],
3095 MEMBLK_TOBLK(memblk), (FMTZ_CAST)memblk->rawsize, memblk->sequence);
3096 #ifdef MEMENTO_DETAILS
3097 fprintf(stderr, ",st=%x", st->hash);
3098 #endif
3099 if (memblk->label)
3100 fprintf(stderr, ") (%s", memblk->label);
3101 fprintf(stderr, ")");
3102 memento.verboseNewlineSuppressed = 1;
3103 memento.lastVerbosePtr = memblk;
3104 break;
3105 case 2:
3106 if (memento.verboseNewlineSuppressed)
3107 fprintf(stderr, "\n");
3108 fprintf(stderr, "%s (size="FMTZ"",
3109 eventType[et],
3110 (FMTZ_CAST)memblk->rawsize);
3111 #ifdef MEMENTO_DETAILS
3112 fprintf(stderr, ",st=%x", st->hash);
3113 #endif
3114 if (memblk->label)
3115 fprintf(stderr, ") (%s", memblk->label);
3116 fprintf(stderr, ")");
3117 memento.verboseNewlineSuppressed = 1;
3118 memento.lastVerbosePtr = memblk;
3119 break;
3120 case 0:
3121 break;
3122 }
3123
3124 return MEMBLK_TOBLK(memblk);
3125 }
3126
3127 char *Memento_strdup(const char *text)
3128 {
3129 size_t len = strlen(text) + 1;
3130 char *ret;
3131
3132 if (!memento.inited)
3133 Memento_init();
3134
3135 MEMENTO_LOCK();
3136 ret = do_malloc(len, Memento_EventType_strdup);
3137 MEMENTO_UNLOCK();
3138
3139 if (ret != NULL)
3140 memcpy(ret, text, len);
3141
3142 return ret;
3143 }
3144
3145 #if !defined(MEMENTO_GS_HACKS) && !defined(MEMENTO_MUPDF_HACKS)
3146 int Memento_asprintf(char **ret, const char *format, ...)
3147 {
3148 va_list va;
3149 int n;
3150 int n2;
3151
3152 if (!memento.inited)
3153 Memento_init();
3154
3155 va_start(va, format);
3156 n = vsnprintf(NULL, 0, format, va);
3157 va_end(va);
3158 if (n < 0)
3159 return n;
3160
3161 MEMENTO_LOCK();
3162 *ret = do_malloc(n+1, Memento_EventType_asprintf);
3163 MEMENTO_UNLOCK();
3164 if (*ret == NULL)
3165 return -1;
3166
3167 va_start(va, format);
3168 n2 = vsnprintf(*ret, n + 1, format, va);
3169 va_end(va);
3170
3171 return n2;
3172 }
3173
3174 int Memento_vasprintf(char **ret, const char *format, va_list ap)
3175 {
3176 int n;
3177 va_list ap2;
3178 va_copy(ap2, ap);
3179
3180 if (!memento.inited)
3181 Memento_init();
3182
3183 n = vsnprintf(NULL, 0, format, ap);
3184 if (n < 0) {
3185 va_end(ap2);
3186 return n;
3187 }
3188
3189 MEMENTO_LOCK();
3190 *ret = do_malloc(n+1, Memento_EventType_vasprintf);
3191 MEMENTO_UNLOCK();
3192 if (*ret == NULL) {
3193 va_end(ap2);
3194 return -1;
3195 }
3196
3197 n = vsnprintf(*ret, n + 1, format, ap2);
3198 va_end(ap2);
3199
3200 return n;
3201 }
3202 #endif
3203
3204 void *Memento_malloc(size_t s)
3205 {
3206 void *ret;
3207
3208 if (!memento.inited)
3209 Memento_init();
3210
3211 MEMENTO_LOCK();
3212 ret = do_malloc(s, Memento_EventType_malloc);
3213 MEMENTO_UNLOCK();
3214
3215 return ret;
3216 }
3217
3218 void *Memento_calloc(size_t n, size_t s)
3219 {
3220 void *block;
3221
3222 if (!memento.inited)
3223 Memento_init();
3224
3225 MEMENTO_LOCK();
3226 block = do_malloc(n*s, Memento_EventType_calloc);
3227 MEMENTO_UNLOCK();
3228 if (block)
3229 memset(block, 0, n*s);
3230
3231 return block;
3232 }
3233
3234 #ifdef MEMENTO_TRACKREFS
3235 static void do_reference(Memento_BlkHeader *blk, int event)
3236 {
3237 #ifdef MEMENTO_DETAILS
3238 Memento_hashedST *st = Memento_getHashedStacktrace();
3239 Memento_storeDetails(blk, event, st);
3240 #endif /* MEMENTO_DETAILS */
3241 }
3242 #endif
3243
3244 static int checkPointerOrNullLocked(void *blk)
3245 {
3246 if (blk == NULL)
3247 return 0;
3248 if (blk == MEMENTO_PREFILL_PTR)
3249 fprintf(stderr, "Prefill value found as pointer - buffer underrun?\n");
3250 else if (blk == MEMENTO_POSTFILL_PTR)
3251 fprintf(stderr, "Postfill value found as pointer - buffer overrun?\n");
3252 else if (blk == MEMENTO_ALLOCFILL_PTR)
3253 fprintf(stderr, "Allocfill value found as pointer - use of uninitialised value?\n");
3254 else if (blk == MEMENTO_FREEFILL_PTR)
3255 fprintf(stderr, "Allocfill value found as pointer - use after free?\n");
3256 else
3257 return 0;
3258 #ifdef MEMENTO_DETAILS
3259 fprintf(stderr, "Current backtrace:\n");
3260 Memento_bt();
3261 fprintf(stderr, "History:\n");
3262 Memento_infoLocked(blk);
3263 #endif
3264 Memento_breakpointLocked();
3265 return 1;
3266 }
3267
3268 int Memento_checkPointerOrNull(void *blk)
3269 {
3270 int ret;
3271 MEMENTO_LOCK();
3272 ret = checkPointerOrNullLocked(blk);
3273 MEMENTO_UNLOCK();
3274 return ret;
3275 }
3276
3277 static int checkBytePointerOrNullLocked(void *blk)
3278 {
3279 unsigned char i;
3280 if (blk == NULL)
3281 return 0;
3282 checkPointerOrNullLocked(blk);
3283
3284 i = *(unsigned char *)blk;
3285
3286 if (i == MEMENTO_PREFILL_UBYTE)
3287 fprintf(stderr, "Prefill value found - buffer underrun?\n");
3288 else if (i == MEMENTO_POSTFILL_UBYTE)
3289 fprintf(stderr, "Postfill value found - buffer overrun?\n");
3290 else if (i == MEMENTO_ALLOCFILL_UBYTE)
3291 fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
3292 else if (i == MEMENTO_FREEFILL_UBYTE)
3293 fprintf(stderr, "Allocfill value found - use after free?\n");
3294 else
3295 return 0;
3296 #ifdef MEMENTO_DETAILS
3297 fprintf(stderr, "Current backtrace:\n");
3298 Memento_bt();
3299 fprintf(stderr, "History:\n");
3300 Memento_infoLocked(blk);
3301 #endif
3302 Memento_breakpointLocked();
3303 return 1;
3304 }
3305
3306 int Memento_checkBytePointerOrNull(void *blk)
3307 {
3308 int ret;
3309 MEMENTO_LOCK();
3310 ret = checkBytePointerOrNullLocked(blk);
3311 MEMENTO_UNLOCK();
3312 return ret;
3313 }
3314
3315 static int checkShortPointerOrNullLocked(void *blk)
3316 {
3317 unsigned short i;
3318 if (blk == NULL)
3319 return 0;
3320 checkPointerOrNullLocked(blk);
3321
3322 i = *(unsigned short *)blk;
3323
3324 if (i == MEMENTO_PREFILL_USHORT)
3325 fprintf(stderr, "Prefill value found - buffer underrun?\n");
3326 else if (i == MEMENTO_POSTFILL_USHORT)
3327 fprintf(stderr, "Postfill value found - buffer overrun?\n");
3328 else if (i == MEMENTO_ALLOCFILL_USHORT)
3329 fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
3330 else if (i == MEMENTO_FREEFILL_USHORT)
3331 fprintf(stderr, "Allocfill value found - use after free?\n");
3332 else
3333 return 0;
3334 #ifdef MEMENTO_DETAILS
3335 fprintf(stderr, "Current backtrace:\n");
3336 Memento_bt();
3337 fprintf(stderr, "History:\n");
3338 Memento_infoLocked(blk);
3339 #endif
3340 Memento_breakpointLocked();
3341 return 1;
3342 }
3343
3344 int Memento_checkShortPointerOrNull(void *blk)
3345 {
3346 int ret;
3347 MEMENTO_LOCK();
3348 ret = checkShortPointerOrNullLocked(blk);
3349 MEMENTO_UNLOCK();
3350 return ret;
3351 }
3352
3353 static int checkIntPointerOrNullLocked(void *blk)
3354 {
3355 unsigned int i;
3356 if (blk == NULL)
3357 return 0;
3358 checkPointerOrNullLocked(blk);
3359
3360 i = *(unsigned int *)blk;
3361
3362 if (i == MEMENTO_PREFILL_UINT)
3363 fprintf(stderr, "Prefill value found - buffer underrun?\n");
3364 else if (i == MEMENTO_POSTFILL_UINT)
3365 fprintf(stderr, "Postfill value found - buffer overrun?\n");
3366 else if (i == MEMENTO_ALLOCFILL_UINT)
3367 fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
3368 else if (i == MEMENTO_FREEFILL_UINT)
3369 fprintf(stderr, "Allocfill value found - use after free?\n");
3370 else
3371 return 0;
3372 #ifdef MEMENTO_DETAILS
3373 fprintf(stderr, "Current backtrace:\n");
3374 Memento_bt();
3375 fprintf(stderr, "History:\n");
3376 Memento_infoLocked(blk);
3377 #endif
3378 Memento_breakpointLocked();
3379 return 1;
3380 }
3381
3382 int Memento_checkIntPointerOrNull(void *blk)
3383 {
3384 int ret;
3385 MEMENTO_LOCK();
3386 ret = checkIntPointerOrNullLocked(blk);
3387 MEMENTO_UNLOCK();
3388 return ret;
3389 }
3390
3391 #ifdef MEMENTO_TRACKREFS
3392 static void *do_takeRef(void *blk)
3393 {
3394 do_reference(safe_find_block(blk), Memento_EventType_takeRef);
3395 return blk;
3396 }
3397
3398 static void *do_takeRefAndUnlock(void *blk)
3399 {
3400 do_reference(safe_find_block(blk), Memento_EventType_takeRef);
3401 MEMENTO_UNLOCK();
3402 return blk;
3403 }
3404
3405 static void *do_dropRef(void *blk)
3406 {
3407 do_reference(safe_find_block(blk), Memento_EventType_dropRef);
3408 return blk;
3409 }
3410
3411 static void *do_dropRefAndUnlock(void *blk)
3412 {
3413 do_reference(safe_find_block(blk), Memento_EventType_dropRef);
3414 MEMENTO_UNLOCK();
3415 return blk;
3416 }
3417 #endif
3418
3419 void *Memento_takeByteRef(void *blk)
3420 {
3421 #ifdef MEMENTO_TRACKREFS
3422 if (!memento.inited)
3423 Memento_init();
3424
3425 MEMENTO_LOCK();
3426 if (Memento_event()) Memento_breakpointLocked();
3427
3428 if (!blk) {
3429 MEMENTO_UNLOCK();
3430 return NULL;
3431 }
3432
3433 (void)checkBytePointerOrNullLocked(blk);
3434
3435 return do_takeRefAndUnlock(blk);
3436 #else
3437 return blk;
3438 #endif
3439 }
3440
3441 void *Memento_takeShortRef(void *blk)
3442 {
3443 #ifdef MEMENTO_TRACKREFS
3444 if (!memento.inited)
3445 Memento_init();
3446
3447 MEMENTO_LOCK();
3448 if (Memento_event()) Memento_breakpointLocked();
3449
3450 if (!blk) {
3451 MEMENTO_UNLOCK();
3452 return NULL;
3453 }
3454
3455 (void)checkShortPointerOrNullLocked(blk);
3456
3457 return do_takeRefAndUnlock(blk);
3458 #else
3459 return blk;
3460 #endif
3461 }
3462
3463 void *Memento_takeIntRef(void *blk)
3464 {
3465 #ifdef MEMENTO_TRACKREFS
3466 if (!memento.inited)
3467 Memento_init();
3468
3469 MEMENTO_LOCK();
3470 if (Memento_event()) Memento_breakpointLocked();
3471
3472 if (!blk) {
3473 MEMENTO_UNLOCK();
3474 return NULL;
3475 }
3476
3477 (void)checkIntPointerOrNullLocked(blk);
3478
3479 return do_takeRefAndUnlock(blk);
3480 #else
3481 return blk;
3482 #endif
3483 }
3484
3485 void *Memento_takeRef(void *blk)
3486 {
3487 #ifdef MEMENTO_TRACKREFS
3488 if (!memento.inited)
3489 Memento_init();
3490
3491 MEMENTO_LOCK();
3492 if (Memento_event()) Memento_breakpointLocked();
3493
3494 if (!blk) {
3495 MEMENTO_UNLOCK();
3496 return NULL;
3497 }
3498
3499 return do_takeRefAndUnlock(blk);
3500 #else
3501 return blk;
3502 #endif
3503 }
3504
3505 void *Memento_dropByteRef(void *blk)
3506 {
3507 #ifdef MEMENTO_TRACKREFS
3508 if (!memento.inited)
3509 Memento_init();
3510
3511 MEMENTO_LOCK();
3512 if (Memento_event()) Memento_breakpointLocked();
3513
3514 if (!blk) {
3515 MEMENTO_UNLOCK();
3516 return NULL;
3517 }
3518
3519 checkBytePointerOrNullLocked(blk);
3520
3521 return do_dropRefAndUnlock(blk);
3522 #else
3523 return blk;
3524 #endif
3525 }
3526
3527 void *Memento_dropShortRef(void *blk)
3528 {
3529 #ifdef MEMENTO_TRACKREFS
3530 if (!memento.inited)
3531 Memento_init();
3532
3533 MEMENTO_LOCK();
3534 if (Memento_event()) Memento_breakpointLocked();
3535
3536 if (!blk) {
3537 MEMENTO_UNLOCK();
3538 return NULL;
3539 }
3540
3541 checkShortPointerOrNullLocked(blk);
3542
3543 return do_dropRefAndUnlock(blk);
3544 #else
3545 return blk;
3546 #endif
3547 }
3548
3549 void *Memento_dropIntRef(void *blk)
3550 {
3551 #ifdef MEMENTO_TRACKREFS
3552 if (!memento.inited)
3553 Memento_init();
3554
3555 MEMENTO_LOCK();
3556 if (Memento_event()) Memento_breakpointLocked();
3557
3558 if (!blk) {
3559 MEMENTO_UNLOCK();
3560 return NULL;
3561 }
3562
3563 checkIntPointerOrNullLocked(blk);
3564
3565 return do_dropRefAndUnlock(blk);
3566 #else
3567 return blk;
3568 #endif
3569 }
3570
3571 void *Memento_dropRef(void *blk)
3572 {
3573 #ifdef MEMENTO_TRACKREFS
3574 if (!memento.inited)
3575 Memento_init();
3576
3577 MEMENTO_LOCK();
3578 if (Memento_event()) Memento_breakpointLocked();
3579
3580 if (!blk) {
3581 MEMENTO_UNLOCK();
3582 return NULL;
3583 }
3584
3585 return do_dropRefAndUnlock(blk);
3586 #else
3587 return blk;
3588 #endif
3589 }
3590
3591 void *Memento_adjustRef(void *blk, int adjust)
3592 {
3593 #ifdef MEMENTO_TRACKREFS
3594 if (!memento.inited)
3595 Memento_init();
3596
3597 MEMENTO_LOCK();
3598 if (Memento_event()) Memento_breakpointLocked();
3599
3600 if (blk == NULL) {
3601 MEMENTO_UNLOCK();
3602 return NULL;
3603 }
3604
3605 while (adjust > 0)
3606 {
3607 do_takeRef(blk);
3608 adjust--;
3609 }
3610 while (adjust < 0)
3611 {
3612 do_dropRef(blk);
3613 adjust++;
3614 }
3615
3616 MEMENTO_UNLOCK();
3617 #endif
3618 return blk;
3619 }
3620
3621 void *Memento_reference(void *blk)
3622 {
3623 #ifdef MEMENTO_TRACKREFS
3624 if (!blk)
3625 return NULL;
3626
3627 if (!memento.inited)
3628 Memento_init();
3629
3630 MEMENTO_LOCK();
3631 do_reference(safe_find_block(blk), Memento_EventType_reference);
3632 MEMENTO_UNLOCK();
3633 #endif
3634 return blk;
3635 }
3636
3637 /* Treat blocks from the user with suspicion, and check them the slow
3638 * but safe way. */
3639 static int checkBlockUser(Memento_BlkHeader *memblk, const char *action)
3640 {
3641 #ifndef MEMENTO_LEAKONLY
3642 BlkCheckData data;
3643
3644 memset(&data, 0, sizeof(data));
3645 Memento_appBlockUser(&memento.used, Memento_Internal_checkAllocedBlock,
3646 &data, memblk);
3647 if (!data.found) {
3648 /* Failure! */
3649 fprintf(stderr, "Attempt to %s block ", action);
3650 showBlock(memblk, 32);
3651 fprintf(stderr, "\n");
3652 Memento_breakpointLocked();
3653 return 1;
3654 } else if (data.preCorrupt || data.postCorrupt) {
3655 fprintf(stderr, "Block ");
3656 showBlock(memblk, ' ');
3657 fprintf(stderr, " found to be corrupted on %s!\n", action);
3658 if (data.preCorrupt) {
3659 fprintf(stderr, "Preguard corrupted\n");
3660 }
3661 if (data.postCorrupt) {
3662 fprintf(stderr, "Postguard corrupted\n");
3663 }
3664 fprintf(stderr, "Block last checked OK at allocation %d. Now %d.\n",
3665 memblk->lastCheckedOK, memento.sequence);
3666 if ((memblk->flags & Memento_Flag_Reported) == 0)
3667 {
3668 memblk->flags |= Memento_Flag_Reported;
3669 Memento_breakpointLocked();
3670 }
3671 return 1;
3672 }
3673 #endif
3674 return 0;
3675 }
3676
3677 static int checkBlock(Memento_BlkHeader *memblk, const char *action)
3678 {
3679 #ifndef MEMENTO_LEAKONLY
3680 BlkCheckData data;
3681 #endif
3682
3683 if (memblk->child != MEMENTO_CHILD_MAGIC ||
3684 memblk->sibling != MEMENTO_SIBLING_MAGIC)
3685 {
3686 /* Failure! */
3687 fprintf(stderr, "Attempt to %s invalid block ", action);
3688 showBlock(memblk, 32);
3689 fprintf(stderr, "\n");
3690 return 2;
3691 }
3692
3693 #ifndef MEMENTO_LEAKONLY
3694 memset(&data, 0, sizeof(data));
3695 Memento_appBlock(&memento.used, Memento_Internal_checkAllocedBlock,
3696 &data, memblk);
3697 if (!data.found) {
3698 /* Failure! */
3699 fprintf(stderr, "Attempt to %s block ", action);
3700 showBlock(memblk, 32);
3701 fprintf(stderr, "\n");
3702 return 2;
3703 } else if (data.preCorrupt || data.postCorrupt) {
3704 fprintf(stderr, "Block ");
3705 showBlock(memblk, ' ');
3706 fprintf(stderr, " found to be corrupted on %s!\n", action);
3707 if (data.preCorrupt) {
3708 fprintf(stderr, "Preguard corrupted\n");
3709 }
3710 if (data.postCorrupt) {
3711 fprintf(stderr, "Postguard corrupted\n");
3712 }
3713 fprintf(stderr, "Block last checked OK at allocation %d. Now %d.\n",
3714 memblk->lastCheckedOK, memento.sequence);
3715 if ((memblk->flags & Memento_Flag_Reported) == 0)
3716 {
3717 memblk->flags |= Memento_Flag_Reported;
3718 return 2;
3719 }
3720 return 1;
3721 }
3722 #endif
3723 return 0;
3724 }
3725
3726 static void do_free(void *blk, int et)
3727 {
3728 Memento_BlkHeader *memblk;
3729 int ret;
3730 #ifdef MEMENTO_DETAILS
3731 Memento_hashedST *st;
3732 #endif
3733
3734 if (Memento_event()) Memento_breakpointLocked();
3735
3736 if (blk == NULL)
3737 return;
3738
3739 memblk = MEMBLK_FROMBLK(blk);
3740 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3741 ret = checkBlock(memblk, "free");
3742 if (ret)
3743 {
3744 if (ret & 2)
3745 Memento_breakpoint();
3746 if (memento.abortOnCorruption) {
3747 fprintf(stderr, "*** memblk corrupted, calling abort()\n");
3748 abort();
3749 }
3750 return;
3751 }
3752
3753 #ifdef MEMENTO_DETAILS
3754 st = Memento_getHashedStacktrace();
3755 #endif
3756
3757 switch (memento.verbose) {
3758 default:
3759 if (memento.verboseNewlineSuppressed) {
3760 fprintf(stderr, "\n");
3761 memento.verboseNewlineSuppressed = 0;
3762 }
3763 fprintf(stderr, "%s "FMTP":(size="FMTZ",num=%d",
3764 eventType[et],
3765 MEMBLK_TOBLK(memblk), (FMTZ_CAST)memblk->rawsize, memblk->sequence);
3766 #ifdef MEMENTO_DETAILS
3767 fprintf(stderr, ",hash=%x", st->hash);
3768 #endif
3769 if (memblk->label)
3770 fprintf(stderr, ") (%s", memblk->label);
3771 fprintf(stderr, ")\n");
3772 break;
3773 case 2:
3774 if (memento.verboseNewlineSuppressed) {
3775 fprintf(stderr, "\n");
3776 memento.verboseNewlineSuppressed = 0;
3777 }
3778 fprintf(stderr, "%s (size="FMTZ,
3779 eventType[et],
3780 (FMTZ_CAST)memblk->rawsize);
3781 #ifdef MEMENTO_DETAILS
3782 fprintf(stderr, ",hash=%x", st->hash);
3783 #endif
3784 if (memblk->label)
3785 fprintf(stderr, ") (%s", memblk->label);
3786 fprintf(stderr, ")\n");
3787 break;
3788 case 0:
3789 break;
3790 }
3791
3792 #ifdef MEMENTO_DETAILS
3793 Memento_storeDetails(memblk, et, st);
3794 #endif
3795
3796 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3797 if (memblk->flags & Memento_Flag_BreakOnFree)
3798 Memento_breakpointLocked();
3799
3800 memento.alloc -= memblk->rawsize;
3801 memento.numFrees++;
3802
3803 Memento_removeBlock(&memento.used, memblk);
3804
3805 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3806 if (Memento_Internal_makeSpace(MEMBLK_SIZE(memblk->rawsize))) {
3807 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3808 VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(memblk),
3809 memblk->rawsize + Memento_PostSize);
3810 #ifndef MEMENTO_LEAKONLY
3811 memset(MEMBLK_TOBLK(memblk), MEMENTO_FREEFILL, memblk->rawsize);
3812 #endif
3813 memblk->flags |= Memento_Flag_Freed;
3814 Memento_addBlockTail(&memento.free, memblk, 1);
3815 } else {
3816 free_block(memblk);
3817 }
3818 }
3819
3820 void Memento_free(void *blk)
3821 {
3822 if (!memento.inited)
3823 Memento_init();
3824
3825 MEMENTO_LOCK();
3826 do_free(blk, Memento_EventType_free);
3827 MEMENTO_UNLOCK();
3828 }
3829
3830 static void *do_realloc(void *blk, size_t newsize, int type)
3831 {
3832 Memento_BlkHeader *memblk, *newmemblk;
3833 size_t newsizemem;
3834 int flags, ret;
3835 size_t oldsize;
3836 #ifdef MEMENTO_DETAILS
3837 Memento_hashedST *st;
3838 #endif
3839 char oldptrstr[100];
3840
3841
3842 if (Memento_failThisEventLocked()) {
3843 errno = ENOMEM;
3844 return NULL;
3845 }
3846
3847 #ifdef MEMENTO_DETAILS
3848 st = Memento_getHashedStacktrace();
3849 #endif
3850
3851 memblk = MEMBLK_FROMBLK(blk);
3852 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3853 ret = checkBlock(memblk, "realloc");
3854 if (ret) {
3855 switch (memento.verbose) {
3856 default:
3857 if (memento.verboseNewlineSuppressed) {
3858 fprintf(stderr, "\n");
3859 memento.verboseNewlineSuppressed = 0;
3860 }
3861 fprintf(stderr, "%s bad block "FMTP":(size=?=>"FMTZ", num=?, now=%d",
3862 eventType[type],
3863 MEMBLK_TOBLK(memblk),
3864 (FMTZ_CAST)newsize, memento.sequence);
3865 #ifdef MEMENTO_DETAILS
3866 fprintf(stderr, ",hash=%x", st->hash);
3867 #endif
3868 fprintf(stderr, ")\n");
3869 break;
3870 case 2:
3871 if (memento.verboseNewlineSuppressed) {
3872 fprintf(stderr, "\n");
3873 memento.verboseNewlineSuppressed = 0;
3874 }
3875 fprintf(stderr, "%s bad block (size=?=>"FMTZ,
3876 eventType[type],
3877 (FMTZ_CAST)newsize);
3878 #ifdef MEMENTO_DETAILS
3879 fprintf(stderr, ",hash=%x", st->hash);
3880 #endif
3881 fprintf(stderr, ")\n");
3882 break;
3883 case 0:
3884 break;
3885 }
3886 if (ret == 2)
3887 Memento_breakpoint();
3888 errno = ENOMEM;
3889 return NULL;
3890 }
3891
3892 #ifdef MEMENTO_DETAILS
3893 Memento_storeDetails(memblk, type, st);
3894 #endif
3895
3896 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3897 if (memblk->flags & Memento_Flag_BreakOnRealloc)
3898 Memento_breakpointLocked();
3899
3900 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3901 oldsize = memblk->rawsize;
3902 if (memento.maxMemory != 0 && memento.alloc - oldsize + newsize > memento.maxMemory) {
3903 switch (memento.verbose) {
3904 default:
3905 if (memento.verboseNewlineSuppressed) {
3906 fprintf(stderr, "\n");
3907 memento.verboseNewlineSuppressed = 0;
3908 }
3909 fprintf(stderr, "%s failing (memory limit exceeded) "FMTP":(size="FMTZ"=>"FMTZ", num=%d, now=%d",
3910 eventType[type], MEMBLK_TOBLK(memblk),
3911 (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize,
3912 memblk->sequence, memento.sequence);
3913 #ifdef MEMENTO_DETAILS
3914 fprintf(stderr, ",hash=%x", st->hash);
3915 #endif
3916 if (memblk->label)
3917 fprintf(stderr, ") (%s", memblk->label);
3918 fprintf(stderr, ")\n");
3919 break;
3920 case 2:
3921 if (memento.verboseNewlineSuppressed) {
3922 fprintf(stderr, "\n");
3923 memento.verboseNewlineSuppressed = 0;
3924 }
3925 fprintf(stderr, "%s failing (memory limit exceeded) (size="FMTZ"=>"FMTZ,
3926 eventType[type], (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize);
3927 #ifdef MEMENTO_DETAILS
3928 fprintf(stderr, ",hash=%x", st->hash);
3929 #endif
3930 if (memblk->label)
3931 fprintf(stderr, ") (%s", memblk->label);
3932 fprintf(stderr, ")\n");
3933 break;
3934 case 0:
3935 break;
3936 }
3937 errno = ENOMEM;
3938 return NULL;
3939 }
3940
3941 newsizemem = MEMBLK_SIZE(newsize);
3942 Memento_removeBlock(&memento.used, memblk);
3943 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
3944 flags = memblk->flags;
3945 snprintf(oldptrstr, sizeof(oldptrstr), FMTP, MEMBLK_TOBLK(memblk));
3946 newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem);
3947 if (newmemblk == NULL)
3948 {
3949 switch (memento.verbose) {
3950 default:
3951 if (memento.verboseNewlineSuppressed) {
3952 fprintf(stderr, "\n");
3953 memento.verboseNewlineSuppressed = 0;
3954 }
3955 fprintf(stderr, "%s failed "FMTP":(size="FMTZ"=>"FMTZ", num=%d, now=%d",
3956 eventType[type], MEMBLK_TOBLK(memblk),
3957 (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize,
3958 memblk->sequence, memento.sequence);
3959 #ifdef MEMENTO_DETAILS
3960 fprintf(stderr, ",hash=%x", st->hash);
3961 #endif
3962 if (memblk->label)
3963 fprintf(stderr, ") (%s", newmemblk->label);
3964 fprintf(stderr, ")\n");
3965 break;
3966 case 2:
3967 if (memento.verboseNewlineSuppressed) {
3968 fprintf(stderr, "\n");
3969 memento.verboseNewlineSuppressed = 0;
3970 }
3971 fprintf(stderr, "%s failed (size="FMTZ"=>"FMTZ,
3972 eventType[type],
3973 (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize);
3974 #ifdef MEMENTO_DETAILS
3975 fprintf(stderr, ",hash=%x", st->hash);
3976 #endif
3977 if (memblk->label)
3978 fprintf(stderr, ") (%s", newmemblk->label);
3979 fprintf(stderr, ")\n");
3980 break;
3981 case 0:
3982 break;
3983 }
3984 Memento_addBlockHead(&memento.used, memblk, 2);
3985 return NULL;
3986 }
3987 memento.numReallocs++;
3988 memento.totalAlloc += newsize;
3989 memento.alloc -= newmemblk->rawsize;
3990 memento.alloc += newsize;
3991 if (memento.peakAlloc < memento.alloc)
3992 memento.peakAlloc = memento.alloc;
3993 newmemblk->flags = flags;
3994 #ifndef MEMENTO_LEAKONLY
3995 if (newmemblk->rawsize < newsize) {
3996 char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize;
3997 VALGRIND_MAKE_MEM_DEFINED(newbytes, newsize - newmemblk->rawsize);
3998 memset(newbytes, MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize);
3999 VALGRIND_MAKE_MEM_UNDEFINED(newbytes, newsize - newmemblk->rawsize);
4000 }
4001 #endif
4002 newmemblk->rawsize = newsize;
4003 #ifndef MEMENTO_LEAKONLY
4004 VALGRIND_MAKE_MEM_DEFINED(newmemblk->preblk, Memento_PreSize);
4005 memset(newmemblk->preblk, MEMENTO_PREFILL, Memento_PreSize);
4006 VALGRIND_MAKE_MEM_UNDEFINED(newmemblk->preblk, Memento_PreSize);
4007 VALGRIND_MAKE_MEM_DEFINED(MEMBLK_POSTPTR(newmemblk), Memento_PostSize);
4008 memset(MEMBLK_POSTPTR(newmemblk), MEMENTO_POSTFILL, Memento_PostSize);
4009 VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_POSTPTR(newmemblk), Memento_PostSize);
4010 #endif
4011
4012 switch (memento.verbose) {
4013 default:
4014 if (memento.verboseNewlineSuppressed) {
4015 fprintf(stderr, "\n");
4016 memento.verboseNewlineSuppressed = 0;
4017 }
4018 fprintf(stderr, "%s %s=>"FMTP":(size="FMTZ"=>"FMTZ", num=%d, now=%d",
4019 eventType[type],
4020 oldptrstr, MEMBLK_TOBLK(newmemblk),
4021 (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize,
4022 newmemblk->sequence, memento.sequence);
4023 #ifdef MEMENTO_DETAILS
4024 fprintf(stderr, ",hash=%x", st->hash);
4025 #endif
4026 if (newmemblk->label)
4027 fprintf(stderr, ") (%s", newmemblk->label);
4028 fprintf(stderr, ")\n");
4029 break;
4030 case 2:
4031 if (memento.verboseNewlineSuppressed) {
4032 fprintf(stderr, "\n");
4033 memento.verboseNewlineSuppressed = 0;
4034 }
4035 fprintf(stderr, "%s (size="FMTZ"=>"FMTZ,
4036 eventType[type],
4037 (FMTZ_CAST)oldsize, (FMTZ_CAST)newsize);
4038 #ifdef MEMENTO_DETAILS
4039 fprintf(stderr, ",hash=%x", st->hash);
4040 #endif
4041 if (newmemblk->label)
4042 fprintf(stderr, ") (%s", newmemblk->label);
4043 fprintf(stderr, ")\n");
4044 break;
4045 case 0:
4046 break;
4047 }
4048
4049 Memento_addBlockHead(&memento.used, newmemblk, 2);
4050 return MEMBLK_TOBLK(newmemblk);
4051 }
4052
4053 void *Memento_realloc(void *blk, size_t newsize)
4054 {
4055 void *ret;
4056
4057 if (!memento.inited)
4058 Memento_init();
4059
4060 if (blk == NULL)
4061 {
4062 MEMENTO_LOCK();
4063 ret = do_malloc(newsize, Memento_EventType_realloc);
4064 MEMENTO_UNLOCK();
4065 if (!ret) errno = ENOMEM;
4066 return ret;
4067 }
4068 if (newsize == 0) {
4069 MEMENTO_LOCK();
4070 do_free(blk, Memento_EventType_realloc);
4071 MEMENTO_UNLOCK();
4072 return NULL;
4073 }
4074
4075 MEMENTO_LOCK();
4076 ret = do_realloc(blk, newsize, Memento_EventType_realloc);
4077 MEMENTO_UNLOCK();
4078 if (!ret) errno = ENOMEM;
4079 return ret;
4080 }
4081
4082 int Memento_checkBlock(void *blk)
4083 {
4084 Memento_BlkHeader *memblk;
4085 int ret;
4086
4087 if (blk == NULL)
4088 return 0;
4089
4090 MEMENTO_LOCK();
4091 memblk = MEMBLK_FROMBLK(blk);
4092 ret = checkBlockUser(memblk, "check");
4093 MEMENTO_UNLOCK();
4094 return ret;
4095 }
4096
4097 #ifndef MEMENTO_LEAKONLY
4098 static int Memento_Internal_checkAllAlloced(Memento_BlkHeader *memblk, void *arg)
4099 {
4100 BlkCheckData *data = (BlkCheckData *)arg;
4101
4102 Memento_Internal_checkAllocedBlock(memblk, data);
4103 if (data->preCorrupt || data->postCorrupt) {
4104 if ((data->found & 2) == 0) {
4105 fprintf(stderr, "Allocated blocks:\n");
4106 data->found |= 2;
4107 }
4108 fprintf(stderr, " Block ");
4109 showBlock(memblk, ' ');
4110 if (data->preCorrupt) {
4111 fprintf(stderr, " Preguard ");
4112 }
4113 if (data->postCorrupt) {
4114 fprintf(stderr, "%s Postguard ",
4115 (data->preCorrupt ? "&" : ""));
4116 }
4117 fprintf(stderr, "corrupted.\n "
4118 "Block last checked OK at allocation %d. Now %d.\n",
4119 memblk->lastCheckedOK, memento.sequence);
4120 if (memento.abortOnCorruption) {
4121 fprintf(stderr, "*** memblk corrupted, calling abort()\n");
4122 abort();
4123 }
4124 data->preCorrupt = 0;
4125 data->postCorrupt = 0;
4126 data->freeCorrupt = 0;
4127 if ((memblk->flags & Memento_Flag_Reported) == 0)
4128 {
4129 memblk->flags |= Memento_Flag_Reported;
4130 data->found |= 8;
4131 }
4132 }
4133 else
4134 memblk->lastCheckedOK = memento.sequence;
4135 return 0;
4136 }
4137
4138 static int Memento_Internal_checkAllFreed(Memento_BlkHeader *memblk, void *arg)
4139 {
4140 BlkCheckData *data = (BlkCheckData *)arg;
4141
4142 Memento_Internal_checkFreedBlock(memblk, data);
4143 if (data->preCorrupt || data->postCorrupt || data->freeCorrupt) {
4144 if ((data->found & 4) == 0) {
4145 fprintf(stderr, "Freed blocks:\n");
4146 data->found |= 4;
4147 }
4148 fprintf(stderr, " ");
4149 showBlock(memblk, ' ');
4150 if (data->freeCorrupt) {
4151 fprintf(stderr, " index %d (address "FMTP") onwards", (int)data->index,
4152 &((char *)MEMBLK_TOBLK(memblk))[data->index]);
4153 if (data->preCorrupt) {
4154 fprintf(stderr, "+ preguard");
4155 }
4156 if (data->postCorrupt) {
4157 fprintf(stderr, "+ postguard");
4158 }
4159 } else {
4160 if (data->preCorrupt) {
4161 fprintf(stderr, " preguard");
4162 }
4163 if (data->postCorrupt) {
4164 fprintf(stderr, "%s Postguard",
4165 (data->preCorrupt ? "+" : ""));
4166 }
4167 }
4168 VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(Memento_BlkHeader));
4169 fprintf(stderr, " corrupted.\n"
4170 " Block last checked OK at allocation %d. Now %d.\n",
4171 memblk->lastCheckedOK, memento.sequence);
4172 if ((memblk->flags & Memento_Flag_Reported) == 0)
4173 {
4174 memblk->flags |= Memento_Flag_Reported;
4175 data->found |= 8;
4176 }
4177 VALGRIND_MAKE_MEM_NOACCESS(memblk, sizeof(Memento_BlkHeader));
4178 data->preCorrupt = 0;
4179 data->postCorrupt = 0;
4180 data->freeCorrupt = 0;
4181 }
4182 else
4183 memblk->lastCheckedOK = memento.sequence;
4184 return 0;
4185 }
4186 #endif /* MEMENTO_LEAKONLY */
4187
4188 static int Memento_checkAllMemoryLocked(void)
4189 {
4190 #ifndef MEMENTO_LEAKONLY
4191 BlkCheckData data;
4192
4193 memset(&data, 0, sizeof(data));
4194 Memento_appBlocks(&memento.used, Memento_Internal_checkAllAlloced, &data);
4195 Memento_appBlocks(&memento.free, Memento_Internal_checkAllFreed, &data);
4196 return data.found;
4197 #else
4198 return 0;
4199 #endif
4200 }
4201
4202 int Memento_checkAllMemory(void)
4203 {
4204 #ifndef MEMENTO_LEAKONLY
4205 int ret;
4206
4207 MEMENTO_LOCK();
4208 ret = Memento_checkAllMemoryLocked();
4209 MEMENTO_UNLOCK();
4210 if (ret & 8) {
4211 Memento_breakpoint();
4212 return 1;
4213 }
4214 #endif
4215 return 0;
4216 }
4217
4218 int Memento_setParanoia(int i)
4219 {
4220 memento.paranoia = i;
4221 if (memento.paranoia > 0)
4222 memento.countdown = memento.paranoia;
4223 else
4224 memento.countdown = -memento.paranoia;
4225 return i;
4226 }
4227
4228 int Memento_setIgnoreNewDelete(int ignore)
4229 {
4230 int ret = memento.ignoreNewDelete;
4231 memento.ignoreNewDelete = ignore;
4232 return ret;
4233 }
4234
4235 int Memento_paranoidAt(int i)
4236 {
4237 memento.paranoidAt = i;
4238 return i;
4239 }
4240
4241 int Memento_getBlockNum(void *b)
4242 {
4243 Memento_BlkHeader *memblk;
4244 if (b == NULL)
4245 return 0;
4246 memblk = MEMBLK_FROMBLK(b);
4247 return (memblk->sequence);
4248 }
4249
4250 int Memento_check(void)
4251 {
4252 int result;
4253
4254 fprintf(stderr, "Checking memory\n");
4255 result = Memento_checkAllMemory();
4256 fprintf(stderr, "Memory checked!\n");
4257 return result;
4258 }
4259
4260 int Memento_find(void *a)
4261 {
4262 Memento_BlkHeader *blk;
4263 int s;
4264 int flags;
4265
4266 MEMENTO_LOCK();
4267 blk = find_enclosing_block(&memento.used, a, &flags);
4268 if (blk != NULL) {
4269 fprintf(stderr, "Address "FMTP" is in %sallocated block ",
4270 a,
4271 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4272 s = showBlock(blk, ' ');
4273 fprintf(stderr, "\n");
4274 MEMENTO_UNLOCK();
4275 return s;
4276 }
4277 blk = find_enclosing_block(&memento.free, a, &flags);
4278 if (blk != NULL) {
4279 fprintf(stderr, "Address "FMTP" is in %sfreed block ",
4280 a,
4281 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4282 s = showBlock(blk, ' ');
4283 fprintf(stderr, "\n");
4284 MEMENTO_UNLOCK();
4285 return s;
4286 }
4287 MEMENTO_UNLOCK();
4288 return 0;
4289 }
4290
4291 void Memento_breakOnFree(void *a)
4292 {
4293 Memento_BlkHeader *blk;
4294 int flags;
4295
4296 MEMENTO_LOCK();
4297 blk = find_enclosing_block(&memento.used, a, &flags);
4298 if (blk != NULL) {
4299 fprintf(stderr, "Will stop when address "FMTP" (in %sallocated block ",
4300 a,
4301 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4302 showBlock(blk, ' ');
4303 fprintf(stderr, ") is freed\n");
4304 VALGRIND_MAKE_MEM_DEFINED(blk, sizeof(Memento_BlkHeader));
4305 blk->flags |= Memento_Flag_BreakOnFree;
4306 VALGRIND_MAKE_MEM_NOACCESS(blk, sizeof(Memento_BlkHeader));
4307 MEMENTO_UNLOCK();
4308 return;
4309 }
4310 blk = find_enclosing_block(&memento.free, a, &flags);
4311 if (blk != NULL) {
4312 fprintf(stderr, "Can't stop on free; address "FMTP" is in %sfreed block ",
4313 a,
4314 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4315 showBlock(blk, ' ');
4316 fprintf(stderr, "\n");
4317 MEMENTO_UNLOCK();
4318 return;
4319 }
4320 fprintf(stderr, "Can't stop on free; address "FMTP" is not in a known block.\n", a);
4321 MEMENTO_UNLOCK();
4322 }
4323
4324 void Memento_breakOnRealloc(void *a)
4325 {
4326 Memento_BlkHeader *blk;
4327 int flags;
4328
4329 MEMENTO_LOCK();
4330 blk = find_enclosing_block(&memento.used, a, &flags);
4331 if (blk != NULL) {
4332 fprintf(stderr, "Will stop when address "FMTP" (in %sallocated block ",
4333 a,
4334 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4335 showBlock(blk, ' ');
4336 fprintf(stderr, ") is freed (or realloced)\n");
4337 VALGRIND_MAKE_MEM_DEFINED(blk, sizeof(Memento_BlkHeader));
4338 blk->flags |= Memento_Flag_BreakOnFree | Memento_Flag_BreakOnRealloc;
4339 VALGRIND_MAKE_MEM_NOACCESS(blk, sizeof(Memento_BlkHeader));
4340 MEMENTO_UNLOCK();
4341 return;
4342 }
4343 blk = find_enclosing_block(&memento.free, a, &flags);
4344 if (blk != NULL) {
4345 fprintf(stderr, "Can't stop on free/realloc; address "FMTP" is in %sfreed block ",
4346 a,
4347 (flags == 1 ? "" : (flags == 2 ? "preguard of " : "postguard of ")));
4348 showBlock(blk, ' ');
4349 fprintf(stderr, "\n");
4350 MEMENTO_UNLOCK();
4351 return;
4352 }
4353 fprintf(stderr, "Can't stop on free/realloc; address "FMTP" is not in a known block.\n", a);
4354 MEMENTO_UNLOCK();
4355 }
4356
4357 int Memento_failAt(int i)
4358 {
4359 memento.failAt = i;
4360 if ((memento.sequence > memento.failAt) &&
4361 (memento.failing != 0))
4362 Memento_startFailing();
4363 return i;
4364 }
4365
4366 size_t Memento_setMax(size_t max)
4367 {
4368 memento.maxMemory = max;
4369 return max;
4370 }
4371
4372 void Memento_startLeaking(void)
4373 {
4374 if (!memento.inited)
4375 Memento_init();
4376 memento.leaking++;
4377 }
4378
4379 void Memento_stopLeaking(void)
4380 {
4381 memento.leaking--;
4382 }
4383
4384 int Memento_squeezing(void)
4385 {
4386 return memento.squeezing;
4387 }
4388
4389 int Memento_setVerbose(int x)
4390 {
4391 memento.verbose = x;
4392 return x;
4393 }
4394
4395 int Memento_addBacktraceLimitFnname(const char *fnname)
4396 {
4397 char **ss;
4398 char *s;
4399 if (!memento.inited)
4400 Memento_init();
4401 ss = MEMENTO_UNDERLYING_REALLOC(
4402 memento.backtraceLimitFnnames,
4403 sizeof(*memento.backtraceLimitFnnames) * (memento.backtraceLimitFnnamesNum + 1)
4404 );
4405 if (!ss) {
4406 fprintf(stderr, "Memento_addBacktraceLimitFnname(): out of memory\n");
4407 return -1;
4408 }
4409 memento.backtraceLimitFnnames = ss;
4410 s = MEMENTO_UNDERLYING_MALLOC(strlen(fnname) + 1);
4411 if (!s) {
4412 fprintf(stderr, "Memento_addBacktraceLimitFnname(): out of memory\n");
4413 return -1;
4414 }
4415 memento.backtraceLimitFnnames[memento.backtraceLimitFnnamesNum] = s;
4416 strcpy(s, fnname);
4417 memento.backtraceLimitFnnamesNum += 1;
4418 return 0;
4419 }
4420
4421 int Memento_setAtexitFin(int atexitfin)
4422 {
4423 if (!memento.inited) {
4424 Memento_init();
4425 }
4426 memento.atexitFin = atexitfin;
4427 return 0;
4428 }
4429
4430 void *Memento_cpp_new(size_t size)
4431 {
4432 void *ret;
4433
4434 if (!memento.inited)
4435 Memento_init();
4436
4437 if (memento.ignoreNewDelete)
4438 return MEMENTO_UNDERLYING_MALLOC(size);
4439
4440 if (size == 0)
4441 size = 1;
4442 MEMENTO_LOCK();
4443 ret = do_malloc(size, Memento_EventType_new);
4444 MEMENTO_UNLOCK();
4445 return ret;
4446 }
4447
4448 void Memento_cpp_delete(void *pointer)
4449 {
4450 if (!pointer)
4451 return;
4452
4453 if (!memento.inited)
4454 Memento_init();
4455 if (memento.ignoreNewDelete)
4456 {
4457 MEMENTO_UNDERLYING_FREE(pointer);
4458 return;
4459 }
4460
4461 MEMENTO_LOCK();
4462 do_free(pointer, Memento_EventType_delete);
4463 MEMENTO_UNLOCK();
4464 }
4465
4466 /* Some C++ systems (apparently) don't provide new[] or delete[]
4467 * operators. Provide a way to cope with this */
4468 void *Memento_cpp_new_array(size_t size)
4469 {
4470 void *ret;
4471 if (!memento.inited)
4472 Memento_init();
4473
4474 if (size == 0)
4475 size = 1;
4476
4477 if (memento.ignoreNewDelete)
4478 return MEMENTO_UNDERLYING_MALLOC(size);
4479
4480 MEMENTO_LOCK();
4481 ret = do_malloc(size, Memento_EventType_newArray);
4482 MEMENTO_UNLOCK();
4483 return ret;
4484 }
4485
4486 void Memento_cpp_delete_array(void *pointer)
4487 {
4488 if (memento.ignoreNewDelete)
4489 {
4490 MEMENTO_UNDERLYING_FREE(pointer);
4491 return;
4492 }
4493
4494 MEMENTO_LOCK();
4495 do_free(pointer, Memento_EventType_deleteArray);
4496 MEMENTO_UNLOCK();
4497 }
4498
4499 #else /* MEMENTO */
4500
4501 /* Just in case anyone has left some debugging code in... */
4502 void (Memento_breakpoint)(void)
4503 {
4504 }
4505
4506 int (Memento_checkBlock)(void *b)
4507 {
4508 return 0;
4509 }
4510
4511 int (Memento_checkAllMemory)(void)
4512 {
4513 return 0;
4514 }
4515
4516 int (Memento_check)(void)
4517 {
4518 return 0;
4519 }
4520
4521 int (Memento_setParanoia)(int i)
4522 {
4523 return 0;
4524 }
4525
4526 int (Memento_paranoidAt)(int i)
4527 {
4528 return 0;
4529 }
4530
4531 int (Memento_breakAt)(int i)
4532 {
4533 return 0;
4534 }
4535
4536 int (Memento_getBlockNum)(void *i)
4537 {
4538 return 0;
4539 }
4540
4541 int (Memento_find)(void *a)
4542 {
4543 return 0;
4544 }
4545
4546 int (Memento_failAt)(int i)
4547 {
4548 return 0;
4549 }
4550
4551 void (Memento_breakOnFree)(void *a)
4552 {
4553 }
4554
4555 void (Memento_breakOnRealloc)(void *a)
4556 {
4557 }
4558
4559 void *(Memento_takeRef)(void *a)
4560 {
4561 return a;
4562 }
4563
4564 void *(Memento_dropRef)(void *a)
4565 {
4566 return a;
4567 }
4568
4569 void *(Memento_adjustRef)(void *a, int adjust)
4570 {
4571 return a;
4572 }
4573
4574 void *(Memento_reference)(void *a)
4575 {
4576 return a;
4577 }
4578
4579 #undef Memento_malloc
4580 #undef Memento_free
4581 #undef Memento_realloc
4582 #undef Memento_calloc
4583 #undef Memento_strdup
4584 #undef Memento_asprintf
4585 #undef Memento_vasprintf
4586
4587 void *Memento_malloc(size_t size)
4588 {
4589 return MEMENTO_UNDERLYING_MALLOC(size);
4590 }
4591
4592 void Memento_free(void *b)
4593 {
4594 MEMENTO_UNDERLYING_FREE(b);
4595 }
4596
4597 void *Memento_realloc(void *b, size_t s)
4598 {
4599 return MEMENTO_UNDERLYING_REALLOC(b, s);
4600 }
4601
4602 void *Memento_calloc(size_t n, size_t s)
4603 {
4604 return MEMENTO_UNDERLYING_CALLOC(n, s);
4605 }
4606
4607 #if !defined(MEMENTO_GS_HACKS) && !defined(MEMENTO_MUPDF_HACKS)
4608 /* Avoid calling strdup, in case our compiler doesn't support it.
4609 * Yes, I'm looking at you, early Visual Studios. */
4610 char *Memento_strdup(const char *s)
4611 {
4612 size_t len = strlen(s)+1;
4613 char *ret = MEMENTO_UNDERLYING_MALLOC(len);
4614 if (ret != NULL)
4615 memcpy(ret, s, len);
4616 return ret;
4617 }
4618
4619 /* Avoid calling asprintf, in case our compiler doesn't support it.
4620 * Vaguely unhappy about relying on vsnprintf, but... */
4621 int Memento_asprintf(char **ret, const char *format, ...)
4622 {
4623 va_list va;
4624 int n;
4625 int n2;
4626
4627 va_start(va, format);
4628 n = vsnprintf(NULL, 0, format, va);
4629 va_end(va);
4630 if (n < 0)
4631 return n;
4632
4633 *ret = MEMENTO_UNDERLYING_MALLOC(n+1);
4634 if (*ret == NULL)
4635 return -1;
4636
4637 va_start(va, format);
4638 n2 = vsnprintf(*ret, n + 1, format, va);
4639 va_end(va);
4640
4641 return n2;
4642 }
4643
4644 /* Avoid calling vasprintf, in case our compiler doesn't support it.
4645 * Vaguely unhappy about relying on vsnprintf, but... */
4646 int Memento_vasprintf(char **ret, const char *format, va_list ap)
4647 {
4648 int n;
4649 va_list ap2;
4650 va_copy(ap2, ap);
4651
4652 n = vsnprintf(NULL, 0, format, ap);
4653 if (n < 0) {
4654 va_end(ap2);
4655 return n;
4656 }
4657
4658 *ret = MEMENTO_UNDERLYING_MALLOC(n+1);
4659 if (*ret == NULL) {
4660 va_end(ap2);
4661 return -1;
4662 }
4663
4664 n = vsnprintf(*ret, n + 1, format, ap2);
4665 va_end(ap2);
4666
4667 return n;
4668 }
4669 #endif
4670
4671 void (Memento_listBlocks)(void)
4672 {
4673 }
4674
4675 void (Memento_listNewBlocks)(void)
4676 {
4677 }
4678
4679 void (Memento_listLargeBlocks)(void)
4680 {
4681 }
4682
4683 void (Memento_listPhasedBlocks)(void)
4684 {
4685 }
4686
4687 int (Memento_setIgnoreNewDelete)(int ignore)
4688 {
4689 return 0;
4690 }
4691
4692 size_t (Memento_setMax)(size_t max)
4693 {
4694 return 0;
4695 }
4696
4697 void (Memento_stats)(void)
4698 {
4699 }
4700
4701 void *(Memento_label)(void *ptr, const char *label)
4702 {
4703 return ptr;
4704 }
4705
4706 void (Memento_info)(void *addr)
4707 {
4708 }
4709
4710 void (Memento_listBlockInfo)(void)
4711 {
4712 }
4713
4714 void (Memento_blockInfo)(void *ptr)
4715 {
4716 }
4717
4718 void (Memento_startLeaking)(void)
4719 {
4720 }
4721
4722 void (Memento_stopLeaking)(void)
4723 {
4724 }
4725
4726 int (Memento_squeezing)(void)
4727 {
4728 return 0;
4729 }
4730
4731 int (Memento_setVerbose)(int x)
4732 {
4733 return x;
4734 }
4735
4736 void Memento_showHash(unsigned int hash)
4737 {
4738 }
4739
4740 #endif /* MEMENTO */
4741
4742 #endif /* MEMENTO_CPP_EXTRAS_ONLY */
4743
4744 /* Everything here is only for C++, and then only if we haven't
4745 * disabled it. */
4746
4747 #ifndef MEMENTO_NO_CPLUSPLUS
4748 #ifdef __cplusplus
4749
4750 // C++ Operator Veneers - START
4751 void *operator new(size_t size)
4752 {
4753 return Memento_cpp_new(size);
4754 }
4755 void operator delete(void *pointer)
4756 {
4757 Memento_cpp_delete(pointer);
4758 }
4759 void *operator new[](size_t size)
4760 {
4761 return Memento_cpp_new_array(size);
4762 }
4763 void operator delete[](void *pointer)
4764 {
4765 Memento_cpp_delete_array(pointer);
4766 }
4767
4768 /* Some C++ systems (apparently) don't provide new[] or delete[]
4769 * operators. Provide a way to cope with this */
4770 #ifndef MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS
4771 void *operator new[](size_t size)
4772 {
4773 return Memento_cpp_new_array(size);
4774 }
4775
4776 void operator delete[](void *pointer)
4777 {
4778 Memento_cpp_delete_array(pointer);
4779 }
4780 #endif /* MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS */
4781 // C++ Operator Veneers - END
4782
4783 #endif /* __cplusplus */
4784 #endif /* MEMENTO_NO_CPLUSPLUS */