1 /* More debugging hooks for `malloc'.
2 Copyright (C) 1991-1994,1996-2001,2002, 2003 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)
45 #ifndef attribute_hidden
46 # define attribute_hidden
49 #define TRACE_BUFFER_SIZE 512
51 static FILE *mallstream
;
52 static const char mallenv
[]= "MALLOC_TRACE";
53 static char *malloc_trace_buffer
;
55 __libc_lock_define_initialized (static, lock
);
57 /* Address to breakpoint on accesses to... */
60 #ifdef USE_MTRACE_FILE
61 /* File name and line number information, for callers that had
62 the foresight to call through a macro. */
67 /* Old hook values. */
68 static void (*tr_old_free_hook
) __P ((__ptr_t ptr
, const __ptr_t
));
69 static __ptr_t (*tr_old_malloc_hook
) __P ((__malloc_size_t size
,
71 static __ptr_t (*tr_old_realloc_hook
) __P ((__ptr_t ptr
,
74 static __ptr_t (*tr_old_memalign_hook
) __P ((__malloc_size_t __alignment
,
75 __malloc_size_t __size
,
78 /* This function is called when the block being alloc'd, realloc'd, or
79 freed has an address matching the variable "mallwatch". In a debugger,
80 set "mallwatch" to the address of interest, then put a breakpoint on
83 extern void tr_break
__P ((void));
84 libc_hidden_proto (tr_break
)
89 libc_hidden_def (tr_break
)
91 static void tr_where
__P ((const __ptr_t
)) internal_function
;
97 #ifdef USE_MTRACE_FILE
100 fprintf (mallstream
, "@ %s:%d ", _mtrace_file
, _mtrace_line
);
109 if (_dl_addr (caller
, &info
, NULL
, NULL
))
111 char *buf
= (char *) "";
112 if (info
.dli_sname
!= NULL
)
114 size_t len
= strlen (info
.dli_sname
);
115 buf
= alloca (len
+ 6 + 2 * sizeof (void *));
118 __stpcpy (_fitoa (caller
>= (const __ptr_t
) info
.dli_saddr
119 ? caller
- (const __ptr_t
) info
.dli_saddr
120 : (const __ptr_t
) info
.dli_saddr
- caller
,
121 __stpcpy (__mempcpy (buf
+ 1, info
.dli_sname
,
123 caller
>= (__ptr_t
) info
.dli_saddr
129 fprintf (mallstream
, "@ %s%s%s[%p] ",
130 info
.dli_fname
?: "", info
.dli_fname
? ":" : "",
135 fprintf (mallstream
, "@ [%p] ", caller
);
139 static void tr_freehook
__P ((__ptr_t
, const __ptr_t
));
141 tr_freehook (ptr
, caller
)
143 const __ptr_t caller
;
147 __libc_lock_lock (lock
);
149 /* Be sure to print it first. */
150 fprintf (mallstream
, "- %p\n", ptr
);
151 __libc_lock_unlock (lock
);
152 if (ptr
== mallwatch
)
154 __libc_lock_lock (lock
);
155 __free_hook
= tr_old_free_hook
;
156 if (tr_old_free_hook
!= NULL
)
157 (*tr_old_free_hook
) (ptr
, caller
);
160 __free_hook
= tr_freehook
;
161 __libc_lock_unlock (lock
);
164 static __ptr_t tr_mallochook
__P ((__malloc_size_t
, const __ptr_t
));
166 tr_mallochook (size
, caller
)
167 __malloc_size_t size
;
168 const __ptr_t caller
;
172 __libc_lock_lock (lock
);
174 __malloc_hook
= tr_old_malloc_hook
;
175 if (tr_old_malloc_hook
!= NULL
)
176 hdr
= (__ptr_t
) (*tr_old_malloc_hook
) (size
, caller
);
178 hdr
= (__ptr_t
) malloc (size
);
179 __malloc_hook
= tr_mallochook
;
182 /* We could be printing a NULL here; that's OK. */
183 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
185 __libc_lock_unlock (lock
);
187 if (hdr
== mallwatch
)
193 static __ptr_t tr_reallochook
__P ((__ptr_t
, __malloc_size_t
, const __ptr_t
));
195 tr_reallochook (ptr
, size
, caller
)
197 __malloc_size_t size
;
198 const __ptr_t caller
;
202 if (ptr
== mallwatch
)
205 __libc_lock_lock (lock
);
207 __free_hook
= tr_old_free_hook
;
208 __malloc_hook
= tr_old_malloc_hook
;
209 __realloc_hook
= tr_old_realloc_hook
;
210 if (tr_old_realloc_hook
!= NULL
)
211 hdr
= (__ptr_t
) (*tr_old_realloc_hook
) (ptr
, size
, caller
);
213 hdr
= (__ptr_t
) realloc (ptr
, size
);
214 __free_hook
= tr_freehook
;
215 __malloc_hook
= tr_mallochook
;
216 __realloc_hook
= tr_reallochook
;
220 /* Failed realloc. */
221 fprintf (mallstream
, "! %p %#lx\n", ptr
, (unsigned long int) size
);
222 else if (ptr
== NULL
)
223 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
226 fprintf (mallstream
, "< %p\n", ptr
);
228 fprintf (mallstream
, "> %p %#lx\n", hdr
, (unsigned long int) size
);
231 __libc_lock_unlock (lock
);
233 if (hdr
== mallwatch
)
239 static __ptr_t tr_memalignhook
__P ((__malloc_size_t
, __malloc_size_t
,
242 tr_memalignhook (alignment
, size
, caller
)
243 __malloc_size_t alignment
, size
;
244 const __ptr_t caller
;
248 __libc_lock_lock (lock
);
250 __memalign_hook
= tr_old_memalign_hook
;
251 __malloc_hook
= tr_old_malloc_hook
;
252 if (tr_old_memalign_hook
!= NULL
)
253 hdr
= (__ptr_t
) (*tr_old_memalign_hook
) (alignment
, size
, caller
);
255 hdr
= (__ptr_t
) memalign (alignment
, size
);
256 __memalign_hook
= tr_memalignhook
;
257 __malloc_hook
= tr_mallochook
;
260 /* We could be printing a NULL here; that's OK. */
261 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
263 __libc_lock_unlock (lock
);
265 if (hdr
== mallwatch
)
275 /* This function gets called to make sure all memory the library
276 allocates get freed and so does not irritate the user when studying
277 the mtrace output. */
278 static void __libc_freeres_fn_section
279 release_libc_mem (void)
281 /* Only call the free function if we still are running in mtrace mode. */
282 if (mallstream
!= NULL
)
288 /* We enable tracing if either the environment variable MALLOC_TRACE
289 is set, or if the variable mallwatch has been patched to an address
290 that the debugging user wants us to stop on. When patching mallwatch,
291 don't forget to set a breakpoint on tr_break! */
297 static int added_atexit_handler
;
301 /* Don't panic if we're called more than once. */
302 if (mallstream
!= NULL
)
306 /* When compiling the GNU libc we use the secure getenv function
307 which prevents the misuse in case of SUID or SGID enabled
309 mallfile
= __secure_getenv (mallenv
);
311 mallfile
= getenv (mallenv
);
313 if (mallfile
!= NULL
|| mallwatch
!= NULL
)
315 char *mtb
= malloc (TRACE_BUFFER_SIZE
);
319 mallstream
= fopen (mallfile
!= NULL
? mallfile
: "/dev/null", "wc");
320 if (mallstream
!= NULL
)
322 /* Make sure we close the file descriptor on exec. */
323 int flags
= __fcntl (fileno (mallstream
), F_GETFD
, 0);
327 __fcntl (fileno (mallstream
), F_SETFD
, flags
);
329 /* Be sure it doesn't malloc its buffer! */
330 malloc_trace_buffer
= mtb
;
331 setvbuf (mallstream
, malloc_trace_buffer
, _IOFBF
, TRACE_BUFFER_SIZE
);
332 fprintf (mallstream
, "= Start\n");
333 tr_old_free_hook
= __free_hook
;
334 __free_hook
= tr_freehook
;
335 tr_old_malloc_hook
= __malloc_hook
;
336 __malloc_hook
= tr_mallochook
;
337 tr_old_realloc_hook
= __realloc_hook
;
338 __realloc_hook
= tr_reallochook
;
339 tr_old_memalign_hook
= __memalign_hook
;
340 __memalign_hook
= tr_memalignhook
;
342 if (!added_atexit_handler
)
344 extern void *__dso_handle
__attribute__ ((__weak__
));
345 added_atexit_handler
= 1;
346 __cxa_atexit ((void (*) (void *)) release_libc_mem
, NULL
,
347 &__dso_handle
? __dso_handle
: NULL
);
359 if (mallstream
== NULL
)
362 fprintf (mallstream
, "= End\n");
365 __free_hook
= tr_old_free_hook
;
366 __malloc_hook
= tr_old_malloc_hook
;
367 __realloc_hook
= tr_old_realloc_hook
;
368 __memalign_hook
= tr_old_memalign_hook
;