1 /* mtrace implementation for `malloc'.
2 Copyright (C) 1991-2021 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, see
19 <https://www.gnu.org/licenses/>. */
32 #include <libc-internal.h>
33 #include <dso_handle.h>
35 #include <kernel-features.h>
37 #define TRACE_BUFFER_SIZE 512
39 static FILE *mallstream
;
40 static const char mallenv
[] = "MALLOC_TRACE";
41 static char *malloc_trace_buffer
;
44 tr_where (const void *caller
, Dl_info
*info
)
50 char *buf
= (char *) "";
51 if (info
->dli_sname
!= NULL
)
53 size_t len
= strlen (info
->dli_sname
);
54 buf
= alloca (len
+ 6 + 2 * sizeof (void *));
57 (ptrdiff_t) info
->dli_saddr
- (ptrdiff_t) caller
;
59 if (caller
>= (const void *) info
->dli_saddr
)
67 sprintf (buf
, "(%s%c%" PRIxPTR
")", info
->dli_sname
, sign
,
71 fprintf (mallstream
, "@ %s%s%s[%p] ", info
->dli_fname
? : "",
72 info
->dli_fname
? ":" : "",
76 fprintf (mallstream
, "@ [%p] ", caller
);
81 lock_and_info (const void *caller
, Dl_info
*mem
)
86 Dl_info
*res
= dladdr (caller
, mem
) ? mem
: NULL
;
88 flockfile (mallstream
);
94 free_mtrace (void *ptr
, const void *caller
)
100 Dl_info
*info
= lock_and_info (caller
, &mem
);
101 tr_where (caller
, info
);
102 /* Be sure to print it first. */
103 fprintf (mallstream
, "- %p\n", ptr
);
104 funlockfile (mallstream
);
108 malloc_mtrace_after (void *block
, size_t size
, const void *caller
)
111 Dl_info
*info
= lock_and_info (caller
, &mem
);
113 tr_where (caller
, info
);
114 /* We could be printing a NULL here; that's OK. */
115 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
117 funlockfile (mallstream
);
121 realloc_mtrace_after (void *block
, const void *oldptr
, size_t size
,
125 Dl_info
*info
= lock_and_info (caller
, &mem
);
127 tr_where (caller
, info
);
131 /* Failed realloc. */
132 fprintf (mallstream
, "! %p %#lx\n", oldptr
, (unsigned long int) size
);
134 fprintf (mallstream
, "- %p\n", oldptr
);
136 else if (oldptr
== NULL
)
137 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
140 fprintf (mallstream
, "< %p\n", oldptr
);
141 tr_where (caller
, info
);
142 fprintf (mallstream
, "> %p %#lx\n", block
, (unsigned long int) size
);
145 funlockfile (mallstream
);
149 memalign_mtrace_after (void *block
, size_t size
, const void *caller
)
152 Dl_info
*info
= lock_and_info (caller
, &mem
);
154 tr_where (caller
, info
);
155 /* We could be printing a NULL here; that's OK. */
156 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
158 funlockfile (mallstream
);
161 /* This function gets called to make sure all memory the library
162 allocates get freed and so does not irritate the user when studying
163 the mtrace output. */
165 release_libc_mem (void)
167 /* Only call the free function if we still are running in mtrace mode. */
168 if (mallstream
!= NULL
)
172 /* We enable tracing if the environment variable MALLOC_TRACE is set. */
177 static int added_atexit_handler
;
180 /* Don't panic if we're called more than once. */
181 if (mallstream
!= NULL
)
184 mallfile
= secure_getenv (mallenv
);
185 if (mallfile
!= NULL
)
187 char *mtb
= malloc (TRACE_BUFFER_SIZE
);
191 mallstream
= fopen (mallfile
!= NULL
? mallfile
: "/dev/null", "wce");
192 if (mallstream
!= NULL
)
194 /* Be sure it doesn't malloc its buffer! */
195 malloc_trace_buffer
= mtb
;
196 setvbuf (mallstream
, malloc_trace_buffer
, _IOFBF
, TRACE_BUFFER_SIZE
);
197 fprintf (mallstream
, "= Start\n");
198 if (!added_atexit_handler
)
200 added_atexit_handler
= 1;
201 __cxa_atexit ((void (*)(void *))release_libc_mem
, NULL
,
204 __malloc_debug_enable (MALLOC_MTRACE_HOOK
);
214 __malloc_debug_disable (MALLOC_MTRACE_HOOK
);
215 if (mallstream
== NULL
)
218 /* Do the reverse of what done in mtrace: first reset the hooks and
219 MALLSTREAM, and only after that write the trailer and close the
221 FILE *f
= mallstream
;
224 fprintf (f
, "= End\n");