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
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program 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
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "intercept.h"
31 #include "memintercept.h"
32 #include "memintercept-utils.h"
33 #include "stack-frame.h"
35 static void *(*old_malloc
) (size_t size
);
36 static void *(*old_calloc
) (size_t nmemb
, size_t size
);
37 static void *(*old_memalign
) (size_t boundary
, size_t size
);
38 static void *(*old_realloc
) (void *ptr
, size_t size
);
39 static void (*old_free
) (void *ptr
);
42 abort_unitialized (const char *call
)
44 mi_debug ("MemProf: unexpected library call during initialization: %s\n", call
);
49 do_malloc (size_t size
, int to_skip
)
54 /* It's possible to get recursion here, since dlsym() can trigger
55 * memory allocation. To deal with this, we flag the initialization
56 * condition specially, then use the special knowledge that it's
57 * OK for malloc to fail during initialization (libc degrades
58 * gracefully), so we just return NULL from malloc(), realloc().
60 * This trick is borrowed from from libc's memusage.
62 if (!mi_check_init ())
65 result
= (*old_malloc
) (size
);
68 info
.alloc
.operation
= MI_MALLOC
;
69 info
.alloc
.old_ptr
= NULL
;
70 info
.alloc
.new_ptr
= result
;
71 info
.alloc
.size
= size
;
73 mi_call_with_backtrace (to_skip
+ 1, mi_write_stack
, &info
);
80 __libc_malloc (size_t size
)
82 return do_malloc (size
, 1);
88 return do_malloc (size
, 1);
92 do_calloc (size_t nmemb
, size_t size
)
94 int total
= nmemb
* size
;
95 void *result
= do_malloc (total
, 2);
98 memset (result
, 0, total
);
105 __libc_calloc (size_t nmemb
, size_t size
)
107 return do_calloc (nmemb
, size
);
111 calloc (size_t nmemb
, size_t size
)
113 return do_calloc (nmemb
, size
);
117 do_memalign (size_t boundary
, size_t size
)
122 if (!mi_check_init ())
123 abort_unitialized ("memalign");
125 result
= (*old_memalign
) (boundary
, size
);
128 info
.alloc
.operation
= MI_MALLOC
;
129 info
.alloc
.old_ptr
= NULL
;
130 info
.alloc
.new_ptr
= result
;
131 info
.alloc
.size
= size
;
133 mi_call_with_backtrace (2, mi_write_stack
, &info
);
140 __libc_memalign (size_t boundary
, size_t size
)
142 return do_memalign (boundary
, size
);
146 memalign (size_t boundary
, size_t size
)
148 return do_memalign (boundary
, size
);
152 do_realloc (void *ptr
, size_t size
)
157 if (!mi_check_init ())
158 return NULL
;/* See comment in initialize() */
160 result
= (*old_realloc
) (ptr
, size
);
163 info
.alloc
.operation
= MI_REALLOC
;
164 info
.alloc
.old_ptr
= ptr
;
165 info
.alloc
.new_ptr
= result
;
166 info
.alloc
.size
= size
;
168 mi_call_with_backtrace (2, mi_write_stack
, &info
);
175 __libc_realloc (void *ptr
, size_t size
)
177 return do_realloc (ptr
, size
);
181 realloc (void *ptr
, size_t size
)
183 return do_realloc (ptr
, size
);
191 if (!mi_check_init ())
197 info
.alloc
.operation
= MI_FREE
;
198 info
.alloc
.old_ptr
= ptr
;
199 info
.alloc
.new_ptr
= NULL
;
202 mi_call_with_backtrace (2, mi_write_stack
, &info
);
207 __libc_free (void *ptr
)
221 old_malloc
= dlsym(RTLD_NEXT
, "__libc_malloc");
222 old_realloc
= dlsym(RTLD_NEXT
, "__libc_realloc");
223 old_free
= dlsym(RTLD_NEXT
, "__libc_free");
224 old_calloc
= dlsym(RTLD_NEXT
, "__libc_calloc");
225 old_memalign
= dlsym(RTLD_NEXT
, "__libc_memalign");