Move files around. libs to lib/, app to src/ and test to tests/
[memprof.git] / lib / memintercept.c
blob97595eeb1b6b1258278748006bf7319a1d2da287
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.
21 /*====*/
23 #define _GNU_SOURCE
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <dlfcn.h>
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);
41 static void
42 abort_unitialized (const char *call)
44 mi_debug ("MemProf: unexpected library call during initialization: %s\n", call);
45 abort();
48 static void *
49 do_malloc (size_t size, int to_skip)
51 void *result;
52 MIInfo info;
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 ())
63 return NULL;
65 result = (*old_malloc) (size);
67 if (mi_tracing ()) {
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);
76 return result;
79 void *
80 __libc_malloc (size_t size)
82 return do_malloc (size, 1);
85 void *
86 malloc (size_t size)
88 return do_malloc (size, 1);
91 static void *
92 do_calloc (size_t nmemb, size_t size)
94 int total = nmemb * size;
95 void *result = do_malloc (total, 2);
97 if (result)
98 memset (result, 0, total);
100 return result;
104 void *
105 __libc_calloc (size_t nmemb, size_t size)
107 return do_calloc (nmemb, size);
110 void *
111 calloc (size_t nmemb, size_t size)
113 return do_calloc (nmemb, size);
116 static void *
117 do_memalign (size_t boundary, size_t size)
119 void *result;
120 MIInfo info;
122 if (!mi_check_init ())
123 abort_unitialized ("memalign");
125 result = (*old_memalign) (boundary, size);
127 if (mi_tracing ()) {
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);
136 return result;
139 void *
140 __libc_memalign (size_t boundary, size_t size)
142 return do_memalign (boundary, size);
145 void *
146 memalign (size_t boundary, size_t size)
148 return do_memalign (boundary, size);
151 static void *
152 do_realloc (void *ptr, size_t size)
154 void *result;
155 MIInfo info;
157 if (!mi_check_init ())
158 return NULL;/* See comment in initialize() */
160 result = (*old_realloc) (ptr, size);
162 if (mi_tracing ()) {
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);
171 return result;
174 void *
175 __libc_realloc (void *ptr, size_t size)
177 return do_realloc (ptr, size);
180 void *
181 realloc (void *ptr, size_t size)
183 return do_realloc (ptr, size);
186 static void
187 do_free (void *ptr)
189 MIInfo info;
191 if (!mi_check_init ())
192 return;
194 (*old_free) (ptr);
196 if (mi_tracing ()) {
197 info.alloc.operation = MI_FREE;
198 info.alloc.old_ptr = ptr;
199 info.alloc.new_ptr = NULL;
200 info.alloc.size = 0;
202 mi_call_with_backtrace (2, mi_write_stack, &info);
206 void
207 __libc_free (void *ptr)
209 do_free (ptr);
212 void
213 free (void *ptr)
215 do_free (ptr);
218 void
219 mi_init (void)
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");
228 void
229 mi_start (void)
233 void
234 mi_stop (void)