1 /* -*- mode: C; c-file-style: "linux" -*- */
3 /* MemProf -- memory profiler and leak detector
4 * Copyright 1999, 2000, 2001, Red Hat, Inc.
5 * Copyright 2002, Kristian Rietveld
6 * Copyright 2009, Holger Hans Peter Freyther
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "intercept.h"
32 #include "memintercept.h"
33 #include "memintercept-utils.h"
34 #include "stack-frame.h"
36 static void *(*old_malloc
) (size_t size
);
37 static void *(*old_calloc
) (size_t nmemb
, size_t size
);
38 static void *(*old_memalign
) (size_t boundary
, size_t size
);
39 static void *(*old_realloc
) (void *ptr
, size_t size
);
40 static void (*old_free
) (void *ptr
);
42 /* helpers for WebKit */
43 static void *(*old_fastMalloc
) (size_t size
);
44 static void *(*old_fastCalloc
) (size_t nmemb
, size_t size
);
45 static void *(*old_fastRealloc
) (void *ptr
, size_t size
);
46 static void (*old_fastFree
) (void *ptr
);
49 abort_unitialized (const char *call
)
51 mi_debug ("MemProf: unexpected library call during initialization: %s\n", call
);
56 do_malloc (size_t size
, int to_skip
)
61 /* It's possible to get recursion here, since dlsym() can trigger
62 * memory allocation. To deal with this, we flag the initialization
63 * condition specially, then use the special knowledge that it's
64 * OK for malloc to fail during initialization (libc degrades
65 * gracefully), so we just return NULL from malloc(), realloc().
67 * This trick is borrowed from from libc's memusage.
69 if (!mi_check_init ())
72 result
= (*old_malloc
) (size
);
75 info
.alloc
.operation
= MI_MALLOC
;
76 info
.alloc
.old_ptr
= NULL
;
77 info
.alloc
.new_ptr
= result
;
78 info
.alloc
.size
= size
;
80 mi_call_with_backtrace (to_skip
+ 1, mi_write_stack
, &info
);
87 __libc_malloc (size_t size
)
89 return do_malloc (size
, 1);
95 return do_malloc (size
, 1);
99 do_calloc (size_t nmemb
, size_t size
)
101 int total
= nmemb
* size
;
102 void *result
= do_malloc (total
, 2);
105 memset (result
, 0, total
);
112 __libc_calloc (size_t nmemb
, size_t size
)
114 return do_calloc (nmemb
, size
);
118 calloc (size_t nmemb
, size_t size
)
120 return do_calloc (nmemb
, size
);
124 do_memalign (size_t boundary
, size_t size
)
129 if (!mi_check_init ())
130 abort_unitialized ("memalign");
132 result
= (*old_memalign
) (boundary
, size
);
135 info
.alloc
.operation
= MI_MALLOC
;
136 info
.alloc
.old_ptr
= NULL
;
137 info
.alloc
.new_ptr
= result
;
138 info
.alloc
.size
= size
;
140 mi_call_with_backtrace (2, mi_write_stack
, &info
);
147 __libc_memalign (size_t boundary
, size_t size
)
149 return do_memalign (boundary
, size
);
153 memalign (size_t boundary
, size_t size
)
155 return do_memalign (boundary
, size
);
159 do_realloc (void *ptr
, size_t size
)
164 if (!mi_check_init ())
165 return NULL
;/* See comment in initialize() */
167 result
= (*old_realloc
) (ptr
, size
);
170 info
.alloc
.operation
= MI_REALLOC
;
171 info
.alloc
.old_ptr
= ptr
;
172 info
.alloc
.new_ptr
= result
;
173 info
.alloc
.size
= size
;
175 mi_call_with_backtrace (2, mi_write_stack
, &info
);
182 __libc_realloc (void *ptr
, size_t size
)
184 return do_realloc (ptr
, size
);
188 realloc (void *ptr
, size_t size
)
190 return do_realloc (ptr
, size
);
198 if (!mi_check_init ())
204 info
.alloc
.operation
= MI_FREE
;
205 info
.alloc
.old_ptr
= ptr
;
206 info
.alloc
.new_ptr
= NULL
;
209 mi_call_with_backtrace (2, mi_write_stack
, &info
);
214 __libc_free (void *ptr
)
226 _ZN3WTF10fastMallocEj(size_t size
)
231 if (!mi_check_init ())
232 return NULL
;/* See comment in initialize() */
234 result
= (*old_fastMalloc
) (size
);
237 info
.alloc
.operation
= MI_MALLOC
;
238 info
.alloc
.old_ptr
= NULL
;
239 info
.alloc
.new_ptr
= result
;
240 info
.alloc
.size
= size
;
242 mi_call_with_backtrace (2, mi_write_stack
, &info
);
249 _ZN3WTF11fastReallocEPvj(void *ptr
, size_t size
)
254 if (!mi_check_init ())
255 return NULL
;/* See comment in initialize() */
257 result
= (*old_fastRealloc
) (ptr
, size
);
260 info
.alloc
.operation
= MI_REALLOC
;
261 info
.alloc
.old_ptr
= ptr
;
262 info
.alloc
.new_ptr
= result
;
263 info
.alloc
.size
= size
;
265 mi_call_with_backtrace (1, mi_write_stack
, &info
);
272 _ZN3WTF8fastFreeEPv(void *ptr
)
276 if (!mi_check_init ())
277 return;/* See comment in initialize() */
279 (*old_fastFree
) (ptr
);
282 info
.alloc
.operation
= MI_FREE
;
283 info
.alloc
.old_ptr
= ptr
;
284 info
.alloc
.new_ptr
= NULL
;
287 mi_call_with_backtrace (1, mi_write_stack
, &info
);
292 _ZN3WTF10fastCallocEjj(size_t nmemb
, size_t size
)
297 if (!mi_check_init ())
298 return NULL
;/* See comment in initialize() */
300 result
= (*old_fastCalloc
) (nmemb
, size
);
303 info
.alloc
.operation
= MI_MALLOC
;
304 info
.alloc
.old_ptr
= NULL
;
305 info
.alloc
.new_ptr
= result
;
306 info
.alloc
.size
= nmemb
* size
;
308 mi_call_with_backtrace (1, mi_write_stack
, &info
);
317 old_malloc
= dlsym(RTLD_NEXT
, "malloc");
318 old_realloc
= dlsym(RTLD_NEXT
, "realloc");
319 old_free
= dlsym(RTLD_NEXT
, "free");
320 old_calloc
= dlsym(RTLD_NEXT
, "calloc");
321 old_memalign
= dlsym(RTLD_NEXT
, "memalign");
323 /* to ease debugging webkit */
324 old_fastMalloc
= dlsym(RTLD_NEXT
, "_ZN3WTF10fastMallocEj");
325 old_fastRealloc
= dlsym(RTLD_NEXT
, "_ZN3WTF11fastReallocEPvj");
326 old_fastFree
= dlsym(RTLD_NEXT
, "_ZN3WTF8fastFreeEPv");
327 old_fastCalloc
= dlsym(RTLD_NEXT
, "_ZN3WTF10fastCallocEjj");