1 /* More debugging hooks for `malloc'.
2 Copyright (C) 1991-1994,1996-2003, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Written April 2, 1991 by John Gilmore of Cygnus Support.
5 Based on mcheck.c by Mike Haertel.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #ifndef _MALLOC_INTERNAL
23 #define _MALLOC_INTERNAL
26 #include <bits/libc-lock.h>
35 #include <stdio-common/_itoa.h>
38 # include <libc-internal.h>
40 # include <libio/iolibio.h>
41 # define setvbuf(s, b, f, l) INTUSE(_IO_setvbuf) (s, b, f, l)
42 # define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
43 extern __typeof (malloc
) __libc_malloc
;
44 extern __typeof (free
) __libc_free
;
45 extern __typeof (realloc
) __libc_realloc
;
46 libc_hidden_proto (__libc_malloc
)
47 libc_hidden_proto (__libc_realloc
)
48 libc_hidden_proto (__libc_free
)
49 libc_hidden_proto (__libc_memalign
)
51 # define __libc_malloc(sz) malloc (sz)
52 # define __libc_free(ptr) free (ptr)
53 # define __libc_realloc(ptr, sz) realloc (ptr, sz)
54 # define __libc_memalign(al, sz) memalign (al, sz)
57 #ifndef attribute_hidden
58 # define attribute_hidden
61 #define TRACE_BUFFER_SIZE 512
63 static FILE *mallstream
;
64 static const char mallenv
[]= "MALLOC_TRACE";
65 static char *malloc_trace_buffer
;
67 __libc_lock_define_initialized (static, lock
);
69 /* Address to breakpoint on accesses to... */
72 #ifdef USE_MTRACE_FILE
73 /* File name and line number information, for callers that had
74 the foresight to call through a macro. */
79 /* Old hook values. */
80 static void (*tr_old_free_hook
) (__ptr_t ptr
, const __ptr_t
);
81 static __ptr_t (*tr_old_malloc_hook
) (__malloc_size_t size
, const __ptr_t
);
82 static __ptr_t (*tr_old_realloc_hook
) (__ptr_t ptr
, __malloc_size_t size
,
84 static __ptr_t (*tr_old_memalign_hook
) (__malloc_size_t __alignment
,
85 __malloc_size_t __size
,
88 /* This function is called when the block being alloc'd, realloc'd, or
89 freed has an address matching the variable "mallwatch". In a debugger,
90 set "mallwatch" to the address of interest, then put a breakpoint on
93 extern void tr_break (void) __THROW
;
94 libc_hidden_proto (tr_break
)
99 libc_hidden_def (tr_break
)
101 static void tr_where (const __ptr_t
) __THROW internal_function
;
105 const __ptr_t caller
;
107 #ifdef USE_MTRACE_FILE
110 fprintf (mallstream
, "@ %s:%d ", _mtrace_file
, _mtrace_line
);
119 if (_dl_addr (caller
, &info
, NULL
, NULL
))
121 char *buf
= (char *) "";
122 if (info
.dli_sname
!= NULL
)
124 size_t len
= strlen (info
.dli_sname
);
125 buf
= alloca (len
+ 6 + 2 * sizeof (void *));
128 __stpcpy (_fitoa (caller
>= (const __ptr_t
) info
.dli_saddr
129 ? caller
- (const __ptr_t
) info
.dli_saddr
130 : (const __ptr_t
) info
.dli_saddr
- caller
,
131 __stpcpy (__mempcpy (buf
+ 1, info
.dli_sname
,
133 caller
>= (__ptr_t
) info
.dli_saddr
139 fprintf (mallstream
, "@ %s%s%s[%p] ",
140 info
.dli_fname
?: "", info
.dli_fname
? ":" : "",
145 fprintf (mallstream
, "@ [%p] ", caller
);
149 static void tr_freehook (__ptr_t
, const __ptr_t
) __THROW
;
151 tr_freehook (ptr
, caller
)
153 const __ptr_t caller
;
157 __libc_lock_lock (lock
);
159 /* Be sure to print it first. */
160 fprintf (mallstream
, "- %p\n", ptr
);
161 __libc_lock_unlock (lock
);
162 if (ptr
== mallwatch
)
164 __libc_lock_lock (lock
);
165 __free_hook
= tr_old_free_hook
;
166 if (tr_old_free_hook
!= NULL
)
167 (*tr_old_free_hook
) (ptr
, caller
);
170 __free_hook
= tr_freehook
;
171 __libc_lock_unlock (lock
);
174 static __ptr_t
tr_mallochook (__malloc_size_t
, const __ptr_t
) __THROW
;
176 tr_mallochook (size
, caller
)
177 __malloc_size_t size
;
178 const __ptr_t caller
;
182 __libc_lock_lock (lock
);
184 __malloc_hook
= tr_old_malloc_hook
;
185 if (tr_old_malloc_hook
!= NULL
)
186 hdr
= (__ptr_t
) (*tr_old_malloc_hook
) (size
, caller
);
188 hdr
= (__ptr_t
) __libc_malloc (size
);
189 __malloc_hook
= tr_mallochook
;
192 /* We could be printing a NULL here; that's OK. */
193 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
195 __libc_lock_unlock (lock
);
197 if (hdr
== mallwatch
)
203 static __ptr_t
tr_reallochook (__ptr_t
, __malloc_size_t
, const __ptr_t
)
206 tr_reallochook (ptr
, size
, caller
)
208 __malloc_size_t size
;
209 const __ptr_t caller
;
213 if (ptr
== mallwatch
)
216 __libc_lock_lock (lock
);
218 __free_hook
= tr_old_free_hook
;
219 __malloc_hook
= tr_old_malloc_hook
;
220 __realloc_hook
= tr_old_realloc_hook
;
221 if (tr_old_realloc_hook
!= NULL
)
222 hdr
= (__ptr_t
) (*tr_old_realloc_hook
) (ptr
, size
, caller
);
224 hdr
= (__ptr_t
) __libc_realloc (ptr
, size
);
225 __free_hook
= tr_freehook
;
226 __malloc_hook
= tr_mallochook
;
227 __realloc_hook
= tr_reallochook
;
231 /* Failed realloc. */
232 fprintf (mallstream
, "! %p %#lx\n", ptr
, (unsigned long int) size
);
233 else if (ptr
== NULL
)
234 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
237 fprintf (mallstream
, "< %p\n", ptr
);
239 fprintf (mallstream
, "> %p %#lx\n", hdr
, (unsigned long int) size
);
242 __libc_lock_unlock (lock
);
244 if (hdr
== mallwatch
)
250 static __ptr_t
tr_memalignhook (__malloc_size_t
, __malloc_size_t
,
251 const __ptr_t
) __THROW
;
253 tr_memalignhook (alignment
, size
, caller
)
254 __malloc_size_t alignment
, size
;
255 const __ptr_t caller
;
259 __libc_lock_lock (lock
);
261 __memalign_hook
= tr_old_memalign_hook
;
262 __malloc_hook
= tr_old_malloc_hook
;
263 if (tr_old_memalign_hook
!= NULL
)
264 hdr
= (__ptr_t
) (*tr_old_memalign_hook
) (alignment
, size
, caller
);
266 hdr
= (__ptr_t
) __libc_memalign (alignment
, size
);
267 __memalign_hook
= tr_memalignhook
;
268 __malloc_hook
= tr_mallochook
;
271 /* We could be printing a NULL here; that's OK. */
272 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
274 __libc_lock_unlock (lock
);
276 if (hdr
== mallwatch
)
286 /* This function gets called to make sure all memory the library
287 allocates get freed and so does not irritate the user when studying
288 the mtrace output. */
289 static void __libc_freeres_fn_section
290 release_libc_mem (void)
292 /* Only call the free function if we still are running in mtrace mode. */
293 if (mallstream
!= NULL
)
299 /* We enable tracing if either the environment variable MALLOC_TRACE
300 is set, or if the variable mallwatch has been patched to an address
301 that the debugging user wants us to stop on. When patching mallwatch,
302 don't forget to set a breakpoint on tr_break! */
308 static int added_atexit_handler
;
312 /* Don't panic if we're called more than once. */
313 if (mallstream
!= NULL
)
317 /* When compiling the GNU libc we use the secure getenv function
318 which prevents the misuse in case of SUID or SGID enabled
320 mallfile
= __secure_getenv (mallenv
);
322 mallfile
= getenv (mallenv
);
324 if (mallfile
!= NULL
|| mallwatch
!= NULL
)
326 char *mtb
= malloc (TRACE_BUFFER_SIZE
);
330 mallstream
= fopen (mallfile
!= NULL
? mallfile
: "/dev/null", "wc");
331 if (mallstream
!= NULL
)
333 /* Make sure we close the file descriptor on exec. */
334 int flags
= __fcntl (fileno (mallstream
), F_GETFD
, 0);
338 __fcntl (fileno (mallstream
), F_SETFD
, flags
);
340 /* Be sure it doesn't malloc its buffer! */
341 malloc_trace_buffer
= mtb
;
342 setvbuf (mallstream
, malloc_trace_buffer
, _IOFBF
, TRACE_BUFFER_SIZE
);
343 fprintf (mallstream
, "= Start\n");
344 tr_old_free_hook
= __free_hook
;
345 __free_hook
= tr_freehook
;
346 tr_old_malloc_hook
= __malloc_hook
;
347 __malloc_hook
= tr_mallochook
;
348 tr_old_realloc_hook
= __realloc_hook
;
349 __realloc_hook
= tr_reallochook
;
350 tr_old_memalign_hook
= __memalign_hook
;
351 __memalign_hook
= tr_memalignhook
;
353 if (!added_atexit_handler
)
355 extern void *__dso_handle
__attribute__ ((__weak__
));
356 added_atexit_handler
= 1;
357 __cxa_atexit ((void (*) (void *)) release_libc_mem
, NULL
,
358 &__dso_handle
? __dso_handle
: NULL
);
370 if (mallstream
== NULL
)
373 fprintf (mallstream
, "= End\n");
376 __free_hook
= tr_old_free_hook
;
377 __malloc_hook
= tr_old_malloc_hook
;
378 __realloc_hook
= tr_old_realloc_hook
;
379 __memalign_hook
= tr_old_memalign_hook
;