blob: 80dd90a642fd739762e3d282c6a4c7728b0b2228 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/* **************************************************************************
33 *
34 * Set of malloc/realloc/calloc/strdup/free replacement macros that
35 * insert some extra words around each allocation for debugging purposes
36 * and also attempt to detect invalid uses of the malloc heap through
37 * various tricks like inserting clobber words at the head and tail of
38 * the user's area, delayed free() calls, and setting the memory to
39 * a fixed pattern on allocation and when freed. The allocations also
40 * can include warrants so that when an area is clobbered, this
41 * package can report where the allocation took place.
42 * The macros included are:
43 * malloc(size)
44 * realloc(ptr,size)
45 * calloc(nelem,elsize)
46 * strdup(s1)
47 * free(ptr)
48 * malloc_police() <--- Not a system function
49 * The above macros match the standard behavior of the system functions.
50 *
51 * They should be used through the include file "debug_malloc.h".
52 *
53 * IMPORTANT: All source files that call any of these macros
54 * should include debug_malloc.h. This package will
55 * not work if the memory isn't allocated and freed
56 * by the macros in debug_malloc.h. The important issue
57 * is that any malloc() from debug_malloc.h must be
58 * freed by the free() in debug_malloc.h.
59 *
60 * The macros in debug_malloc.h will override the normal use of
61 * malloc, realloc, calloc, strdup, and free with the functions below.
62 *
63 * These functions include:
64 * void *debug_malloc(size_t, void*, int);
65 * void *debug_realloc(void*, size_t, void*, int);
66 * void *debug_calloc(size_t, size_t, void*, int);
67 * void debug_free(void *, void*, int);
68 *
69 * In addition the function debug_malloc_police() can be called to
70 * tell you what memory has not been freed.
71 * void debug_malloc_police(void*, int);
72 * The function debug_malloc_police() is available through the macro
73 * malloc_police(). Normally you would want to call this at exit()
74 * time to find out what memory is still allocated.
75 *
76 * The variable malloc_watch determines if the warrants are generated.
77 * warrants are structures that include the filename and line number
78 * of the caller who allocated the memory. This structure is stored
79 * at the tail of the malloc space, which is allocated large enough
80 * to hold some clobber words at the head and tail, the user's request
81 * and the warrant record (if malloc_watch is non-zero).
82 *
83 * The macro LEFT_OVER_CHAR is what the trailing bytes of an allocation
84 * are set to (when the allocation is not a multiple of 8) on allocation.
85 * At free(0 time, these bytes are double checked to make sure they were
86 * not clobbered. To remove this feature #undef LEFT_OVER_CHAR.
87 *
88 * The memory freed will have the FREED_CHAR put into it. To remove this
89 * feature #undef FREED_CHAR.
90 *
91 * The memory allocated (not calloc'd) will have the ALLOC_CHAR put into it
92 * at the time of allocation. To remove this feature #undef ALLOC_CHAR.
93 *
94 * The macro MAX_FREE_DELAY_COUNT controls how many free blocks will
95 * be kept around before being freed. This creates a delayed affect
96 * so that free space that gets clobbered just might get detected.
97 * The free() call will immediately set the user space to the FREED_CHAR,
98 * leaving the clobber words and warrant in place (making sure they
99 * haven't been clobbered). Then the free() pointer is added to a
100 * queue of MAX_FREE_DELAY_COUNT long, and if the queue was full, the
101 * oldest free()'d memory is actually freed, getting it's entire
102 * memory length set to the FREED_CHAR.
103 *
104 * WARNING: This can significantly slow down an application, depending
105 * on how many allocations are made. Also the additional memory
106 * needed for the clobber words and the warrants can be significant
107 * again, depending on how many allocations are made.
108 * In addition, the delayed free calls can create situations
109 * where you might run out of memory prematurely.
110 *
111 * **************************************************************************
112 */
113
114#ifdef DEBUG
115
116#include <stdio.h>
117#include <stdlib.h>
118#include <string.h>
119#include <ctype.h>
120#include <stdarg.h>
121#include "hprof.h"
122
123/* ***************************************************************************
124 * Space normally looks like (clobber Word is 64 bits and aligned to 8 bytes):
125 *
126 * -----------------
127 * malloc/free get->| clobber Word | ---> contains -size requested by user
128 * -----------------
129 * User gets --->| user space |
130 * | |
131 * | | left_over | ---> left_over bytes will be <= 7
132 * -----------------
133 * | clobber Word | ---> contains -size requested by user
134 * -----------------
135 * | Warrant | ---> Optional (malloc_watch!=0)
136 * | | Contains filename and line number
137 * | | where allocation happened
138 * | |
139 * -----------------
140 ***************************************************************************/
141
142/*
143 * Flag that tells debug_malloc/debug_free/debug_realloc to police
144 * heap space usage. (This is a dynamic flag that can be turned on/off)
145 */
146static int malloc_watch = 1;
147
148/* Character to stuff into freed space */
149#define FREED_CHAR 'F'
150
151/* Character to stuff into allocated space */
152#define ALLOC_CHAR 'A'
153
154/* Character to stuff into left over trailing bytes */
155#define LEFT_OVER_CHAR 'Z'
156
157/* Number of 'free' calls that will be delayed until the end */
158#define MAX_FREE_DELAY_COUNT 1
159#undef MAX_FREE_DELAY_COUNT
160
161/* Maximum name of __FILE_ stored in each malloc'd area */
162#define WARRANT_NAME_MAX (32-1) /* 1 less than multiple of 8 is best */
163
164/* Macro to convert a user pointer to the malloc pointer */
165#define user2malloc_(uptr) (((char*)(void*)uptr)-sizeof(Word))
166
167/* Macro to convert a macro pointer to the user pointer */
168#define malloc2user_(mptr) (((char*)(void*)(mptr))+sizeof(Word))
169
170/* Size of the warrant record (this is dynamic) */
171#define warrant_space ( malloc_watch?sizeof(Warrant_Record):0 )
172
173/* Macro to round up a number of bytes to a multiple of sizeof(Word) bytes */
174#define round_up_(n) \
175 ((n)==0?0:(sizeof(Word)+(((n)-1)/sizeof(Word))*sizeof(Word)))
176
177/* Macro to calculate the needed malloc bytes from the user's request. */
178#define rbytes_(nbytes) \
179 (size_t)( sizeof(Word) + round_up_(nbytes) + sizeof(Word) + warrant_space )
180
181/* Macro to get the -size stored in space through the malloc pointer */
182#define nsize1_(mptr) (((Word*)(void*)(mptr))->nsize1)
183#define nsize2_(mptr) (((Word*)(void*)(mptr))->nsize2)
184
185/* Macro to get the -size stored in the tail of the space through */
186/* the malloc pointer */
187#define tail_nsize1_(mptr) \
188 nsize1_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))
189#define tail_nsize2_(mptr) \
190 nsize2_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))
191
192/* Macro to get the -size stored in space through the user pointer */
193#define user_nsize1_(uptr) nsize1_(user2malloc_(uptr))
194#define user_nsize2_(uptr) nsize2_(user2malloc_(uptr))
195
196/* Macro to get the -size stored in the tail of the space through */
197/* the user pointer */
198#define user_tail_nsize1_(uptr) tail_nsize1_(user2malloc_(uptr))
199#define user_tail_nsize2_(uptr) tail_nsize2_(user2malloc_(uptr))
200
201/* Macro to get the int* of the last 32bit word of user space */
202#define last_user_word_(mptr) \
203 ((int*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))))
204
205/* Macros to get at the warrant contents from the malloc pointer */
206#define warrant_(mptr) \
207 (*((Warrant_Record*)(void*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)*2)))
208
209/* This struct is allocated after the tail clobber word if malloc_watch */
210/* is true. */
211typedef struct {
212 void *link; /* Next mptr in list */
213 char name[WARRANT_NAME_MAX + 1]; /* Name of allocator */
214 int line; /* Line number where allocated */
215 int id; /* Nth allocation */
216} Warrant_Record;
217#define warrant_link_(mptr) warrant_(mptr).link
218#define warrant_name_(mptr) warrant_(mptr).name
219#define warrant_line_(mptr) warrant_(mptr).line
220#define warrant_id_(mptr) warrant_(mptr).id
221#define MFILE(mptr) (malloc_watch?warrant_name_(mptr):"?")
222#define MLINE(mptr) (malloc_watch?warrant_line_(mptr):0)
223#define MID(mptr) (malloc_watch?warrant_id_(mptr):0)
224
225/* This should be one machine word and is also the clobber word struct */
226typedef struct {
227 int nsize1;
228 int nsize2;
229} Word; /* Largest basic type , sizeof(double)? */
230
231/* The first malloc pointer for the warrants */
232static void *first_warrant_mptr = NULL;
233
234/* Counter of allocations */
235static int id_counter = 0;
236static int largest_size = 0;
237static void * largest_addr = NULL;
238static void * smallest_addr = NULL;
239
240/* Used to isolate what the error is */
241static char *debug_check;
242static void *clobbered_ptr;
243
244/* Minumum macro */
245#define minimum(a,b) ((a)<(b)?(a):(b))
246
247/* Message routine */
248static void
249error_message(const char * format, ...)
250{
251 FILE *error_fp = stderr; /* All debug_malloc.c messages */
252 va_list ap;
253 va_start(ap, format);
254 (void)fprintf(error_fp, "debug_malloc: ");
255 (void)vfprintf(error_fp, format, ap);
256 (void)fprintf(error_fp, "\n");
257 (void)fflush(error_fp);
258 va_end(ap);
259}
260
261/* This function prints out a memory error for the memory function
262 * 'name' which was called in file 'file' at line number 'line'. The malloc
263 * pointer with the error is in 'mptr'.
264 */
265static void
266memory_error(void *mptr, const char *name, int mid, const char *mfile, int mline, const char *file, int line)
267{
268 char nice_words[512];
269 char temp[256];
270 int len;
271 void *mptr_walk;
272
273 if (name == NULL)
274 name = "UNKNOWN_NAME";
275 if (file == NULL)
276 file = "UNKNOWN_FILE";
277 md_system_error(temp, (int)sizeof(temp));
278 (void)strcpy(nice_words, temp);
279 if ( debug_check!=NULL ) {
280 (void)md_snprintf(nice_words, sizeof(nice_words),
281 "%s The %s at %p appears to have been hit.",
282 temp, debug_check, clobbered_ptr);
283 }
284 len = -nsize1_(mptr);
285 error_message("Error: "
286 "%s The malloc space #%d is at %p [user size=%d(0x%x)],"
287 " and was allocated from file \"%s\" at line %d."
288 " [The debug function %s() detected this error "
289 "in file \"%s\" at line %d.]",
290 nice_words, mid, mptr, len, len, mfile, mline,
291 name, file, line);
292
293 /* Print out contents of this allocation */
294 {
295 int i;
296 void *uptr = malloc2user_(mptr);
297 char *pmess;
298 pmess = temp;
299 for(i=0;i<(int)sizeof(temp);i++) {
300 int ch = ((unsigned char*)uptr)[i];
301 if ( isprint(ch) ) {
302 *pmess++ = ch;
303 } else {
304 *pmess++ = '\\';
305 *pmess++ = 'x';
306 (void)sprintf(pmess,"%02x",ch);
307 pmess+=2;
308 }
309 }
310 *pmess = 0;
311 error_message("Error: %p contains user data: %s", uptr, temp);
312 }
313
314 /* Try and print out table */
315 if (!malloc_watch) {
316 return;
317 }
318 mptr_walk = first_warrant_mptr;
319 if (mptr_walk != NULL) {
320 error_message("Active allocations: "
321 "count=%d, largest_size=%d, address range (%p,%p)",
322 id_counter, largest_size, smallest_addr, largest_addr);
323 do {
324 int size1;
325 int size2;
326 char *mfile_walk;
327
328 if ( mptr_walk > largest_addr || mptr_walk < smallest_addr ) {
329 error_message("Terminating list due to pointer corruption");
330 break;
331 }
332 size1 = -nsize1_(mptr_walk);
333 size2 = -nsize2_(mptr_walk);
334 mfile_walk = MFILE(mptr_walk);
335 error_message("#%d: addr=%p size1=%d size2=%d file=\"%.*s\" line=%d",
336 MID(mptr_walk), mptr_walk, size1, size2,
337 WARRANT_NAME_MAX, mfile_walk, MLINE(mptr_walk));
338 if ( size1 != size2 || size1 > largest_size || size1 < 0 ) {
339 error_message("Terminating list due to size corruption");
340 break;
341 }
342 mptr_walk = warrant_link_(mptr_walk);
343 } while (mptr_walk != NULL);
344 }
345 abort();
346}
347
348/* This function sets the clobber word and sets up the warrant for the input
349 * malloc pointer "mptr".
350 */
351static void
352setup_space_and_issue_warrant(void *mptr, size_t size, const char *file, int line)
353{
354 register int nbytes;
355
356 /*LINTED*/
357 nbytes = (int)size;
358 if ( nbytes > largest_size || largest_addr == NULL ) largest_size = nbytes;
359 /*LINTED*/
360 if ( mptr > largest_addr ) largest_addr = mptr;
361 /*LINTED*/
362 if ( mptr < smallest_addr || smallest_addr == NULL ) smallest_addr = mptr;
363
364 /* Must be done first: */
365 nsize1_(mptr) = -nbytes;
366 nsize2_(mptr) = -nbytes;
367 tail_nsize1_(mptr) = -nbytes;
368 tail_nsize2_(mptr) = -nbytes;
369
370#ifdef LEFT_OVER_CHAR
371 /* Fill in those few extra bytes just before the tail Word structure */
372 {
373 register int trailing_extra_bytes;
374 /* LINTED */
375 trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);
376 if ( trailing_extra_bytes > 0 ) {
377 register char *p;
378 register int i;
379 p = ((char *) mptr) + sizeof(Word) + nbytes;
380 for (i = 0; i < trailing_extra_bytes; i++)
381 p[i] = LEFT_OVER_CHAR;
382 }
383 }
384#endif
385
386 /* Fill out warrant */
387 if (malloc_watch) {
388 static Warrant_Record zero_warrant;
389 register void *p1,
390 *p2;
391 size_t len;
392 int start_pos = 0;
393 warrant_(mptr) = zero_warrant;
394 p1 = warrant_name_(mptr);
395 len = strlen(file);
396 if ( len > WARRANT_NAME_MAX ) {
397 /*LINTED*/
398 start_pos = (int)len - WARRANT_NAME_MAX;
399 }
400 p2 = ((char*)file) + start_pos;
401 /*LINTED*/
402 (void) memcpy(p1, p2, minimum(((int)len), WARRANT_NAME_MAX));
403 warrant_line_(mptr) = line;
404 warrant_id_(mptr) = ++id_counter;
405 warrant_link_(mptr) = first_warrant_mptr;
406 first_warrant_mptr = mptr;
407 }
408}
409
410/* This function checks the clobber words at the beginning and end of the
411 * allocated space.
412 */
413static void
414memory_check(void *uptr, int mid, const char *mfile, int mline, const char *file, int line)
415{
416 int neg_nbytes;
417 int nbytes;
418
419 debug_check = "pointer value itself";
420 clobbered_ptr = uptr;
421 if (uptr == NULL)
422 memory_error((void *) NULL, "memory_check", mid, mfile, mline, file, line);
423
424 /* Check both Word structures */
425
426 debug_check = "first beginning clobber word";
427 clobbered_ptr = (char*)&user_nsize1_(uptr);
428 neg_nbytes = user_nsize1_(uptr);
429 if (neg_nbytes >= 0)
430 memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
431
432 debug_check = "second beginning clobber word";
433 clobbered_ptr = (char*)&user_nsize2_(uptr);
434 if (neg_nbytes != user_nsize2_(uptr))
435 memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
436
437 debug_check = "first ending clobber word";
438 clobbered_ptr = (char*)&user_tail_nsize1_(uptr);
439 if (neg_nbytes != user_tail_nsize1_(uptr))
440 memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
441
442 debug_check = "second ending clobber word";
443 clobbered_ptr = (char*)&user_tail_nsize2_(uptr);
444 if (neg_nbytes != user_tail_nsize2_(uptr))
445 memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
446
447 /* Get a positive count of bytes */
448 nbytes = -neg_nbytes;
449
450#ifdef LEFT_OVER_CHAR
451 {
452 /* Check those few extra bytes just before the tail Word structure */
453 register int trailing_extra_bytes;
454 register int i;
455 register char *p;
456 /* LINTED */
457 trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);
458 p = ((char *) (uptr)) + nbytes;
459 debug_check = "trailing left over area";
460 for (i = 0; i < trailing_extra_bytes; i++) {
461 clobbered_ptr = p+1;
462 if (p[i] != LEFT_OVER_CHAR) {
463 memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);
464 }
465 }
466 }
467#endif
468
469 /* Make sure debug_check is cleared */
470 debug_check = NULL;
471}
472
473/* This function looks for the given malloc pointer in the police line up
474 * and removes it from the warrant list.
475 * mptr The pointer to the malloc space being removed
476 */
477static int
478remove_warrant(void *mptr)
479{
480 void *mptr1,
481 *last_mptr1;
482
483 /* Free it up from the list */
484 if (malloc_watch && mptr != NULL) {
485 int found;
486
487 found = 0;
488 last_mptr1 = NULL;
489 mptr1 = first_warrant_mptr;
490 while (mptr1 != NULL) {
491 if (mptr1 == mptr) {
492 if (last_mptr1 == NULL)
493 first_warrant_mptr = warrant_link_(mptr1);
494 else
495 warrant_link_(last_mptr1) = warrant_link_(mptr1);
496 found = 1;
497 break;
498 }
499 last_mptr1 = mptr1;
500 mptr1 = warrant_link_(mptr1);
501 }
502 return found;
503 }
504 return 1;
505}
506
507static void
508actual_free(void *uptr, const char *file, int line)
509{
510 void *mptr;
511 const char *mfile;
512 int mline;
513 int mid;
514 if ( uptr == NULL )
515 return;
516 mptr = user2malloc_(uptr);
517 memory_check(uptr, (mid=MID(mptr)), (mfile=MFILE(mptr)), (mline=MLINE(mptr)), file, line);
518 if (malloc_watch && remove_warrant(mptr)==0 )
519 memory_check(uptr, mid, mfile, mline, file, line);
520#ifdef FREED_CHAR
521 if ( mptr!=NULL ) {
522 size_t nbytes = -nsize1_(mptr);
523 /* LINTED */
524 (void)memset(mptr, FREED_CHAR, rbytes_(nbytes));
525 }
526#endif
527 free(mptr);
528}
529
530#ifdef MAX_FREE_DELAY_COUNT
531
532static void *free_delay[MAX_FREE_DELAY_COUNT];
533static int free_delay_pos = 0;
534
535static void
536delayed_free(void *uptr, const char* file, int line)
537{
538 void *mptr;
539 void *olduptr = free_delay[free_delay_pos];
540 size_t nbytes;
541 if ( uptr==NULL )
542 return;
543 mptr = user2malloc_(uptr);
544 memory_check(uptr, MID(mptr), MFILE(mptr), MLINE(mptr), file, line);
545 if ( olduptr!=NULL ) {
546 actual_free(olduptr, file, line);
547 }
548 free_delay[free_delay_pos] = uptr;
549 free_delay_pos++;
550 free_delay_pos = free_delay_pos % MAX_FREE_DELAY_COUNT;
551 nbytes = -user_nsize1_(uptr);
552#ifdef FREED_CHAR
553 (void)memset(uptr, FREED_CHAR, (size_t)nbytes);
554#endif
555}
556
557static void
558delayed_free_all(const char *file, int line)
559{
560 int i;
561 for ( i=0; i< MAX_FREE_DELAY_COUNT; i++) {
562 void *olduptr = free_delay[i];
563 free_delay[i] = NULL;
564 if ( olduptr!=NULL ) {
565 actual_free(olduptr, file, line);
566 }
567 }
568}
569
570#endif
571
572void
573debug_free(void *uptr, const char *file, int line)
574{
575 int mid = 0;
576
577 if (uptr == NULL)
578 memory_error((void *) NULL, "debug_free", mid, file, line, file, line);
579#ifdef MAX_FREE_DELAY_COUNT
580 delayed_free(uptr, file, line);
581#else
582 actual_free(uptr, file, line);
583#endif
584}
585
586/* This function calls malloc(). */
587void *
588debug_malloc(size_t nbytes, const char *file, int line)
589{
590 void *mptr;
591 void *uptr;
592 int mid = id_counter;
593
594 /*LINTED*/
595 if ((int)nbytes <= 0)
596 memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);
597 /* LINTED */
598 mptr = malloc(rbytes_(nbytes));
599 if (mptr == NULL)
600 memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);
601 setup_space_and_issue_warrant(mptr, nbytes, file, line);
602 uptr = malloc2user_(mptr);
603#ifdef ALLOC_CHAR
604 (void)memset(uptr, ALLOC_CHAR, (size_t)nbytes);
605#endif
606 return uptr;
607}
608
609void *
610debug_realloc(void *uptr, size_t nbytes, const char *file, int line)
611{
612 void *mptr;
613 void *oldmptr;
614 void *newuptr;
615 size_t oldnbytes;
616 int mid = id_counter;
617
618 oldmptr = user2malloc_(uptr);
619 oldnbytes = 0;
620 if ((int)nbytes <= 0)
621 memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);
622 if (uptr != NULL) {
623 memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);
624 oldnbytes = -user_nsize1_(uptr);
625 if ( malloc_watch && remove_warrant(oldmptr)==0 )
626 memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);
627 }
628 if (uptr == NULL) {
629 /* LINTED */
630 mptr = malloc(rbytes_(nbytes));
631 } else {
632 /* LINTED */
633 mptr = realloc(oldmptr, rbytes_(nbytes));
634 }
635 if (mptr == NULL)
636 memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);
637 setup_space_and_issue_warrant(mptr, nbytes, file, line);
638 newuptr = malloc2user_(mptr);
639#ifdef ALLOC_CHAR
640 if (uptr == NULL)
641 (void)memset(newuptr, ALLOC_CHAR, (size_t)nbytes);
642 else if ( nbytes > oldnbytes )
643 (void)memset(((char*)newuptr)+oldnbytes, ALLOC_CHAR, (size_t)nbytes-oldnbytes);
644#endif
645 return newuptr;
646}
647
648/* This function calls calloc(). */
649void *
650debug_calloc(size_t nelem, size_t elsize, const char *file, int line)
651{
652 void *mptr;
653 size_t nbytes;
654 int mid = id_counter;
655
656 nbytes = nelem*elsize;
657 /*LINTED*/
658 if ((int)nbytes <= 0)
659 memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);
660 /* LINTED */
661 mptr = calloc(rbytes_(nbytes),1);
662 if (mptr == NULL)
663 memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);
664 setup_space_and_issue_warrant(mptr, nbytes, file, line);
665 return malloc2user_(mptr);
666}
667
668/* This function replaces strdup(). */
669char *
670debug_strdup(const char *s1, const char *file, int line)
671{
672 void *mptr;
673 void *uptr;
674 size_t nbytes;
675 int mid = id_counter;
676
677 if (s1 == NULL)
678 memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
679 nbytes = strlen(s1)+1;
680 /*LINTED*/
681 if ((int)nbytes < 0)
682 memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
683 /* LINTED */
684 mptr = malloc(rbytes_(nbytes));
685 if (mptr == NULL)
686 memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);
687 setup_space_and_issue_warrant(mptr, nbytes, file, line);
688 uptr = malloc2user_(mptr);
689 (void)strcpy((char*)uptr, s1);
690 return (char*)uptr;
691}
692
693void
694debug_malloc_verify(const char *file, int line)
695{
696 void *mptr;
697
698#ifdef MAX_FREE_DELAY_COUNT
699 delayed_free_all(file,line);
700#endif
701
702 if (!malloc_watch) {
703 return;
704 }
705 mptr = first_warrant_mptr;
706 if (mptr != NULL) {
707 /* Check all this memory first */
708 do {
709 memory_check(malloc2user_(mptr), MID(mptr), MFILE(mptr), MLINE(mptr), file, line);
710 mptr = warrant_link_(mptr);
711 } while (mptr != NULL);
712 }
713}
714
715/* Report outstanding space warrants to console. */
716void
717debug_malloc_police(const char *file, int line)
718{
719 void *mptr;
720
721#ifdef MAX_FREE_DELAY_COUNT
722 delayed_free_all(file,line);
723#endif
724
725 if (!malloc_watch) {
726 return;
727 }
728
729 mptr = first_warrant_mptr;
730 if (mptr != NULL) {
731 debug_malloc_verify(file, line);
732 /* Now issue warrants */
733 mptr = first_warrant_mptr;
734 do {
735 error_message("Outstanding space warrant: %p (%d bytes) allocated by %s at line %d, allocation #%d",
736 mptr, -nsize1_(mptr), warrant_name_(mptr),
737 warrant_line_(mptr), warrant_id_(mptr));
738
739 mptr = warrant_link_(mptr);
740 } while (mptr != NULL);
741 }
742}
743
744#else
745
746void
747debug_malloc_verify(const char *file, int line)
748{
749 file = file;
750 line = line;
751}
752
753void
754debug_malloc_police(const char *file, int line)
755{
756 file = file;
757 line = line;
758}
759
760#endif