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