1 /* More debugging hooks for `malloc'.
2 Copyright (C) 1991, 92, 93, 94, 96, 97, 98 Free Software Foundation, Inc.
3 Written April 2, 1991 by John Gilmore of Cygnus Support.
4 Based on mcheck.c by Mike Haertel.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 The author may be reached (Email) at the address mike@ai.mit.edu,
22 or (US mail) as Mike Haertel c/o Free Software Foundation. */
24 #ifndef _MALLOC_INTERNAL
25 #define _MALLOC_INTERNAL
28 #include <bits/libc-lock.h>
32 #include <elf/ldsodefs.h>
37 #ifndef __GNU_LIBRARY__
38 extern char *getenv ();
43 #if defined _LIBC && defined USE_IN_LIBIO
44 # define setvbuf(s, b, f, l) _IO_setvbuf (s, b, f, l)
47 #define TRACE_BUFFER_SIZE 512
49 static FILE *mallstream;
50 static const char mallenv[]= "MALLOC_TRACE";
51 static char malloc_trace_buffer[TRACE_BUFFER_SIZE];
53 __libc_lock_define_initialized (static, lock);
55 /* Address to breakpoint on accesses to... */
58 /* File name and line number information, for callers that had
59 the foresight to call through a macro. */
63 /* Old hook values. */
64 static void (*tr_old_free_hook) __P ((__ptr_t ptr, const __ptr_t));
65 static __ptr_t (*tr_old_malloc_hook) __P ((__malloc_size_t size,
67 static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr,
71 /* This function is called when the block being alloc'd, realloc'd, or
72 freed has an address matching the variable "mallwatch". In a debugger,
73 set "mallwatch" to the address of interest, then put a breakpoint on
76 void tr_break __P ((void));
82 static void tr_where __P ((const __ptr_t)) internal_function;
90 fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line);
93 else if (caller != NULL)
97 if (_dl_addr (caller, &info))
99 fprintf (mallstream, "@ %s%s%s%s%s[%p]",
100 info.dli_fname ?: "", info.dli_fname ? ":" : "",
101 info.dli_sname ? "(" : "",
102 info.dli_sname ?: "", info.dli_sname ? ") " : " ",
107 fprintf (mallstream, "@ [%p] ", caller);
111 static void tr_freehook __P ((__ptr_t, const __ptr_t));
113 tr_freehook (ptr, caller)
115 const __ptr_t caller;
118 /* Be sure to print it first. */
119 fprintf (mallstream, "- %p\n", ptr);
120 if (ptr == mallwatch)
122 __libc_lock_lock (lock);
123 __free_hook = tr_old_free_hook;
124 if (tr_old_free_hook != NULL)
125 (*tr_old_free_hook) (ptr, caller);
128 __free_hook = tr_freehook;
129 __libc_lock_unlock (lock);
132 static __ptr_t tr_mallochook __P ((__malloc_size_t, const __ptr_t));
134 tr_mallochook (size, caller)
135 __malloc_size_t size;
136 const __ptr_t caller;
140 __libc_lock_lock (lock);
142 __malloc_hook = tr_old_malloc_hook;
143 if (tr_old_malloc_hook != NULL)
144 hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller);
146 hdr = (__ptr_t) malloc (size);
147 __malloc_hook = tr_mallochook;
149 __libc_lock_unlock (lock);
152 /* We could be printing a NULL here; that's OK. */
153 fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
155 if (hdr == mallwatch)
161 static __ptr_t tr_reallochook __P ((__ptr_t, __malloc_size_t, const __ptr_t));
163 tr_reallochook (ptr, size, caller)
165 __malloc_size_t size;
166 const __ptr_t caller;
170 if (ptr == mallwatch)
173 __libc_lock_lock (lock);
175 __free_hook = tr_old_free_hook;
176 __malloc_hook = tr_old_malloc_hook;
177 __realloc_hook = tr_old_realloc_hook;
178 if (tr_old_realloc_hook != NULL)
179 hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller);
181 hdr = (__ptr_t) realloc (ptr, size);
182 __free_hook = tr_freehook;
183 __malloc_hook = tr_mallochook;
184 __realloc_hook = tr_reallochook;
186 __libc_lock_unlock (lock);
190 /* Failed realloc. */
191 fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
192 else if (ptr == NULL)
193 fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
195 fprintf (mallstream, "< %p\n> %p %#lx\n", ptr, hdr,
196 (unsigned long int) size);
198 if (hdr == mallwatch)
206 extern void __libc_freeres (void);
208 /* This function gets called to make sure all memory the library
209 allocates get freed and so does not irritate the user when studying
210 the mtrace output. */
212 release_libc_mem (void)
214 /* Only call the free function if we still are running in mtrace mode. */
215 if (mallstream != NULL)
221 /* We enable tracing if either the environment variable MALLOC_TRACE
222 is set, or if the variable mallwatch has been patched to an address
223 that the debugging user wants us to stop on. When patching mallwatch,
224 don't forget to set a breakpoint on tr_break! */
230 static int added_atexit_handler = 0;
234 /* Don't panic if we're called more than once. */
235 if (mallstream != NULL)
239 /* When compiling the GNU libc we use the secure getenv function
240 which prevents the misuse in case of SUID or SGID enabled
242 mallfile = __secure_getenv (mallenv);
244 mallfile = getenv (mallenv);
246 if (mallfile != NULL || mallwatch != NULL)
248 mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
249 if (mallstream != NULL)
251 /* Be sure it doesn't malloc its buffer! */
252 setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
253 fprintf (mallstream, "= Start\n");
254 tr_old_free_hook = __free_hook;
255 __free_hook = tr_freehook;
256 tr_old_malloc_hook = __malloc_hook;
257 __malloc_hook = tr_mallochook;
258 tr_old_realloc_hook = __realloc_hook;
259 __realloc_hook = tr_reallochook;
261 if (!added_atexit_handler)
263 added_atexit_handler = 1;
264 atexit (release_libc_mem);
274 if (mallstream == NULL)
277 fprintf (mallstream, "= End\n");
280 __free_hook = tr_old_free_hook;
281 __malloc_hook = tr_old_malloc_hook;
282 __realloc_hook = tr_old_realloc_hook;