2 This file is part of SXEmacs
4 SXEmacs is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 SXEmacs is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Synched up with: Not in FSF. */
20 /* Debugging hooks for malloc. */
22 /* These hooks work with gmalloc to catch allocation errors.
23 In particular, the following is trapped:
25 * Freeing the same pointer twice.
26 * Trying to free a pointer not returned by malloc.
27 * Trying to realloc a pointer not returned by malloc.
29 In addition, every word of every block freed is set to
30 0xdeadbeef. This causes many uses of freed storage to be
31 trapped or recognized.
33 When you use this, the storage used by the last FREE_QUEUE_LIMIT
34 calls to free() is not recycled. When you call free for the Nth
35 time, the (N - FREE_QUEUE_LIMIT)'th block is actually recycled.
37 For these last FREE_QUEUE_LIMIT calls to free() a backtrace is
38 saved showing where it was called from. The function
39 find_backtrace() is provided here to be called from GDB with a
40 pointer (such as would be passed to free()) as argument, e.g.
41 (gdb) p/a *find_backtrace (0x234000). If SAVE_ARGS is defined,
42 the first three arguments to each function are saved as well as the
45 If UNMAPPED_FREE is defined, instead of setting every word of freed
46 storage to 0xdeadbeef, every call to malloc goes on its own page(s).
47 When free() is called, the block is read and write protected. This
48 is very useful when debugging, since it usually generates a bus error
49 when the deadbeef hack might only cause some garbage to be printed.
50 However, this is too slow for everyday use, since it takes an enormous
53 Some other features that would be useful are:
55 * Checking for storage leaks.
56 This could be done by a GC-like facility that would scan the data
57 segment looking for pointers to allocated storage and tell you
58 about those that are no longer referenced. This could be invoked
59 at any time. Another possibility is to report on what allocated
60 storage is still in use when the process is exited. Typically
61 there will be a large amount, so this might not be very useful.
71 #if !defined(HAVE_LIBMCHECK)
78 #include <sys/param.h>
79 #define ROUND_UP_TO_PAGE(i) (((i) + PAGEOFFSET) & PAGEMASK)
82 #include <sys/types.h>
84 /* System function prototypes don't belong in C source files */
85 /* extern void free (void *); */
87 static struct hash_table *pointer_table;
89 extern void (*__free_hook) (void *);
90 extern void *(*__malloc_hook) (size_t);
92 static void *check_malloc(size_t);
94 typedef void (*fun_ptr) (void);
96 /* free_queue is not too useful without backtrace logging */
97 #define FREE_QUEUE_LIMIT 1
98 #define TRACE_LIMIT 20
109 unsigned long length;
112 static free_queue_entry free_queue[FREE_QUEUE_LIMIT];
114 static int current_free;
116 static int strict_free_check;
118 static void check_free(void *ptr)
123 pointer_table = make_hash_table(max(100, FREE_QUEUE_LIMIT * 2));
127 unsigned long rounded_up_size;
131 (EMACS_INT)gethash(ptr, pointer_table,
132 (const void **)((void*)&size));
135 /* This can only happen if you try to free something that didn't
137 #if !defined(__linux__)
138 /* I originally wrote: "There's really no need to drop core."
139 I have seen the error of my ways. -slb */
140 if (strict_free_check)
143 printf("Freeing unmalloc'ed memory at %p\n", ptr);
144 __free_hook = check_free;
145 __malloc_hook = check_malloc;
150 /* This happens when you free twice */
151 #if !defined(__linux__)
152 /* See above comment. */
153 if (strict_free_check)
156 printf("Freeing %p twice\n", ptr);
157 __free_hook = check_free;
158 __malloc_hook = check_malloc;
162 puthash(ptr, (void *)-size, pointer_table);
164 /* Round up size to an even number of pages. */
165 rounded_up_size = ROUND_UP_TO_PAGE(size);
166 /* Protect the pages freed from all access */
167 if (strict_free_check)
168 mprotect(ptr, rounded_up_size, PROT_NONE);
170 /* Set every word in the block to 0xdeadbeef */
171 if (strict_free_check) {
172 unsigned long long_length = (size + (sizeof(long) - 1))
176 for (i = 0; i < long_length; i++)
177 ((unsigned long *)ptr)[i] = 0xdeadbeef;
180 free_queue[current_free].address = ptr;
181 free_queue[current_free].length = size;
184 if (current_free >= FREE_QUEUE_LIMIT)
186 /* Really free this if there's something there */
188 void *old = free_queue[current_free].address;
192 unsigned long old_len =
193 free_queue[current_free].length;
195 mprotect(old, old_len,
196 PROT_READ | PROT_WRITE | PROT_EXEC);
199 remhash(old, pointer_table);
203 __free_hook = check_free;
204 __malloc_hook = check_malloc;
210 static void *check_malloc(size_t size)
212 size_t rounded_up_size;
222 /* Round up to an even number of pages. */
223 rounded_up_size = ROUND_UP_TO_PAGE(size);
225 rounded_up_size = size;
227 result = malloc(rounded_up_size);
229 pointer_table = make_hash_table(FREE_QUEUE_LIMIT * 2);
230 puthash(result, (void *)size, pointer_table);
231 __free_hook = check_free;
232 __malloc_hook = check_malloc;
237 extern void *(*__realloc_hook) (void *, size_t);
242 #define MIN(A, B) ((A) < (B) ? (A) : (B))
244 /* Don't optimize realloc */
246 static void *check_realloc(void *ptr, size_t size)
250 void *result = malloc(size);
255 (EMACS_INT)gethash(ptr, pointer_table,
256 (const void **)((void*)&old_size));
258 /* This can only happen by reallocing a pointer that didn't
260 #if !defined(__linux__)
261 /* see comment in check_free(). */
264 printf("Realloc'ing unmalloc'ed pointer at %p\n", ptr);
269 memcpy(result, ptr, MIN(size, old_size));
275 void enable_strict_free_check(void);
276 void enable_strict_free_check(void)
278 strict_free_check = 1;
281 void disable_strict_free_check(void);
282 void disable_strict_free_check(void)
284 strict_free_check = 0;
287 /* Note: All BLOCK_INPUT stuff removed from this file because it's
288 completely gone in XEmacs */
290 static void *block_input_malloc(size_t size);
292 static void block_input_free(void *ptr)
297 __free_hook = block_input_free;
298 __malloc_hook = block_input_malloc;
301 static void *block_input_malloc(size_t size)
306 result = malloc(size);
307 __free_hook = block_input_free;
308 __malloc_hook = block_input_malloc;
312 static void *block_input_realloc(void *ptr, size_t size)
318 result = realloc(ptr, size);
319 __free_hook = block_input_free;
320 __malloc_hook = block_input_malloc;
321 __realloc_hook = block_input_realloc;
327 void disable_free_hook(void);
328 void disable_free_hook(void)
330 __free_hook = block_input_free;
331 __malloc_hook = block_input_malloc;
332 __realloc_hook = block_input_realloc;
335 void init_free_hook(void)
337 __free_hook = check_free;
338 __malloc_hook = check_malloc;
339 __realloc_hook = check_realloc;
341 strict_free_check = 1;
344 void really_free_one_entry(void *, int, int *);
346 DEFUN("really-free", Freally_free, 0, 1, "P", /*
347 Actually free the storage held by the free() debug hook.
348 A no-op if the free hook is disabled.
353 Lisp_Object lisp_count[2];
355 if ((__free_hook != 0) && pointer_table) {
359 maphash((maphash_function) really_free_one_entry,
360 pointer_table, (void *)&count);
361 memset(free_queue, 0,
362 sizeof(free_queue_entry) * FREE_QUEUE_LIMIT);
364 __free_hook = check_free;
365 XSETINT(lisp_count[0], count[0]);
366 XSETINT(lisp_count[1], count[1]);
367 return Fcons(lisp_count[0], lisp_count[1]);
369 return Fcons(make_int(0), make_int(0));
372 void really_free_one_entry(void *key, int contents, int *countp)
377 mprotect(key, -contents, PROT_READ | PROT_WRITE | PROT_EXEC);
379 remhash(key, pointer_table);
381 countp[1] += -contents;
385 void syms_of_free_hook(void)
387 DEFSUBR(Freally_free);
391 void (*__free_hook) (void *) = check_free;
392 void *(*__malloc_hook) (size_t) = check_malloc;
393 void *(*__realloc_hook) (void *, size_t) = check_realloc;
396 #endif /* !defined(HAVE_LIBMCHECK) */
398 #if defined(DEBUG_INPUT_BLOCKING) || defined (DEBUG_GCPRO)
400 /* Note: There is no more input blocking in XEmacs */
402 block_type, unblock_type, totally_type,
403 gcpro1_type, gcpro2_type, gcpro3_type, gcpro4_type, gcpro5_type,
407 struct block_input_history_struct {
414 typedef struct block_input_history_struct block_input_history;
416 #endif /* DEBUG_INPUT_BLOCKING || DEBUG_GCPRO */
418 #ifdef DEBUG_INPUT_BLOCKING
422 #define BLHISTLIMIT 1000
424 block_input_history blhist[BLHISTLIMIT];
426 note_block_input(char *file, int line)
428 note_block(file, line, block_type);
429 if (interrupt_input_blocked > 2)
433 note_unblock_input(char *file, int line)
435 note_block(file, line, unblock_type);
438 note_totally_unblocked(char *file, int line)
440 note_block(file, line, totally_type);
443 note_block(char *file, int line, blocktype type)
445 blhist[blhistptr].file = file;
446 blhist[blhistptr].line = line;
447 blhist[blhistptr].type = type;
448 blhist[blhistptr].value = interrupt_input_blocked;
451 if (blhistptr >= BLHISTLIMIT)
455 #endif /* DEBUG_INPUT_BLOCKING */
460 #define GCPROHISTLIMIT 1000
461 block_input_history gcprohist[GCPROHISTLIMIT];
463 static void log_gcpro(char *file, int line, struct gcpro *value, blocktype type)
465 if (type == ungcpro_type) {
466 if (value == gcprolist)
470 if (value == gcprolist->next)
472 if (!gcprolist->next)
474 if (value == gcprolist->next->next)
476 if (!gcprolist->next->next)
478 if (value == gcprolist->next->next->next)
480 if (!gcprolist->next->next->next)
482 if (value == gcprolist->next->next->next->next)
487 gcprohist[gcprohistptr].file = file;
488 gcprohist[gcprohistptr].line = line;
489 gcprohist[gcprohistptr].type = type;
490 gcprohist[gcprohistptr].value = (int)value;
492 if (gcprohistptr >= GCPROHISTLIMIT)
496 void debug_gcpro1(char *file, int line, struct gcpro *gcpro1, Lisp_Object * var)
498 gcpro1->next = gcprolist;
502 log_gcpro(file, line, gcpro1, gcpro1_type);
506 debug_gcpro2(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
507 Lisp_Object * var1, Lisp_Object * var2)
509 gcpro1->next = gcprolist;
512 gcpro2->next = gcpro1;
516 log_gcpro(file, line, gcpro2, gcpro2_type);
520 debug_gcpro3(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
521 struct gcpro *gcpro3, Lisp_Object * var1, Lisp_Object * var2,
524 gcpro1->next = gcprolist;
527 gcpro2->next = gcpro1;
530 gcpro3->next = gcpro2;
534 log_gcpro(file, line, gcpro3, gcpro3_type);
538 debug_gcpro4(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
539 struct gcpro *gcpro3, struct gcpro *gcpro4, Lisp_Object * var1,
540 Lisp_Object * var2, Lisp_Object * var3, Lisp_Object * var4)
542 log_gcpro(file, line, gcpro4, gcpro4_type);
543 gcpro1->next = gcprolist;
546 gcpro2->next = gcpro1;
549 gcpro3->next = gcpro2;
552 gcpro4->next = gcpro3;
559 debug_gcpro5(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
560 struct gcpro *gcpro3, struct gcpro *gcpro4, struct gcpro *gcpro5,
561 Lisp_Object * var1, Lisp_Object * var2, Lisp_Object * var3,
562 Lisp_Object * var4, Lisp_Object * var5)
564 log_gcpro(file, line, gcpro5, gcpro5_type);
565 gcpro1->next = gcprolist;
568 gcpro2->next = gcpro1;
571 gcpro3->next = gcpro2;
574 gcpro4->next = gcpro3;
577 gcpro5->next = gcpro4;
584 debug_gcpro6(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
585 struct gcpro *gcpro3, struct gcpro *gcpro4, struct gcpro *gcpro5,
586 struct gcpro *gcpro6,
587 Lisp_Object * var1, Lisp_Object * var2, Lisp_Object * var3,
588 Lisp_Object * var4, Lisp_Object * var5, Lisp_Object * var6)
590 log_gcpro(file, line, gcpro5, gcpro5_type);
591 gcpro1->next = gcprolist;
594 gcpro2->next = gcpro1;
597 gcpro3->next = gcpro2;
600 gcpro4->next = gcpro3;
603 gcpro5->next = gcpro4;
606 gcpro6->next = gcpro5;
613 debug_gcpro7(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
614 struct gcpro *gcpro3, struct gcpro *gcpro4, struct gcpro *gcpro5,
615 struct gcpro *gcpro6, struct gcpro *gcpro7,
616 Lisp_Object * var1, Lisp_Object * var2, Lisp_Object * var3,
617 Lisp_Object * var4, Lisp_Object * var5, Lisp_Object * var6,
620 log_gcpro(file, line, gcpro5, gcpro5_type);
621 gcpro1->next = gcprolist;
624 gcpro2->next = gcpro1;
627 gcpro3->next = gcpro2;
630 gcpro4->next = gcpro3;
633 gcpro5->next = gcpro4;
636 gcpro6->next = gcpro5;
639 gcpro7->next = gcpro6;
646 debug_gcpro8(char *file, int line, struct gcpro *gcpro1, struct gcpro *gcpro2,
647 struct gcpro *gcpro3, struct gcpro *gcpro4, struct gcpro *gcpro5,
648 struct gcpro *gcpro6, struct gcpro *gcpro7, struct gcpro *gcpro8,
649 Lisp_Object * var1, Lisp_Object * var2, Lisp_Object * var3,
650 Lisp_Object * var4, Lisp_Object * var5, Lisp_Object * var6,
651 Lisp_Object * var7, Lisp_Object * var8)
653 log_gcpro(file, line, gcpro5, gcpro5_type);
654 gcpro1->next = gcprolist;
657 gcpro2->next = gcpro1;
660 gcpro3->next = gcpro2;
663 gcpro4->next = gcpro3;
666 gcpro5->next = gcpro4;
669 gcpro6->next = gcpro5;
672 gcpro7->next = gcpro6;
675 gcpro8->next = gcpro7;
681 void debug_ungcpro(char *file, int line, struct gcpro *gcpro1)
683 log_gcpro(file, line, gcpro1, ungcpro_type);
684 gcprolist = gcpro1->next;
687 /* To be called from the debugger */
688 void show_gcprohist(void);
689 void show_gcprohist(void)
692 for (i = 0, j = gcprohistptr; i < GCPROHISTLIMIT; i++, j++) {
693 if (j >= GCPROHISTLIMIT)
695 printf("%3d %s %d %s 0x%x\n",
696 j, gcprohist[j].file, gcprohist[j].line,
697 (gcprohist[j].type ==
698 gcpro1_type ? "GCPRO1" : gcprohist[j].
700 gcpro2_type ? "GCPRO2" : gcprohist[j].
702 gcpro3_type ? "GCPRO3" : gcprohist[j].
704 gcpro4_type ? "GCPRO4" : gcprohist[j].
706 gcpro5_type ? "GCPRO5" : gcprohist[j].
708 ungcpro_type ? "UNGCPRO" : "???"), gcprohist[j].value);
713 #endif /* DEBUG_GCPRO */