blob: f6df4e4d386236a11dd99e3c060e5133473fcc70 [file] [log] [blame]
sewardj9ee81f52005-04-02 17:38:59 +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, a dynamic binary instrumentation
9 framework.
10
sewardj9ebd6e02007-01-08 06:01:59 +000011 Copyright (C) 2000-2007 Julian Seward
sewardj9ee81f52005-04-02 17:38:59 +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/* ---------------------------------------------------------------------
njn16eeb4e2005-06-16 03:56:58 +000033 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
34
35 These functions are drop-in replacements for malloc() and friends.
36 They have global scope, but are not intended to be called directly.
37 See pub_core_redir.h for the gory details.
sewardj9ee81f52005-04-02 17:38:59 +000038
njn16eeb4e2005-06-16 03:56:58 +000039 This file can be linked into the vg_preload_<tool>.so file for any tool
40 that wishes to know about calls to malloc(). The tool must define all
njn51d827b2005-05-09 01:02:08 +000041 the functions that will be called via 'info'.
njn717cde52005-05-10 02:47:21 +000042
njn16eeb4e2005-06-16 03:56:58 +000043 It is called vg_replace_malloc.c because this filename appears in stack
44 traces, so we want the name to be (hopefully!) meaningful to users.
sewardj9ee81f52005-04-02 17:38:59 +000045 ------------------------------------------------------------------ */
46
njnc7561b92005-06-19 01:24:32 +000047#include "pub_core_basics.h"
sewardje66f2e02006-12-30 17:45:08 +000048#include "pub_core_vki.h" // VKI_EINVAL, VKI_ENOMEM
njn93fe3b22005-12-21 20:22:52 +000049#include "pub_core_clreq.h" // for VALGRIND_INTERNAL_PRINTF,
50 // VALGRIND_NON_SIMD_CALL[12]
njn16eeb4e2005-06-16 03:56:58 +000051#include "pub_core_debuginfo.h" // needed for pub_core_redir.h :(
njnaf1d7df2005-06-11 01:31:52 +000052#include "pub_core_mallocfree.h" // for VG_MIN_MALLOC_SZB, VG_AR_CLIENT
sewardjec92a072006-10-17 01:50:31 +000053#include "pub_core_redir.h" // for VG_REPLACE_FUNCTION_*
njnda325d92005-05-11 18:51:53 +000054#include "pub_core_replacemalloc.h"
sewardj9ee81f52005-04-02 17:38:59 +000055
sewardjec92a072006-10-17 01:50:31 +000056/* --------- Some handy Z-encoded names. --------- */
57
58/* --- Soname of the standard C library. --- */
59
60#if defined(VGO_linux)
61# define m_libc_soname libcZdsoZa // libc.so*
62#elif defined(VGP_ppc32_aix5)
63 /* AIX has both /usr/lib/libc.a and /usr/lib/libc_r.a. */
64# define m_libc_soname libcZaZdaZLshrZdoZR // libc*.a(shr.o)
65#elif defined(VGP_ppc64_aix5)
66# define m_libc_soname libcZaZdaZLshrZu64ZdoZR // libc*.a(shr_64.o)
67#else
68# error "Unknown platform"
69#endif
70
71/* --- Soname of the GNU C++ library. --- */
72
73#define m_libstdcxx_soname libstdcZpZpZa // libstdc++*
74
75/* --- Soname of XLC's C++ library. --- */
76
77/* AIX: xlC's C++ runtime library is called libC.a, and the
78 interesting symbols appear to be in ansicore_32.o or ansicore_64.o
79 respectively. */
80#if defined(VGP_ppc32_aix5)
81# define m_libC_dot_a libCZdaZLansicoreZu32ZdoZR // libC.a(ansicore_32.o)
82#elif defined(VGP_ppc64_aix5)
83# define m_libC_dot_a libCZdaZLansicoreZu64ZdoZR // libC.a(ansicore_64.o)
84#endif
85
sewardj9ee81f52005-04-02 17:38:59 +000086
87/* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
88 mangling, could be supported properly by the redirects in this
89 module. Except we can't because it doesn't put its allocation
90 functions in libpgc.so but instead hardwires them into the
91 compilation unit holding main(), which makes them impossible to
92 intercept directly. Fortunately those fns seem to route everything
93 through to malloc/free.
sewardjec92a072006-10-17 01:50:31 +000094
95 mid-06: could be improved, since we can now intercept in the main
96 executable too.
sewardj9ee81f52005-04-02 17:38:59 +000097*/
98
99extern void _exit(int);
100
sewardjec92a072006-10-17 01:50:31 +0000101/* Apparently it is necessary to make ourselves free of any dependency
102 on memcpy() on ppc32-aix5; else programs linked with -brtl fail.
103 memcpy() is used by gcc for a struct assignment in mallinfo()
104 below. Add the following conservative implementation (memmove,
105 really). */
106#if defined(VGO_aix5)
107__attribute__((weak))
108void *memcpy(void *destV, const void *srcV, unsigned long n)
109{
110 unsigned char* src = (unsigned char*)srcV;
111 unsigned char* dest = (unsigned char*)destV;
112 unsigned long i;
113 if (dest < src) {
114 for (i = 0; i < n; i++)
115 dest[i] = src[i];
116 }
117 if (dest > src) {
118 for (i = n; i > 0; i--)
119 dest[i-1] = src[i-1];
120 }
121 return dest;
122}
123#endif
124
125
sewardj9ee81f52005-04-02 17:38:59 +0000126/*------------------------------------------------------------*/
127/*--- Replacing malloc() et al ---*/
128/*------------------------------------------------------------*/
129
130/* This struct is initially empty. Before the first use of any of
131 these functions, we make a client request which fills in the
132 fields.
133*/
134static struct vg_mallocfunc_info info;
135static int init_done;
136
137/* Startup hook - called as init section */
138static void init(void) __attribute__((constructor));
139
sewardj9ee81f52005-04-02 17:38:59 +0000140#define MALLOC_TRACE(format, args...) \
141 if (info.clo_trace_malloc) \
njn12771092005-06-18 02:18:04 +0000142 VALGRIND_INTERNAL_PRINTF(format, ## args )
sewardj9ee81f52005-04-02 17:38:59 +0000143
sewardj9ee81f52005-04-02 17:38:59 +0000144/* Below are new versions of malloc, __builtin_new, free,
145 __builtin_delete, calloc, realloc, memalign, and friends.
146
147 None of these functions are called directly - they are not meant to
sewardj0ec07f32006-01-12 12:32:32 +0000148 be found by the dynamic linker. But ALL client calls to malloc()
149 and friends wind up here eventually. They get called because
150 vg_replace_malloc installs a bunch of code redirects which causes
151 Valgrind to use these functions rather than the ones they're
152 replacing.
sewardj9ee81f52005-04-02 17:38:59 +0000153*/
154
sewardjec92a072006-10-17 01:50:31 +0000155
156/*---------------------- malloc ----------------------*/
157
sewardj9ee81f52005-04-02 17:38:59 +0000158/* Generate a replacement for 'fnname' in object 'soname', which calls
159 'vg_replacement' to allocate memory. If that fails, return NULL.
160*/
161#define ALLOC_or_NULL(soname, fnname, vg_replacement) \
162 \
sewardj0ec07f32006-01-12 12:32:32 +0000163 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \
164 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \
sewardj9ee81f52005-04-02 17:38:59 +0000165 { \
166 void* v; \
167 \
sewardj9ee81f52005-04-02 17:38:59 +0000168 if (!init_done) init(); \
sewardjcf64bd22006-01-19 03:35:37 +0000169 MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
sewardj9ee81f52005-04-02 17:38:59 +0000170 \
171 v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
172 MALLOC_TRACE(" = %p", v ); \
173 return v; \
174 }
175
176
177/* Generate a replacement for 'fnname' in object 'soname', which calls
178 'vg_replacement' to allocate memory. If that fails, it bombs the
179 system.
180*/
181#define ALLOC_or_BOMB(soname, fnname, vg_replacement) \
182 \
sewardj0ec07f32006-01-12 12:32:32 +0000183 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \
184 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \
sewardj9ee81f52005-04-02 17:38:59 +0000185 { \
186 void* v; \
187 \
sewardj9ee81f52005-04-02 17:38:59 +0000188 if (!init_done) init(); \
sewardjcf64bd22006-01-19 03:35:37 +0000189 MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
sewardj9ee81f52005-04-02 17:38:59 +0000190 \
191 v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
192 MALLOC_TRACE(" = %p", v ); \
193 if (NULL == v) { \
194 VALGRIND_PRINTF_BACKTRACE( \
195 "new/new[] failed and should throw an exception, but Valgrind\n" \
196 " cannot throw exceptions and so is aborting instead. Sorry."); \
197 _exit(1); \
198 } \
199 return v; \
200 }
201
202// Each of these lines generates a replacement function:
203// (from_so, from_fn, v's replacement)
204
205// malloc
sewardjec92a072006-10-17 01:50:31 +0000206ALLOC_or_NULL(m_libstdcxx_soname, malloc, malloc);
207ALLOC_or_NULL(m_libc_soname, malloc, malloc);
sewardj9ee81f52005-04-02 17:38:59 +0000208
sewardja0e16562005-05-05 01:16:24 +0000209
sewardjec92a072006-10-17 01:50:31 +0000210/*---------------------- new ----------------------*/
211
sewardj7c1fa872006-05-21 01:52:09 +0000212// operator new(unsigned int), not mangled (for gcc 2.96)
sewardj26820382007-05-02 16:24:30 +0000213ALLOC_or_BOMB(m_libstdcxx_soname, builtin_new, __builtin_new);
sewardjec92a072006-10-17 01:50:31 +0000214ALLOC_or_BOMB(m_libc_soname, builtin_new, __builtin_new);
sewardj7c1fa872006-05-21 01:52:09 +0000215
sewardj26820382007-05-02 16:24:30 +0000216ALLOC_or_BOMB(m_libstdcxx_soname, __builtin_new, __builtin_new);
sewardjec92a072006-10-17 01:50:31 +0000217ALLOC_or_BOMB(m_libc_soname, __builtin_new, __builtin_new);
sewardj7c1fa872006-05-21 01:52:09 +0000218
sewardjec92a072006-10-17 01:50:31 +0000219// operator new(unsigned int), GNU mangling
sewardja0e16562005-05-05 01:16:24 +0000220#if VG_WORDSIZE == 4
sewardjec92a072006-10-17 01:50:31 +0000221 ALLOC_or_BOMB(m_libstdcxx_soname, _Znwj, __builtin_new);
222 ALLOC_or_BOMB(m_libc_soname, _Znwj, __builtin_new);
sewardja0e16562005-05-05 01:16:24 +0000223#endif
sewardjec92a072006-10-17 01:50:31 +0000224
225// operator new(unsigned long), GNU mangling
226#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5)
227 ALLOC_or_BOMB(m_libstdcxx_soname, _Znwm, __builtin_new);
228 ALLOC_or_BOMB(m_libc_soname, _Znwm, __builtin_new);
229#endif
230
231// operator new(unsigned long), ARM/cfront mangling
232#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
233 ALLOC_or_BOMB(m_libC_dot_a, __nw__FUl, __builtin_new);
sewardja0e16562005-05-05 01:16:24 +0000234#endif
sewardj9b3328d2005-04-24 00:04:42 +0000235
236
sewardjec92a072006-10-17 01:50:31 +0000237/*---------------------- new nothrow ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000238
sewardjec92a072006-10-17 01:50:31 +0000239// operator new(unsigned, std::nothrow_t const&), GNU mangling
sewardja0e16562005-05-05 01:16:24 +0000240#if VG_WORDSIZE == 4
sewardjec92a072006-10-17 01:50:31 +0000241 ALLOC_or_NULL(m_libstdcxx_soname, _ZnwjRKSt9nothrow_t, __builtin_new);
242 ALLOC_or_NULL(m_libc_soname, _ZnwjRKSt9nothrow_t, __builtin_new);
sewardja0e16562005-05-05 01:16:24 +0000243#endif
tomf91889f2005-05-04 18:01:26 +0000244
sewardjec92a072006-10-17 01:50:31 +0000245// operator new(unsigned long, std::nothrow_t const&), GNU mangling
246#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
247 ALLOC_or_NULL(m_libstdcxx_soname, _ZnwmRKSt9nothrow_t, __builtin_new);
248 ALLOC_or_NULL(m_libc_soname, _ZnwmRKSt9nothrow_t, __builtin_new);
249#endif
250
251// operator new(unsigned long, std::nothrow_t const&), ARM/cfront mangling
252#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
253 ALLOC_or_NULL(m_libC_dot_a, __nw__FUlRCQ2_3std9nothrow_t, __builtin_new);
254#endif
255
256
257/*---------------------- new [] ----------------------*/
sewardja0e16562005-05-05 01:16:24 +0000258
sewardj7c1fa872006-05-21 01:52:09 +0000259// operator new[](unsigned int), not mangled (for gcc 2.96)
sewardj26820382007-05-02 16:24:30 +0000260ALLOC_or_BOMB(m_libstdcxx_soname, __builtin_vec_new, __builtin_vec_new );
sewardjec92a072006-10-17 01:50:31 +0000261ALLOC_or_BOMB(m_libc_soname, __builtin_vec_new, __builtin_vec_new );
sewardj7c1fa872006-05-21 01:52:09 +0000262
sewardjec92a072006-10-17 01:50:31 +0000263// operator new[](unsigned int), GNU mangling
sewardja0e16562005-05-05 01:16:24 +0000264#if VG_WORDSIZE == 4
sewardjec92a072006-10-17 01:50:31 +0000265 ALLOC_or_BOMB(m_libstdcxx_soname, _Znaj, __builtin_vec_new );
266 ALLOC_or_BOMB(m_libc_soname, _Znaj, __builtin_vec_new );
sewardja0e16562005-05-05 01:16:24 +0000267#endif
sewardjec92a072006-10-17 01:50:31 +0000268
269// operator new[](unsigned long), GNU mangling
270#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
271 ALLOC_or_BOMB(m_libstdcxx_soname, _Znam, __builtin_vec_new );
272 ALLOC_or_BOMB(m_libc_soname, _Znam, __builtin_vec_new );
273#endif
274
275// operator new[](unsigned long), ARM/cfront mangling
276#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
277 ALLOC_or_BOMB(m_libC_dot_a, __vn__FUl, __builtin_vec_new);
sewardja0e16562005-05-05 01:16:24 +0000278#endif
sewardj9b3328d2005-04-24 00:04:42 +0000279
sewardj9ee81f52005-04-02 17:38:59 +0000280
sewardjec92a072006-10-17 01:50:31 +0000281/*---------------------- new [] nothrow ----------------------*/
282
283// operator new[](unsigned, std::nothrow_t const&), GNU mangling
sewardja0e16562005-05-05 01:16:24 +0000284#if VG_WORDSIZE == 4
sewardjec92a072006-10-17 01:50:31 +0000285 ALLOC_or_NULL(m_libstdcxx_soname, _ZnajRKSt9nothrow_t, __builtin_vec_new );
286 ALLOC_or_NULL(m_libc_soname, _ZnajRKSt9nothrow_t, __builtin_vec_new );
sewardja0e16562005-05-05 01:16:24 +0000287#endif
tomf91889f2005-05-04 18:01:26 +0000288
sewardjec92a072006-10-17 01:50:31 +0000289// operator new[](unsigned long, std::nothrow_t const&), GNU mangling
290#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
291 ALLOC_or_NULL(m_libstdcxx_soname, _ZnamRKSt9nothrow_t, __builtin_vec_new );
292 ALLOC_or_NULL(m_libc_soname, _ZnamRKSt9nothrow_t, __builtin_vec_new );
293#endif
294
295// operator new [](unsigned long, std::nothrow_t const&), ARM/cfront mangling
296#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
297 ALLOC_or_BOMB(m_libC_dot_a, __vn__FUlRCQ2_3std9nothrow_t, __builtin_vec_new );
298#endif
299
300
301/*---------------------- free ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000302
303/* Generate a replacement for 'fnname' in object 'soname', which calls
304 'vg_replacement' to free previously allocated memory.
305*/
306#define FREE(soname, fnname, vg_replacement) \
307 \
sewardj0ec07f32006-01-12 12:32:32 +0000308 void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p); \
309 void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p) \
sewardj9ee81f52005-04-02 17:38:59 +0000310 { \
sewardjcf64bd22006-01-19 03:35:37 +0000311 if (!init_done) init(); \
sewardj9ee81f52005-04-02 17:38:59 +0000312 MALLOC_TRACE(#vg_replacement "(%p)", p ); \
313 if (p == NULL) \
314 return; \
sewardj9ee81f52005-04-02 17:38:59 +0000315 (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
316 }
317
318// free
sewardjec92a072006-10-17 01:50:31 +0000319FREE(m_libstdcxx_soname, free, free );
320FREE(m_libc_soname, free, free );
321
322
323/*---------------------- cfree ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000324
325// cfree
sewardjec92a072006-10-17 01:50:31 +0000326FREE(m_libstdcxx_soname, cfree, free );
327FREE(m_libc_soname, cfree, free );
sewardj9ee81f52005-04-02 17:38:59 +0000328
sewardjec92a072006-10-17 01:50:31 +0000329
330/*---------------------- delete ----------------------*/
sewardj7c1fa872006-05-21 01:52:09 +0000331// operator delete(void*), not mangled (for gcc 2.96)
sewardj26820382007-05-02 16:24:30 +0000332FREE(m_libstdcxx_soname, __builtin_delete, __builtin_delete );
sewardjec92a072006-10-17 01:50:31 +0000333FREE(m_libc_soname, __builtin_delete, __builtin_delete );
sewardj7c1fa872006-05-21 01:52:09 +0000334
sewardj9ee81f52005-04-02 17:38:59 +0000335// operator delete(void*), GNU mangling
sewardjec92a072006-10-17 01:50:31 +0000336FREE(m_libstdcxx_soname, _ZdlPv, __builtin_delete );
337FREE(m_libc_soname, _ZdlPv, __builtin_delete );
338
339// operator delete(void*), ARM/cfront mangling
340#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
341FREE(m_libC_dot_a, __dl__FPv, __builtin_delete );
342#endif
343
344
345/*---------------------- delete nothrow ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000346
347// operator delete(void*, std::nothrow_t const&), GNU mangling
sewardjec92a072006-10-17 01:50:31 +0000348FREE(m_libstdcxx_soname, _ZdlPvRKSt9nothrow_t, __builtin_delete );
349FREE(m_libc_soname, _ZdlPvRKSt9nothrow_t, __builtin_delete );
sewardj9ee81f52005-04-02 17:38:59 +0000350
sewardjec92a072006-10-17 01:50:31 +0000351
352/*---------------------- delete [] ----------------------*/
sewardj7c1fa872006-05-21 01:52:09 +0000353// operator delete[](void*), not mangled (for gcc 2.96)
sewardj26820382007-05-02 16:24:30 +0000354FREE(m_libstdcxx_soname, __builtin_vec_delete, __builtin_vec_delete );
sewardjec92a072006-10-17 01:50:31 +0000355FREE(m_libc_soname, __builtin_vec_delete, __builtin_vec_delete );
sewardj7c1fa872006-05-21 01:52:09 +0000356
sewardj9ee81f52005-04-02 17:38:59 +0000357// operator delete[](void*), GNU mangling
sewardjec92a072006-10-17 01:50:31 +0000358FREE(m_libstdcxx_soname, _ZdaPv, __builtin_vec_delete );
359FREE(m_libc_soname, _ZdaPv, __builtin_vec_delete );
360
361// operator delete[](void*), ARM/cfront mangling
362#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
363FREE(m_libC_dot_a, __vd__FPv, __builtin_vec_delete );
364#endif
365
366
367/*---------------------- delete [] nothrow ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000368
369// operator delete[](void*, std::nothrow_t const&), GNU mangling
sewardjec92a072006-10-17 01:50:31 +0000370FREE(m_libstdcxx_soname, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
371FREE(m_libc_soname, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
sewardj9ee81f52005-04-02 17:38:59 +0000372
373
sewardjec92a072006-10-17 01:50:31 +0000374/*---------------------- calloc ----------------------*/
375
sewardj9ee81f52005-04-02 17:38:59 +0000376#define CALLOC(soname, fnname) \
377 \
sewardj0ec07f32006-01-12 12:32:32 +0000378 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ); \
379 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ) \
sewardj9ee81f52005-04-02 17:38:59 +0000380 { \
381 void* v; \
382 \
sewardjcf64bd22006-01-19 03:35:37 +0000383 if (!init_done) init(); \
sewardj9ee81f52005-04-02 17:38:59 +0000384 MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \
sewardj9ee81f52005-04-02 17:38:59 +0000385 \
sewardj9ee81f52005-04-02 17:38:59 +0000386 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
387 MALLOC_TRACE(" = %p", v ); \
388 return v; \
389 }
390
sewardjec92a072006-10-17 01:50:31 +0000391CALLOC(m_libc_soname, calloc);
sewardj9ee81f52005-04-02 17:38:59 +0000392
393
sewardjec92a072006-10-17 01:50:31 +0000394/*---------------------- realloc ----------------------*/
395
sewardj9ee81f52005-04-02 17:38:59 +0000396#define REALLOC(soname, fnname) \
397 \
sewardj0ec07f32006-01-12 12:32:32 +0000398 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size );\
399 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size ) \
sewardj9ee81f52005-04-02 17:38:59 +0000400 { \
401 void* v; \
402 \
sewardjcf64bd22006-01-19 03:35:37 +0000403 if (!init_done) init(); \
sewardj9ee81f52005-04-02 17:38:59 +0000404 MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \
sewardj9ee81f52005-04-02 17:38:59 +0000405 \
406 if (ptrV == NULL) \
407 /* We need to call a malloc-like function; so let's use \
408 one which we know exists. */ \
sewardjec92a072006-10-17 01:50:31 +0000409 return VG_REPLACE_FUNCTION_ZU(m_libc_soname,malloc) (new_size); \
sewardj9ee81f52005-04-02 17:38:59 +0000410 if (new_size <= 0) { \
sewardjec92a072006-10-17 01:50:31 +0000411 VG_REPLACE_FUNCTION_ZU(m_libc_soname,free)(ptrV); \
njn12771092005-06-18 02:18:04 +0000412 MALLOC_TRACE(" = 0"); \
sewardj9ee81f52005-04-02 17:38:59 +0000413 return NULL; \
414 } \
sewardj9ee81f52005-04-02 17:38:59 +0000415 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
416 MALLOC_TRACE(" = %p", v ); \
417 return v; \
418 }
419
sewardjec92a072006-10-17 01:50:31 +0000420REALLOC(m_libc_soname, realloc);
sewardj9ee81f52005-04-02 17:38:59 +0000421
422
sewardjec92a072006-10-17 01:50:31 +0000423/*---------------------- memalign ----------------------*/
424
sewardj9ee81f52005-04-02 17:38:59 +0000425#define MEMALIGN(soname, fnname) \
426 \
sewardj0ec07f32006-01-12 12:32:32 +0000427 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ); \
428 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ) \
sewardj9ee81f52005-04-02 17:38:59 +0000429 { \
430 void* v; \
431 \
sewardjcf64bd22006-01-19 03:35:37 +0000432 if (!init_done) init(); \
sewardj9ee81f52005-04-02 17:38:59 +0000433 MALLOC_TRACE("memalign(al %llu, size %llu)", \
434 (ULong)alignment, (ULong)n ); \
sewardj9ee81f52005-04-02 17:38:59 +0000435 \
436 /* Round up to minimum alignment if necessary. */ \
437 if (alignment < VG_MIN_MALLOC_SZB) \
438 alignment = VG_MIN_MALLOC_SZB; \
439 \
440 /* Round up to nearest power-of-two if necessary (like glibc). */ \
441 while (0 != (alignment & (alignment - 1))) alignment++; \
442 \
sewardj9ee81f52005-04-02 17:38:59 +0000443 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
444 MALLOC_TRACE(" = %p", v ); \
445 return v; \
446 }
447
sewardjec92a072006-10-17 01:50:31 +0000448MEMALIGN(m_libc_soname, memalign);
sewardj9ee81f52005-04-02 17:38:59 +0000449
450
sewardjec92a072006-10-17 01:50:31 +0000451/*---------------------- valloc ----------------------*/
452
sewardj9ee81f52005-04-02 17:38:59 +0000453#define VALLOC(soname, fnname) \
454 \
sewardj0ec07f32006-01-12 12:32:32 +0000455 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ); \
456 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ) \
sewardj9ee81f52005-04-02 17:38:59 +0000457 { \
sewardje66f2e02006-12-30 17:45:08 +0000458 static int pszB = 0; \
459 extern int getpagesize (void); \
460 if (pszB == 0) \
461 pszB = getpagesize(); \
462 return VG_REPLACE_FUNCTION_ZU(m_libc_soname,memalign) \
463 ((SizeT)pszB, size); \
sewardj9ee81f52005-04-02 17:38:59 +0000464 }
465
sewardjec92a072006-10-17 01:50:31 +0000466VALLOC(m_libc_soname, valloc);
sewardj9ee81f52005-04-02 17:38:59 +0000467
468
sewardjec92a072006-10-17 01:50:31 +0000469/*---------------------- mallopt ----------------------*/
470
sewardj9ee81f52005-04-02 17:38:59 +0000471/* Various compatibility wrapper functions, for glibc and libstdc++. */
472
473#define MALLOPT(soname, fnname) \
474 \
sewardj0ec07f32006-01-12 12:32:32 +0000475 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ); \
476 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ) \
sewardj9ee81f52005-04-02 17:38:59 +0000477 { \
478 /* In glibc-2.2.4, 1 denotes a successful return value for \
479 mallopt */ \
480 return 1; \
481 }
482
sewardjec92a072006-10-17 01:50:31 +0000483MALLOPT(m_libc_soname, mallopt);
sewardj9ee81f52005-04-02 17:38:59 +0000484
485
sewardjec92a072006-10-17 01:50:31 +0000486/*---------------------- malloc_trim ----------------------*/
njnceb02662006-07-08 08:29:20 +0000487// Documentation says:
488// malloc_trim(size_t pad);
489//
490// If possible, gives memory back to the system (via negative arguments to
491// sbrk) if there is unused memory at the `high' end of the malloc pool.
492// You can call this after freeing large blocks of memory to potentially
493// reduce the system-level memory requirements of a program. However, it
494// cannot guarantee to reduce memory. Under some allocation patterns,
495// some large free blocks of memory will be locked between two used
496// chunks, so they cannot be given back to the system.
497//
498// The `pad' argument to malloc_trim represents the amount of free
499// trailing space to leave untrimmed. If this argument is zero, only the
500// minimum amount of memory to maintain internal data structures will be
501// left (one page or less). Non-zero arguments can be supplied to maintain
502// enough trailing space to service future expected allocations without
503// having to re-obtain memory from the system.
504//
505// Malloc_trim returns 1 if it actually released any memory, else 0. On
506// systems that do not support "negative sbrks", it will always return 0.
507//
508// For simplicity, we always return 0.
509#define MALLOC_TRIM(soname, fnname) \
510 \
511 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ); \
512 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ) \
513 { \
514 /* 0 denotes that malloc_trim() either wasn't able \
515 to do anything, or was not implemented */ \
516 return 0; \
517 }
518
sewardjec92a072006-10-17 01:50:31 +0000519MALLOC_TRIM(m_libc_soname, malloc_trim);
njnceb02662006-07-08 08:29:20 +0000520
521
sewardjec92a072006-10-17 01:50:31 +0000522/*---------------------- posix_memalign ----------------------*/
523
sewardj9ee81f52005-04-02 17:38:59 +0000524#define POSIX_MEMALIGN(soname, fnname) \
525 \
sewardj0ec07f32006-01-12 12:32:32 +0000526 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \
527 SizeT alignment, SizeT size ); \
528 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \
529 SizeT alignment, SizeT size ) \
sewardj9ee81f52005-04-02 17:38:59 +0000530 { \
531 void *mem; \
532 \
533 /* Test whether the alignment argument is valid. It must be \
534 a power of two multiple of sizeof (void *). */ \
535 if (alignment % sizeof (void *) != 0 \
536 || (alignment & (alignment - 1)) != 0) \
537 return VKI_EINVAL; \
538 \
sewardjec92a072006-10-17 01:50:31 +0000539 mem = VG_REPLACE_FUNCTION_ZU(m_libc_soname,memalign)(alignment, size); \
sewardj9ee81f52005-04-02 17:38:59 +0000540 \
541 if (mem != NULL) { \
542 *memptr = mem; \
543 return 0; \
544 } \
545 \
546 return VKI_ENOMEM; \
547 }
548
sewardjec92a072006-10-17 01:50:31 +0000549POSIX_MEMALIGN(m_libc_soname, posix_memalign);
sewardj9ee81f52005-04-02 17:38:59 +0000550
551
sewardjec92a072006-10-17 01:50:31 +0000552/*---------------------- malloc_usable_size ----------------------*/
553
sewardj9ee81f52005-04-02 17:38:59 +0000554#define MALLOC_USABLE_SIZE(soname, fnname) \
555 \
sewardj0ec07f32006-01-12 12:32:32 +0000556 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ); \
557 int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ) \
sewardj9ee81f52005-04-02 17:38:59 +0000558 { \
559 SizeT pszB; \
560 \
sewardjcf64bd22006-01-19 03:35:37 +0000561 if (!init_done) init(); \
sewardj9ee81f52005-04-02 17:38:59 +0000562 MALLOC_TRACE("malloc_usable_size(%p)", p ); \
563 if (NULL == p) \
564 return 0; \
565 \
sewardj9ee81f52005-04-02 17:38:59 +0000566 pszB = (SizeT)VALGRIND_NON_SIMD_CALL2( info.arena_payload_szB, \
567 VG_AR_CLIENT, p ); \
568 MALLOC_TRACE(" = %llu", (ULong)pszB ); \
569 \
570 return pszB; \
571 }
572
sewardjec92a072006-10-17 01:50:31 +0000573MALLOC_USABLE_SIZE(m_libc_soname, malloc_usable_size);
sewardj9ee81f52005-04-02 17:38:59 +0000574
575
sewardjec92a072006-10-17 01:50:31 +0000576/*---------------------- (unimplemented) ----------------------*/
577
sewardj9ee81f52005-04-02 17:38:59 +0000578/* Bomb out if we get any of these. */
579
580static void panic(const char *str)
581{
582 VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s", str);
583 _exit(99);
584 *(int *)0 = 'x';
585}
586
587#define PANIC(soname, fnname) \
588 \
sewardj0ec07f32006-01-12 12:32:32 +0000589 void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
590 void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \
sewardj9ee81f52005-04-02 17:38:59 +0000591 { \
592 panic(#fnname); \
593 }
594
sewardjec92a072006-10-17 01:50:31 +0000595PANIC(m_libc_soname, pvalloc);
596PANIC(m_libc_soname, malloc_stats);
597PANIC(m_libc_soname, malloc_get_state);
598PANIC(m_libc_soname, malloc_set_state);
599
600
601/*---------------------- mallinfo ----------------------*/
sewardj9ee81f52005-04-02 17:38:59 +0000602
njn088bfb42005-08-17 05:01:37 +0000603// mi must be static; if it is auto then Memcheck thinks it is
604// uninitialised when used by the caller of this function, because Memcheck
605// doesn't know that the call to mallinfo fills in mi.
sewardj9ee81f52005-04-02 17:38:59 +0000606#define MALLINFO(soname, fnname) \
607 \
sewardj0ec07f32006-01-12 12:32:32 +0000608 struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
609 struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \
sewardj9ee81f52005-04-02 17:38:59 +0000610 { \
njn088bfb42005-08-17 05:01:37 +0000611 static struct vg_mallinfo mi; \
njn088bfb42005-08-17 05:01:37 +0000612 if (!init_done) init(); \
sewardjcf64bd22006-01-19 03:35:37 +0000613 MALLOC_TRACE("mallinfo()"); \
njn088bfb42005-08-17 05:01:37 +0000614 (void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \
sewardj9ee81f52005-04-02 17:38:59 +0000615 return mi; \
616 }
617
sewardjec92a072006-10-17 01:50:31 +0000618MALLINFO(m_libc_soname, mallinfo);
sewardj9ee81f52005-04-02 17:38:59 +0000619
620
621/* All the code in here is unused until this function is called */
622
623static void init(void)
624{
625 int res;
626
627 if (init_done)
628 return;
629
630 init_done = 1;
631
sewardj0ec07f32006-01-12 12:32:32 +0000632 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__GET_MALLOCFUNCS, &info,
sewardj9af10a12006-02-01 14:59:42 +0000633 0, 0, 0, 0);
sewardj9ee81f52005-04-02 17:38:59 +0000634}
635
636/*--------------------------------------------------------------------*/
637/*--- end vg_replace_malloc.c ---*/
638/*--------------------------------------------------------------------*/