blob: ce02c9790d4580f54208eb2155f6b4941bf863d5 [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
3/*--- Replacements for malloc() et al, which run on the simulated ---*/
4/*--- CPU. vg_replace_malloc.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
10
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 Julian Seward
njn3e884182003-04-15 13:03:23 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32/* ---------------------------------------------------------------------
33 All the code in this file runs on the SIMULATED CPU. It is
34 intended for various reasons as drop-in replacements for malloc()
35 and friends. These functions have global visibility (obviously) and
36 have no prototypes in vg_include.h, since they are not intended to
37 be called from within Valgrind.
38
nethercote7cc9c232004-01-21 15:08:04 +000039 This file can be #included into a tool that wishes to know about
njn3e884182003-04-15 13:03:23 +000040 calls to malloc(). It should define functions SK_(malloc) et al
41 that will be called.
42 ------------------------------------------------------------------ */
43
njn72718642003-07-24 08:45:32 +000044#include "valgrind.h" /* for VALGRIND_NON_SIMD_CALL[12] */
nethercote851b0f62003-11-13 23:02:16 +000045#include "vg_include.h"
fitzhardinge98abfc72003-12-16 02:05:15 +000046#include "vg_skin.h"
njn3e884182003-04-15 13:03:23 +000047
fitzhardinge98abfc72003-12-16 02:05:15 +000048/* Create an alias */
49#define ALIAS(ret, name, args, toname) \
50 ret name args __attribute__((alias(#toname), visibility("protected")))
njn3e884182003-04-15 13:03:23 +000051
fitzhardinge98abfc72003-12-16 02:05:15 +000052/* Declare a function, along with libc's various aliases */
53#define LIBALIAS(ret, name, args) \
54 ALIAS(ret, __##name, args, name); \
55 ALIAS(ret, __libc_##name, args, name); \
56 ret name args
njn3e884182003-04-15 13:03:23 +000057
58/*------------------------------------------------------------*/
59/*--- Replacing malloc() et al ---*/
60/*------------------------------------------------------------*/
61
fitzhardinge98abfc72003-12-16 02:05:15 +000062static struct vg_mallocfunc_info info;
63static int init_done;
64
65/* Startup hook - called as init section */
66static void init(void) __attribute__((constructor));
67
njn3e884182003-04-15 13:03:23 +000068/* Below are new versions of malloc, __builtin_new, free,
69 __builtin_delete, calloc, realloc, memalign, and friends.
70
fitzhardinge98abfc72003-12-16 02:05:15 +000071 None of these functions are called directly - they are not meant to
72 be found by the dynamic linker. They get called because
73 vg_replace_malloc installs a bunch of code redirects which causes
74 Valgrind to use these functions rather than the ones they're
75 replacing. That said, we certainly don't mind if the linker finds
76 them, because it makes our life easier with respect to startup
77 initialization order (we can't guarantee that our init routine will
78 necessarily be called early enough to do the redirects before
79 someone wants to allocate).
njn3e884182003-04-15 13:03:23 +000080*/
81
82#define MALLOC_TRACE(format, args...) \
fitzhardinge98abfc72003-12-16 02:05:15 +000083 if (info.clo_trace_malloc) \
fitzhardinge7fae3e02003-10-31 07:13:41 +000084 VALGRIND_INTERNAL_PRINTF(format, ## args )
njn3e884182003-04-15 13:03:23 +000085
86#define MAYBE_SLOPPIFY(n) \
fitzhardinge98abfc72003-12-16 02:05:15 +000087 if (info.clo_sloppy_malloc) { \
88 n = (n+3) & ~3; \
njn3e884182003-04-15 13:03:23 +000089 }
90
njnd0eab5f2003-09-30 16:52:47 +000091/* ALL calls to malloc() and friends wind up here. */
92#define ALLOC(fff, vgfff) \
fitzhardinge98abfc72003-12-16 02:05:15 +000093LIBALIAS(void *, fff, (Int n)) \
njnd0eab5f2003-09-30 16:52:47 +000094{ \
95 void* v; \
96 \
fitzhardinge98abfc72003-12-16 02:05:15 +000097 MALLOC_TRACE(#fff "(%d)", n ); \
njnd0eab5f2003-09-30 16:52:47 +000098 MAYBE_SLOPPIFY(n); \
fitzhardinge98abfc72003-12-16 02:05:15 +000099 if (!init_done) init(); \
njnd0eab5f2003-09-30 16:52:47 +0000100 \
fitzhardinge98abfc72003-12-16 02:05:15 +0000101 v = (void*)VALGRIND_NON_SIMD_CALL1( info.sk_##vgfff, n ); \
fitzhardinge7fae3e02003-10-31 07:13:41 +0000102 MALLOC_TRACE(" = %p", v ); \
njnd0eab5f2003-09-30 16:52:47 +0000103 return v; \
njn3e884182003-04-15 13:03:23 +0000104}
fitzhardinge98abfc72003-12-16 02:05:15 +0000105ALLOC( malloc, malloc );
106ALLOC( __builtin_new, __builtin_new );
107ALLOC( _Znwj, __builtin_new );
njn5cebf572003-10-09 15:40:38 +0000108
109// operator new(unsigned, std::nothrow_t const&)
fitzhardinge98abfc72003-12-16 02:05:15 +0000110ALLOC( _ZnwjRKSt9nothrow_t, __builtin_new );
njn5cebf572003-10-09 15:40:38 +0000111
fitzhardinge98abfc72003-12-16 02:05:15 +0000112ALLOC( __builtin_vec_new, __builtin_vec_new );
113ALLOC( _Znaj, __builtin_vec_new );
njn5cebf572003-10-09 15:40:38 +0000114
115// operator new[](unsigned, std::nothrow_t const&
fitzhardinge98abfc72003-12-16 02:05:15 +0000116ALLOC( _ZnajRKSt9nothrow_t, __builtin_vec_new );
njn3e884182003-04-15 13:03:23 +0000117
njnd0eab5f2003-09-30 16:52:47 +0000118#define FREE(fff, vgfff) \
fitzhardinge98abfc72003-12-16 02:05:15 +0000119LIBALIAS(void, fff, (void *p)) \
njnd0eab5f2003-09-30 16:52:47 +0000120{ \
fitzhardinge98abfc72003-12-16 02:05:15 +0000121 MALLOC_TRACE(#fff "(%p)", p ); \
njnd0eab5f2003-09-30 16:52:47 +0000122 if (p == NULL) \
123 return; \
fitzhardinge98abfc72003-12-16 02:05:15 +0000124 if (!init_done) init(); \
125 (void)VALGRIND_NON_SIMD_CALL1( info.sk_##vgfff, p ); \
njn3e884182003-04-15 13:03:23 +0000126}
fitzhardinge98abfc72003-12-16 02:05:15 +0000127FREE( free, free );
128FREE( __builtin_delete, __builtin_delete );
129FREE( _ZdlPv, __builtin_delete );
130FREE( __builtin_vec_delete, __builtin_vec_delete );
131FREE( _ZdaPv, __builtin_vec_delete );
njn3e884182003-04-15 13:03:23 +0000132
fitzhardinge98abfc72003-12-16 02:05:15 +0000133LIBALIAS(void*, calloc, ( Int nmemb, Int size ))
njn3e884182003-04-15 13:03:23 +0000134{
135 void* v;
136
fitzhardinge98abfc72003-12-16 02:05:15 +0000137 MALLOC_TRACE("calloc(%d,%d)", nmemb, size );
njn3e884182003-04-15 13:03:23 +0000138 MAYBE_SLOPPIFY(size);
139
fitzhardinge98abfc72003-12-16 02:05:15 +0000140 if (!init_done) init();
141 v = (void*)VALGRIND_NON_SIMD_CALL2( info.sk_calloc, nmemb, size );
fitzhardinge7fae3e02003-10-31 07:13:41 +0000142 MALLOC_TRACE(" = %p", v );
njn3e884182003-04-15 13:03:23 +0000143 return v;
144}
145
fitzhardinge98abfc72003-12-16 02:05:15 +0000146LIBALIAS(void*, realloc, ( void* ptrV, Int new_size ))
njn3e884182003-04-15 13:03:23 +0000147{
148 void* v;
149
fitzhardinge98abfc72003-12-16 02:05:15 +0000150 MALLOC_TRACE("realloc(%p,%d)", ptrV, new_size );
njn3e884182003-04-15 13:03:23 +0000151 MAYBE_SLOPPIFY(new_size);
152
153 if (ptrV == NULL)
154 return malloc(new_size);
155 if (new_size <= 0) {
156 free(ptrV);
fitzhardinge98abfc72003-12-16 02:05:15 +0000157 if (info.clo_trace_malloc)
158 VALGRIND_INTERNAL_PRINTF(" = 0" );
njn3e884182003-04-15 13:03:23 +0000159 return NULL;
160 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000161 if (!init_done) init();
162 v = (void*)VALGRIND_NON_SIMD_CALL2( info.sk_realloc, ptrV, new_size );
fitzhardinge7fae3e02003-10-31 07:13:41 +0000163 MALLOC_TRACE(" = %p", v );
njn3e884182003-04-15 13:03:23 +0000164 return v;
165}
166
167
fitzhardinge98abfc72003-12-16 02:05:15 +0000168LIBALIAS(void*, memalign, ( Int alignment, Int n ))
njn3e884182003-04-15 13:03:23 +0000169{
170 void* v;
171
fitzhardinge98abfc72003-12-16 02:05:15 +0000172 MALLOC_TRACE("memalign(al %d, size %d)", alignment, n );
njn3e884182003-04-15 13:03:23 +0000173 MAYBE_SLOPPIFY(n);
174
fitzhardinge98abfc72003-12-16 02:05:15 +0000175 if (!init_done) init();
176 v = (void*)VALGRIND_NON_SIMD_CALL2( info.sk_memalign, alignment, n );
fitzhardinge7fae3e02003-10-31 07:13:41 +0000177 MALLOC_TRACE(" = %p", v );
njn3e884182003-04-15 13:03:23 +0000178 return v;
179}
180
181
fitzhardinge98abfc72003-12-16 02:05:15 +0000182LIBALIAS(void*, valloc, ( Int size ))
njn3e884182003-04-15 13:03:23 +0000183{
184 return memalign(VKI_BYTES_PER_PAGE, size);
185}
186
187
188/* Various compatibility wrapper functions, for glibc and libstdc++. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000189
190/* Don't just alias free, otherwise people could get confused seeing
191 cfree rather than free in error output */
192LIBALIAS(void, cfree, ( void* p ) )
njn3e884182003-04-15 13:03:23 +0000193{
fitzhardinge98abfc72003-12-16 02:05:15 +0000194 free(p);
njn3e884182003-04-15 13:03:23 +0000195}
196
fitzhardinge98abfc72003-12-16 02:05:15 +0000197LIBALIAS(int, mallopt, ( int cmd, int value ))
njn3e884182003-04-15 13:03:23 +0000198{
199 /* In glibc-2.2.4, 1 denotes a successful return value for mallopt */
200 return 1;
201}
202
203
fitzhardinge98abfc72003-12-16 02:05:15 +0000204LIBALIAS(int, posix_memalign, ( void **memptr, UInt alignment, UInt size ))
njn3e884182003-04-15 13:03:23 +0000205{
206 void *mem;
207
mueller211d05d2003-11-28 00:15:57 +0000208 /* Test whether the alignment argument is valid. It must be a power of
njn3e884182003-04-15 13:03:23 +0000209 two multiple of sizeof (void *). */
mueller211d05d2003-11-28 00:15:57 +0000210 if (alignment % sizeof (void *) != 0 || (alignment & (alignment - 1)) != 0)
njn3e884182003-04-15 13:03:23 +0000211 return VKI_EINVAL /*22*/ /*EINVAL*/;
212
213 mem = memalign (alignment, size);
214
215 if (mem != NULL) {
216 *memptr = mem;
217 return 0;
218 }
219
220 return VKI_ENOMEM /*12*/ /*ENOMEM*/;
221}
222
fitzhardinge98abfc72003-12-16 02:05:15 +0000223LIBALIAS(int, malloc_usable_size, ( void* p ))
njn8a6b6c02003-04-22 22:45:55 +0000224{
225 Int pszB;
226
fitzhardinge98abfc72003-12-16 02:05:15 +0000227 MALLOC_TRACE("malloc_usable_size(%p)", p );
njn8a6b6c02003-04-22 22:45:55 +0000228 if (NULL == p)
229 return 0;
230
fitzhardinge98abfc72003-12-16 02:05:15 +0000231 if (!init_done) init();
232 pszB = (Int)VALGRIND_NON_SIMD_CALL2( info.arena_payload_szB,
233 VG_AR_CLIENT, p );
fitzhardinge7fae3e02003-10-31 07:13:41 +0000234 MALLOC_TRACE(" = %d", pszB );
njn8a6b6c02003-04-22 22:45:55 +0000235
236 return pszB;
237}
238
njn3e884182003-04-15 13:03:23 +0000239
240/* Bomb out if we get any of these. */
njn8a6b6c02003-04-22 22:45:55 +0000241
fitzhardinge98abfc72003-12-16 02:05:15 +0000242extern void _exit(int);
243
244static void panic(const char *str)
245{
246 VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s", str);
247
248 _exit(99);
249 *(int *)0 = 'x';
250}
251
252#define PANIC(x) \
253 void x(void) \
254 { \
255 panic(#x); \
256 }
257
258PANIC(pvalloc);
259PANIC(malloc_stats);
260PANIC(malloc_trim);
261PANIC(malloc_get_state);
262PANIC(malloc_set_state);
njn3e884182003-04-15 13:03:23 +0000263
264
265/* Yet another ugly hack. Cannot include <malloc.h> because we
266 implement functions implemented there with different signatures.
267 This struct definition MUST match the system one. */
268
269/* SVID2/XPG mallinfo structure */
270struct mallinfo {
271 int arena; /* total space allocated from system */
272 int ordblks; /* number of non-inuse chunks */
273 int smblks; /* unused -- always zero */
274 int hblks; /* number of mmapped regions */
275 int hblkhd; /* total space in mmapped regions */
276 int usmblks; /* unused -- always zero */
277 int fsmblks; /* unused -- always zero */
278 int uordblks; /* total allocated space */
279 int fordblks; /* total non-inuse space */
280 int keepcost; /* top-most, releasable (via malloc_trim) space */
281};
282
fitzhardinge98abfc72003-12-16 02:05:15 +0000283LIBALIAS(struct mallinfo, mallinfo, ( void ))
njn3e884182003-04-15 13:03:23 +0000284{
285 /* Should really try to return something a bit more meaningful */
sewardj05bcdcb2003-05-18 10:05:38 +0000286 UInt i;
njn3e884182003-04-15 13:03:23 +0000287 struct mallinfo mi;
288 UChar* pmi = (UChar*)(&mi);
289 for (i = 0; i < sizeof(mi); i++)
290 pmi[i] = 0;
291 return mi;
292}
293
fitzhardinge98abfc72003-12-16 02:05:15 +0000294static const struct {
295 const Char *libname;
296 Addr func;
297} replacements[] =
298{
299#define E(pfx, x) { pfx #x, (Addr)x }
300#define R(x) E("", x), E("__libc_", x), E("__", x)
301
302 /* alloc */
303 R(malloc),
304 R(__builtin_new),
305 R(_Znwj),
306 R(_ZnwjRKSt9nothrow_t), /* operator new(unsigned, std::nothrow_t const&) */
307 R(__builtin_vec_new),
308 R(_Znaj),
309 R(_ZnajRKSt9nothrow_t), /* operator new[](unsigned, std::nothrow_t const& */
310 R(calloc),
311 R(realloc),
312 R(memalign),
313 R(valloc),
314 R(cfree),
315 R(posix_memalign),
316
317 /* free */
318 R(free),
319 R(__builtin_delete),
320 R(_ZdlPv),
321 R(__builtin_vec_delete),
322 R(_ZdaPv),
323
324 /* misc */
325 R(mallopt),
326 R(malloc_usable_size),
327 R(mallinfo),
328
329 /* bad */
330 R(pvalloc),
331 R(malloc_stats),
332 R(malloc_trim),
333 R(malloc_get_state),
334 R(malloc_set_state),
335#undef R
336#undef S
337#undef E
338};
339
340/* All the code in here is unused until this function is called */
341
342static void init(void)
343{
344 int i;
345 int res;
346
347 if (init_done)
348 return;
349
350 init_done = 1;
351
352 VALGRIND_MAGIC_SEQUENCE(res, -1, VG_USERREQ__GET_MALLOCFUNCS, &info, 0, 0, 0);
353
354 for(i = 0; i < sizeof(replacements)/sizeof(*replacements); i++) {
355#if 0
356 /* doesn't seem much point - ld-linux.so will have already used
357 malloc/free before we run */
358 VALGRIND_MAGIC_SEQUENCE(res, 0, VG_USERREQ__REGISTER_REDIRECT_ADDR,
359 "soname:ld-linux.so.2", replacements[i].libname,
360 replacements[i].func, 0);
361#endif
362 VALGRIND_MAGIC_SEQUENCE(res, 0, VG_USERREQ__REGISTER_REDIRECT_ADDR,
363 "soname:libc.so.6", replacements[i].libname,
364 replacements[i].func, 0);
365 VALGRIND_MAGIC_SEQUENCE(res, 0, VG_USERREQ__REGISTER_REDIRECT_ADDR,
366 "soname:libstdc++*", replacements[i].libname,
367 replacements[i].func, 0);
368 }
369}
370
njn3e884182003-04-15 13:03:23 +0000371/*--------------------------------------------------------------------*/
372/*--- end vg_replace_malloc.c ---*/
373/*--------------------------------------------------------------------*/