mtrace.c revision 1.1
1/* $NetBSD: mtrace.c,v 1.1 2016/01/13 21:42:18 christos Exp $ */ 2 3/* More debugging hooks for `malloc'. 4 Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. 5 Written April 2, 1991 by John Gilmore of Cygnus Support. 6 Based on mcheck.c by Mike Haertel. 7 8This library is free software; you can redistribute it and/or 9modify it under the terms of the GNU Library General Public License as 10published by the Free Software Foundation; either version 2 of the 11License, or (at your option) any later version. 12 13This library is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16Library General Public License for more details. 17 18You should have received a copy of the GNU Library General Public 19License along with this library; see the file COPYING.LIB. If 20not, write to the Free Software Foundation, Inc., 675 Mass Ave, 21Cambridge, MA 02139, USA. 22 23 The author may be reached (Email) at the address mike@ai.mit.edu, 24 or (US mail) as Mike Haertel c/o Free Software Foundation. */ 25 26#ifndef _MALLOC_INTERNAL 27#define _MALLOC_INTERNAL 28#include <malloc.h> 29#endif 30 31#include <stdio.h> 32 33#ifndef __GNU_LIBRARY__ 34extern char *getenv (); 35#else 36#include <stdlib.h> 37#endif 38 39static FILE *mallstream; 40static char mallenv[]= "MALLOC_TRACE"; 41static char mallbuf[BUFSIZ]; /* Buffer for the output. */ 42 43/* Address to breakpoint on accesses to... */ 44__ptr_t mallwatch; 45 46/* File name and line number information, for callers that had 47 the foresight to call through a macro. */ 48char *_mtrace_file; 49int _mtrace_line; 50 51/* Old hook values. */ 52static void (*tr_old_free_hook) __P ((__ptr_t ptr)); 53static __ptr_t (*tr_old_malloc_hook) __P ((__malloc_size_t size)); 54static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size)); 55 56/* This function is called when the block being alloc'd, realloc'd, or 57 freed has an address matching the variable "mallwatch". In a debugger, 58 set "mallwatch" to the address of interest, then put a breakpoint on 59 tr_break. */ 60 61void tr_break __P ((void)); 62void 63tr_break () 64{ 65} 66 67static void tr_where __P ((void)); 68static void 69tr_where () 70{ 71 if (_mtrace_file) 72 { 73 fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line); 74 _mtrace_file = NULL; 75 } 76} 77 78static void tr_freehook __P ((__ptr_t)); 79static void 80tr_freehook (ptr) 81 __ptr_t ptr; 82{ 83 tr_where (); 84 fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */ 85 if (ptr == mallwatch) 86 tr_break (); 87 __free_hook = tr_old_free_hook; 88 free (ptr); 89 __free_hook = tr_freehook; 90} 91 92static __ptr_t tr_mallochook __P ((__malloc_size_t)); 93static __ptr_t 94tr_mallochook (size) 95 __malloc_size_t size; 96{ 97 __ptr_t hdr; 98 99 __malloc_hook = tr_old_malloc_hook; 100 hdr = (__ptr_t) malloc (size); 101 __malloc_hook = tr_mallochook; 102 103 tr_where (); 104 /* We could be printing a NULL here; that's OK. */ 105 fprintf (mallstream, "+ %p %lx\n", hdr, (unsigned long)size); 106 107 if (hdr == mallwatch) 108 tr_break (); 109 110 return hdr; 111} 112 113static __ptr_t tr_reallochook __P ((__ptr_t, __malloc_size_t)); 114static __ptr_t 115tr_reallochook (ptr, size) 116 __ptr_t ptr; 117 __malloc_size_t size; 118{ 119 __ptr_t hdr; 120 121 if (ptr == mallwatch) 122 tr_break (); 123 124 __free_hook = tr_old_free_hook; 125 __malloc_hook = tr_old_malloc_hook; 126 __realloc_hook = tr_old_realloc_hook; 127 hdr = (__ptr_t) realloc (ptr, size); 128 __free_hook = tr_freehook; 129 __malloc_hook = tr_mallochook; 130 __realloc_hook = tr_reallochook; 131 tr_where (); 132 if (hdr == NULL) 133 /* Failed realloc. */ 134 fprintf (mallstream, "! %p %lx\n", ptr, (unsigned long)size); 135 else 136 fprintf (mallstream, "< %p\n> %p %lx\n", ptr, hdr, (unsigned long)size); 137 138 if (hdr == mallwatch) 139 tr_break (); 140 141 return hdr; 142} 143 144/* We enable tracing if either the environment variable MALLOC_TRACE 145 is set, or if the variable mallwatch has been patched to an address 146 that the debugging user wants us to stop on. When patching mallwatch, 147 don't forget to set a breakpoint on tr_break! */ 148 149void 150mtrace () 151{ 152 char *mallfile; 153 154 /* Don't panic if we're called more than once. */ 155 if (mallstream != NULL) 156 return; 157 158 mallfile = getenv (mallenv); 159 if (mallfile != NULL || mallwatch != NULL) 160 { 161 mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w"); 162 if (mallstream != NULL) 163 { 164 /* Be sure it doesn't malloc its buffer! */ 165 setbuf (mallstream, mallbuf); 166 fprintf (mallstream, "= Start\n"); 167 tr_old_free_hook = __free_hook; 168 __free_hook = tr_freehook; 169 tr_old_malloc_hook = __malloc_hook; 170 __malloc_hook = tr_mallochook; 171 tr_old_realloc_hook = __realloc_hook; 172 __realloc_hook = tr_reallochook; 173 } 174 } 175} 176 177void 178muntrace () 179{ 180 if (mallstream == NULL) 181 return; 182 183 fprintf (mallstream, "= End\n"); 184 fclose (mallstream); 185 mallstream = NULL; 186 __free_hook = tr_old_free_hook; 187 __malloc_hook = tr_old_malloc_hook; 188 __realloc_hook = tr_old_realloc_hook; 189} 190