1 /* More debugging hooks for `malloc'.
2 Copyright (C) 1991-1994,1996-2004, 2008 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>
37 #include <libc-internal.h>
39 #include <libio/iolibio.h>
40 #define setvbuf(s, b, f, l) INTUSE(_IO_setvbuf) (s, b, f, l)
41 #define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
43 #include <kernel-features.h>
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
) (__ptr_t ptr
, const __ptr_t
);
69 static __ptr_t (*tr_old_malloc_hook
) (__malloc_size_t size
, const __ptr_t
);
70 static __ptr_t (*tr_old_realloc_hook
) (__ptr_t ptr
, __malloc_size_t size
,
72 static __ptr_t (*tr_old_memalign_hook
) (__malloc_size_t __alignment
,
73 __malloc_size_t __size
,
76 /* This function is called when the block being alloc'd, realloc'd, or
77 freed has an address matching the variable "mallwatch". In a debugger,
78 set "mallwatch" to the address of interest, then put a breakpoint on
81 extern void tr_break (void) __THROW
;
82 libc_hidden_proto (tr_break
)
87 libc_hidden_def (tr_break
)
89 static void tr_where (const __ptr_t
) __THROW internal_function
;
95 #ifdef USE_MTRACE_FILE
98 fprintf (mallstream
, "@ %s:%d ", _mtrace_file
, _mtrace_line
);
107 if (_dl_addr (caller
, &info
, NULL
, NULL
))
109 char *buf
= (char *) "";
110 if (info
.dli_sname
!= NULL
)
112 size_t len
= strlen (info
.dli_sname
);
113 buf
= alloca (len
+ 6 + 2 * sizeof (void *));
116 __stpcpy (_fitoa (caller
>= (const __ptr_t
) info
.dli_saddr
117 ? caller
- (const __ptr_t
) info
.dli_saddr
118 : (const __ptr_t
) info
.dli_saddr
- caller
,
119 __stpcpy (__mempcpy (buf
+ 1, info
.dli_sname
,
121 caller
>= (__ptr_t
) info
.dli_saddr
127 fprintf (mallstream
, "@ %s%s%s[%p] ",
128 info
.dli_fname
?: "", info
.dli_fname
? ":" : "",
133 fprintf (mallstream
, "@ [%p] ", caller
);
137 static void tr_freehook (__ptr_t
, const __ptr_t
) __THROW
;
139 tr_freehook (ptr
, caller
)
141 const __ptr_t caller
;
145 __libc_lock_lock (lock
);
147 /* Be sure to print it first. */
148 fprintf (mallstream
, "- %p\n", ptr
);
149 __libc_lock_unlock (lock
);
150 if (ptr
== mallwatch
)
152 __libc_lock_lock (lock
);
153 __free_hook
= tr_old_free_hook
;
154 if (tr_old_free_hook
!= NULL
)
155 (*tr_old_free_hook
) (ptr
, caller
);
158 __free_hook
= tr_freehook
;
159 __libc_lock_unlock (lock
);
162 static __ptr_t
tr_mallochook (__malloc_size_t
, const __ptr_t
) __THROW
;
164 tr_mallochook (size
, caller
)
165 __malloc_size_t size
;
166 const __ptr_t caller
;
170 __libc_lock_lock (lock
);
172 __malloc_hook
= tr_old_malloc_hook
;
173 if (tr_old_malloc_hook
!= NULL
)
174 hdr
= (__ptr_t
) (*tr_old_malloc_hook
) (size
, caller
);
176 hdr
= (__ptr_t
) malloc (size
);
177 __malloc_hook
= tr_mallochook
;
180 /* We could be printing a NULL here; that's OK. */
181 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
183 __libc_lock_unlock (lock
);
185 if (hdr
== mallwatch
)
191 static __ptr_t
tr_reallochook (__ptr_t
, __malloc_size_t
, const __ptr_t
)
194 tr_reallochook (ptr
, size
, caller
)
196 __malloc_size_t size
;
197 const __ptr_t caller
;
201 if (ptr
== mallwatch
)
204 __libc_lock_lock (lock
);
206 __free_hook
= tr_old_free_hook
;
207 __malloc_hook
= tr_old_malloc_hook
;
208 __realloc_hook
= tr_old_realloc_hook
;
209 if (tr_old_realloc_hook
!= NULL
)
210 hdr
= (__ptr_t
) (*tr_old_realloc_hook
) (ptr
, size
, caller
);
212 hdr
= (__ptr_t
) realloc (ptr
, size
);
213 __free_hook
= tr_freehook
;
214 __malloc_hook
= tr_mallochook
;
215 __realloc_hook
= tr_reallochook
;
219 /* Failed realloc. */
220 fprintf (mallstream
, "! %p %#lx\n", ptr
, (unsigned long int) size
);
221 else if (ptr
== NULL
)
222 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
225 fprintf (mallstream
, "< %p\n", ptr
);
227 fprintf (mallstream
, "> %p %#lx\n", hdr
, (unsigned long int) size
);
230 __libc_lock_unlock (lock
);
232 if (hdr
== mallwatch
)
238 static __ptr_t
tr_memalignhook (__malloc_size_t
, __malloc_size_t
,
239 const __ptr_t
) __THROW
;
241 tr_memalignhook (alignment
, size
, caller
)
242 __malloc_size_t alignment
, size
;
243 const __ptr_t caller
;
247 __libc_lock_lock (lock
);
249 __memalign_hook
= tr_old_memalign_hook
;
250 __malloc_hook
= tr_old_malloc_hook
;
251 if (tr_old_memalign_hook
!= NULL
)
252 hdr
= (__ptr_t
) (*tr_old_memalign_hook
) (alignment
, size
, caller
);
254 hdr
= (__ptr_t
) memalign (alignment
, size
);
255 __memalign_hook
= tr_memalignhook
;
256 __malloc_hook
= tr_mallochook
;
259 /* We could be printing a NULL here; that's OK. */
260 fprintf (mallstream
, "+ %p %#lx\n", hdr
, (unsigned long int) size
);
262 __libc_lock_unlock (lock
);
264 if (hdr
== mallwatch
)
274 /* This function gets called to make sure all memory the library
275 allocates get freed and so does not irritate the user when studying
276 the mtrace output. */
277 static void __libc_freeres_fn_section
278 release_libc_mem (void)
280 /* Only call the free function if we still are running in mtrace mode. */
281 if (mallstream
!= NULL
)
287 /* We enable tracing if either the environment variable MALLOC_TRACE
288 is set, or if the variable mallwatch has been patched to an address
289 that the debugging user wants us to stop on. When patching mallwatch,
290 don't forget to set a breakpoint on tr_break! */
296 static int added_atexit_handler
;
300 /* Don't panic if we're called more than once. */
301 if (mallstream
!= NULL
)
305 /* When compiling the GNU libc we use the secure getenv function
306 which prevents the misuse in case of SUID or SGID enabled
308 mallfile
= __secure_getenv (mallenv
);
310 mallfile
= getenv (mallenv
);
312 if (mallfile
!= NULL
|| mallwatch
!= NULL
)
314 char *mtb
= malloc (TRACE_BUFFER_SIZE
);
318 mallstream
= fopen (mallfile
!= NULL
? mallfile
: "/dev/null", "wce");
319 if (mallstream
!= NULL
)
321 #ifndef __ASSUME_O_CLOEXEC
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
);
330 /* Be sure it doesn't malloc its buffer! */
331 malloc_trace_buffer
= mtb
;
332 setvbuf (mallstream
, malloc_trace_buffer
, _IOFBF
, TRACE_BUFFER_SIZE
);
333 fprintf (mallstream
, "= Start\n");
334 tr_old_free_hook
= __free_hook
;
335 __free_hook
= tr_freehook
;
336 tr_old_malloc_hook
= __malloc_hook
;
337 __malloc_hook
= tr_mallochook
;
338 tr_old_realloc_hook
= __realloc_hook
;
339 __realloc_hook
= tr_reallochook
;
340 tr_old_memalign_hook
= __memalign_hook
;
341 __memalign_hook
= tr_memalignhook
;
343 if (!added_atexit_handler
)
345 extern void *__dso_handle
__attribute__ ((__weak__
));
346 added_atexit_handler
= 1;
347 __cxa_atexit ((void (*) (void *)) release_libc_mem
, NULL
,
348 &__dso_handle
? __dso_handle
: NULL
);
360 if (mallstream
== NULL
)
363 fprintf (mallstream
, "= End\n");
366 __free_hook
= tr_old_free_hook
;
367 __malloc_hook
= tr_old_malloc_hook
;
368 __realloc_hook
= tr_old_realloc_hook
;
369 __memalign_hook
= tr_old_memalign_hook
;