1 /* mtrace implementation for `malloc'.
2 Copyright (C) 1991-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
30 #include <libc-internal.h>
31 #include <dso_handle.h>
33 #include <kernel-features.h>
35 static FILE *mallstream
;
36 static const char mallenv
[] = "MALLOC_TRACE";
39 tr_where (const void *caller
, Dl_info
*info
)
45 char *buf
= (char *) "";
46 if (info
->dli_sname
!= NULL
)
48 size_t len
= strlen (info
->dli_sname
);
49 buf
= alloca (len
+ 6 + 2 * sizeof (void *));
52 (ptrdiff_t) info
->dli_saddr
- (ptrdiff_t) caller
;
54 if (caller
>= (const void *) info
->dli_saddr
)
62 sprintf (buf
, "(%s%c%" PRIxPTR
")", info
->dli_sname
, sign
,
66 fprintf (mallstream
, "@ %s%s%s[0x%" PRIxPTR
"] ",
67 info
->dli_fname
? : "", info
->dli_fname
? ":" : "", buf
,
68 caller
- info
->dli_fbase
);
71 fprintf (mallstream
, "@ [%p] ", caller
);
76 lock_and_info (const void *caller
, Dl_info
*mem
)
81 Dl_info
*res
= dladdr (caller
, mem
) ? mem
: NULL
;
83 flockfile (mallstream
);
89 free_mtrace (void *ptr
, const void *caller
)
95 Dl_info
*info
= lock_and_info (caller
, &mem
);
96 tr_where (caller
, info
);
97 /* Be sure to print it first. */
98 fprintf (mallstream
, "- %p\n", ptr
);
99 funlockfile (mallstream
);
103 malloc_mtrace_after (void *block
, size_t size
, const void *caller
)
106 Dl_info
*info
= lock_and_info (caller
, &mem
);
108 tr_where (caller
, info
);
109 /* We could be printing a NULL here; that's OK. */
110 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
112 funlockfile (mallstream
);
116 realloc_mtrace_after (void *block
, const void *oldptr
, size_t size
,
120 Dl_info
*info
= lock_and_info (caller
, &mem
);
122 tr_where (caller
, info
);
126 /* Failed realloc. */
127 fprintf (mallstream
, "! %p %#lx\n", oldptr
, (unsigned long int) size
);
129 fprintf (mallstream
, "- %p\n", oldptr
);
131 else if (oldptr
== NULL
)
132 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
135 fprintf (mallstream
, "< %p\n", oldptr
);
136 tr_where (caller
, info
);
137 fprintf (mallstream
, "> %p %#lx\n", block
, (unsigned long int) size
);
140 funlockfile (mallstream
);
144 memalign_mtrace_after (void *block
, size_t size
, const void *caller
)
147 Dl_info
*info
= lock_and_info (caller
, &mem
);
149 tr_where (caller
, info
);
150 /* We could be printing a NULL here; that's OK. */
151 fprintf (mallstream
, "+ %p %#lx\n", block
, (unsigned long int) size
);
153 funlockfile (mallstream
);
156 /* This function gets called to make sure all memory the library
157 allocates get freed and so does not irritate the user when studying
158 the mtrace output. */
160 release_libc_mem (void)
162 /* Only call the free function if we still are running in mtrace mode. */
163 if (mallstream
!= NULL
)
167 /* We enable tracing if the environment variable MALLOC_TRACE is set. */
172 static int added_atexit_handler
;
175 /* Don't panic if we're called more than once. */
176 if (mallstream
!= NULL
)
179 mallfile
= secure_getenv (mallenv
);
180 if (mallfile
!= NULL
)
182 mallstream
= fopen (mallfile
!= NULL
? mallfile
: "/dev/null", "wce");
183 if (mallstream
!= NULL
)
185 /* Be sure it doesn't malloc its buffer! */
186 static char tracebuf
[512];
188 setvbuf (mallstream
, tracebuf
, _IOFBF
, sizeof (tracebuf
));
189 fprintf (mallstream
, "= Start\n");
190 if (!added_atexit_handler
)
192 added_atexit_handler
= 1;
193 __cxa_atexit ((void (*)(void *))release_libc_mem
, NULL
,
196 __malloc_debug_enable (MALLOC_MTRACE_HOOK
);
204 __malloc_debug_disable (MALLOC_MTRACE_HOOK
);
205 if (mallstream
== NULL
)
208 /* Do the reverse of what done in mtrace: first reset the hooks and
209 MALLSTREAM, and only after that write the trailer and close the
211 FILE *f
= mallstream
;
214 fprintf (f
, "= End\n");