1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #ifndef _MALLOC_INTERNAL
23: #define _MALLOC_INTERNAL
24: #include <malloc.h>
25: #include <mcheck.h>
26: #include <bits/libc-lock.h>
27: #endif
28:
29: #include <dlfcn.h>
30: #include <fcntl.h>
31: #include <stdio.h>
32: #include <string.h>
33: #include <stdlib.h>
34:
35: #include <stdio-common/_itoa.h>
36:
37: #ifdef _LIBC
38: # include <libc-internal.h>
39:
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: #endif
44:
45: #ifndef attribute_hidden
46: # define attribute_hidden
47: #endif
48:
49: #define TRACE_BUFFER_SIZE 512
50:
51: static FILE *mallstream;
52: static const char mallenv[]= "MALLOC_TRACE";
53: static char *malloc_trace_buffer;
54:
55: __libc_lock_define_initialized (static, lock);
56:
57:
58: __ptr_t mallwatch;
59:
60: #ifdef USE_MTRACE_FILE
61:
62:
63: char *_mtrace_file;
64: int _mtrace_line;
65: #endif
66:
67:
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,
71: const __ptr_t);
72: static __ptr_t (*tr_old_memalign_hook) (__malloc_size_t __alignment,
73: __malloc_size_t __size,
74: __const __ptr_t);
75:
76:
77:
78:
79:
80:
81: extern void tr_break (void) __THROW;
82: libc_hidden_proto (tr_break)
83: void
84: tr_break ()
85: {
86: }
87: libc_hidden_def (tr_break)
88:
89: static void tr_where (const __ptr_t) __THROW internal_function;
90: static void
91: internal_function
92: tr_where (caller)
93: const __ptr_t caller;
94: {
95: #ifdef USE_MTRACE_FILE
96: if (_mtrace_file)
97: {
98: fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line);
99: _mtrace_file = NULL;
100: }
101: else
102: #endif
103: if (caller != NULL)
104: {
105: #ifdef HAVE_ELF
106: Dl_info info;
107: if (_dl_addr (caller, &info, NULL, NULL))
108: {
109: char *buf = (char *) "";
110: if (info.dli_sname != NULL)
111: {
112: size_t len = strlen (info.dli_sname);
113: buf = alloca (len + 6 + 2 * sizeof (void *));
114:
115: buf[0] = '(';
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,
120: len),
121: caller >= (__ptr_t) info.dli_saddr
122: ? "+0x" : "-0x"),
123: 16, 0),
124: ")");
125: }
126:
127: fprintf (mallstream, "@ %s%s%s[%p] ",
128: info.dli_fname ?: "", info.dli_fname ? ":" : "",
129: buf, caller);
130: }
131: else
132: #endif
133: fprintf (mallstream, "@ [%p] ", caller);
134: }
135: }
136:
137: static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
138: static void
139: tr_freehook (ptr, caller)
140: __ptr_t ptr;
141: const __ptr_t caller;
142: {
143: if (ptr == NULL)
144: return;
145: __libc_lock_lock (lock);
146: tr_where (caller);
147:
148: fprintf (mallstream, "- %p\n", ptr);
149: __libc_lock_unlock (lock);
150: if (ptr == mallwatch)
151: tr_break ();
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);
156: else
157: free (ptr);
158: __free_hook = tr_freehook;
159: __libc_lock_unlock (lock);
160: }
161:
162: static __ptr_t tr_mallochook (__malloc_size_t, const __ptr_t) __THROW;
163: static __ptr_t
164: tr_mallochook (size, caller)
165: __malloc_size_t size;
166: const __ptr_t caller;
167: {
168: __ptr_t hdr;
169:
170: __libc_lock_lock (lock);
171:
172: __malloc_hook = tr_old_malloc_hook;
173: if (tr_old_malloc_hook != NULL)
174: hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller);
175: else
176: hdr = (__ptr_t) malloc (size);
177: __malloc_hook = tr_mallochook;
178:
179: tr_where (caller);
180:
181: fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
182:
183: __libc_lock_unlock (lock);
184:
185: if (hdr == mallwatch)
186: tr_break ();
187:
188: return hdr;
189: }
190:
191: static __ptr_t tr_reallochook (__ptr_t, __malloc_size_t, const __ptr_t)
192: __THROW;
193: static __ptr_t
194: tr_reallochook (ptr, size, caller)
195: __ptr_t ptr;
196: __malloc_size_t size;
197: const __ptr_t caller;
198: {
199: __ptr_t hdr;
200:
201: if (ptr == mallwatch)
202: tr_break ();
203:
204: __libc_lock_lock (lock);
205:
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);
211: else
212: hdr = (__ptr_t) realloc (ptr, size);
213: __free_hook = tr_freehook;
214: __malloc_hook = tr_mallochook;
215: __realloc_hook = tr_reallochook;
216:
217: tr_where (caller);
218: if (hdr == NULL)
219:
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);
223: else
224: {
225: fprintf (mallstream, "< %p\n", ptr);
226: tr_where (caller);
227: fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
228: }
229:
230: __libc_lock_unlock (lock);
231:
232: if (hdr == mallwatch)
233: tr_break ();
234:
235: return hdr;
236: }
237:
238: static __ptr_t tr_memalignhook (__malloc_size_t, __malloc_size_t,
239: const __ptr_t) __THROW;
240: static __ptr_t
241: tr_memalignhook (alignment, size, caller)
242: __malloc_size_t alignment, size;
243: const __ptr_t caller;
244: {
245: __ptr_t hdr;
246:
247: __libc_lock_lock (lock);
248:
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);
253: else
254: hdr = (__ptr_t) memalign (alignment, size);
255: __memalign_hook = tr_memalignhook;
256: __malloc_hook = tr_mallochook;
257:
258: tr_where (caller);
259:
260: fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
261:
262: __libc_lock_unlock (lock);
263:
264: if (hdr == mallwatch)
265: tr_break ();
266:
267: return hdr;
268: }
269:
270:
271:
272: #ifdef _LIBC
273:
274:
275:
276:
277: static void __libc_freeres_fn_section
278: release_libc_mem (void)
279: {
280:
281: if (mallstream != NULL)
282: __libc_freeres ();
283: }
284: #endif
285:
286:
287:
288:
289:
290:
291:
292: void
293: mtrace ()
294: {
295: #ifdef _LIBC
296: static int added_atexit_handler;
297: #endif
298: char *mallfile;
299:
300:
301: if (mallstream != NULL)
302: return;
303:
304: #ifdef _LIBC
305:
306:
307:
308: mallfile = __secure_getenv (mallenv);
309: #else
310: mallfile = getenv (mallenv);
311: #endif
312: if (mallfile != NULL || mallwatch != NULL)
313: {
314: char *mtb = malloc (TRACE_BUFFER_SIZE);
315: if (mtb == NULL)
316: return;
317:
318: mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wc");
319: if (mallstream != NULL)
320: {
321:
322: int flags = __fcntl (fileno (mallstream), F_GETFD, 0);
323: if (flags >= 0)
324: {
325: flags |= FD_CLOEXEC;
326: __fcntl (fileno (mallstream), F_SETFD, flags);
327: }
328:
329: malloc_trace_buffer = mtb;
330: setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
331: fprintf (mallstream, "= Start\n");
332: tr_old_free_hook = __free_hook;
333: __free_hook = tr_freehook;
334: tr_old_malloc_hook = __malloc_hook;
335: __malloc_hook = tr_mallochook;
336: tr_old_realloc_hook = __realloc_hook;
337: __realloc_hook = tr_reallochook;
338: tr_old_memalign_hook = __memalign_hook;
339: __memalign_hook = tr_memalignhook;
340: #ifdef _LIBC
341: if (!added_atexit_handler)
342: {
343: extern void *__dso_handle __attribute__ ((__weak__));
344: added_atexit_handler = 1;
345: __cxa_atexit ((void (*) (void *)) release_libc_mem, NULL,
346: &__dso_handle ? __dso_handle : NULL);
347: }
348: #endif
349: }
350: else
351: free (mtb);
352: }
353: }
354:
355: void
356: muntrace ()
357: {
358: if (mallstream == NULL)
359: return;
360:
361: fprintf (mallstream, "= End\n");
362: fclose (mallstream);
363: mallstream = NULL;
364: __free_hook = tr_old_free_hook;
365: __malloc_hook = tr_old_malloc_hook;
366: __realloc_hook = tr_old_realloc_hook;
367: __memalign_hook = tr_old_memalign_hook;
368: }