]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_replacemalloc/vg_replace_malloc.c
42e4731cae38a6841154aefcd9ab4be3fd165aad
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_replacemalloc / vg_replace_malloc.c
1
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
11    Copyright (C) 2000-2010 Julian Seward 
12       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.  
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.
38
39    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
41    the functions that will be called via 'info'.
42
43    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.
45
46    IMPORTANT: this file must not contain any floating point code, nor
47    any integer division.  This is because on ARM these can cause calls
48    to helper functions, which will be unresolved within this .so.
49    Although it is usually the case that the client's ld.so instance
50    can bind them at runtime to the relevant functions in the client
51    executable, there is no guarantee of this; and so the client may
52    die via a runtime link failure.  Hence the only safe approach is to
53    avoid such function calls in the first place.  See "#define CALLOC"
54    below for a specific example.
55
56    A useful command is
57       for f in `find . -name "*preload*.so*"` ; \
58           do nm -A $f | grep " U " ; \
59       done
60
61    to see all the undefined symbols in all the preload shared objects.
62    ------------------------------------------------------------------ */
63
64 #include "pub_core_basics.h"
65 #include "pub_core_vki.h"           // VKI_EINVAL, VKI_ENOMEM
66 #include "pub_core_clreq.h"         // for VALGRIND_INTERNAL_PRINTF,
67                                     //   VALGRIND_NON_SIMD_CALL[12]
68 #include "pub_core_debuginfo.h"     // needed for pub_core_redir.h :(
69 #include "pub_core_mallocfree.h"    // for VG_MIN_MALLOC_SZB, VG_AR_CLIENT
70 #include "pub_core_redir.h"         // for VG_REPLACE_FUNCTION_*
71 #include "pub_core_replacemalloc.h"
72
73
74 /* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
75    mangling, could be supported properly by the redirects in this
76    module.  Except we can't because it doesn't put its allocation
77    functions in libpgc.so but instead hardwires them into the
78    compilation unit holding main(), which makes them impossible to
79    intercept directly.  Fortunately those fns seem to route everything
80    through to malloc/free.
81
82    mid-06: could be improved, since we can now intercept in the main
83    executable too.
84 */
85
86 __attribute__ ((__noreturn__))
87 extern void _exit(int);
88
89 /* Apparently it is necessary to make ourselves free of any dependency
90    on memcpy() on ppc32-aix5; else programs linked with -brtl fail.
91    memcpy() is used by gcc for a struct assignment in mallinfo()
92    below.  Add the following conservative implementation (memmove,
93    really). */
94 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
95 __attribute__((weak))
96 void *memcpy(void *destV, const void *srcV, unsigned long n)
97 {
98    unsigned char* src = (unsigned char*)srcV;
99    unsigned char* dest = (unsigned char*)destV;
100    unsigned long  i;
101    if (dest < src) {
102       for (i = 0; i < n; i++)
103          dest[i] = src[i];
104    }
105    if (dest > src) {
106       for (i = n; i > 0; i--)
107          dest[i-1] = src[i-1];
108    }
109    return dest;
110 }
111 #endif
112
113
114 /* Compute the high word of the double-length unsigned product of U
115    and V.  This is for calloc argument overflow checking; see comments
116    below.  Algorithm as described in Hacker's Delight, chapter 8. */
117 static UWord umulHW ( UWord u, UWord v )
118 {
119    UWord u0, v0, w0, rHi;
120    UWord u1, v1, w1,w2,t;
121    UWord halfMask  = sizeof(UWord)==4 ? (UWord)0xFFFF
122                                       : (UWord)0xFFFFFFFFULL;
123    UWord halfShift = sizeof(UWord)==4 ? 16 : 32;
124    u0  = u & halfMask;
125    u1  = u >> halfShift;
126    v0  = v & halfMask;
127    v1  = v >> halfShift;
128    w0  = u0 * v0;
129    t   = u1 * v0 + (w0 >> halfShift);
130    w1  = t & halfMask;
131    w2  = t >> halfShift;
132    w1  = u0 * v1 + w1;
133    rHi = u1 * v1 + w2 + (w1 >> halfShift);
134    return rHi;
135 }
136
137
138 /*------------------------------------------------------------*/
139 /*--- Replacing malloc() et al                             ---*/
140 /*------------------------------------------------------------*/
141
142 /* This struct is initially empty.  Before the first use of any of
143    these functions, we make a client request which fills in the
144    fields. 
145 */
146 static struct vg_mallocfunc_info info;
147 static int init_done;
148
149 /* Startup hook - called as init section */
150 __attribute__((constructor))
151 static void init(void);
152
153 #define MALLOC_TRACE(format, args...)  \
154    if (info.clo_trace_malloc) {        \
155       VALGRIND_INTERNAL_PRINTF(format, ## args ); }
156
157 /* Below are new versions of malloc, __builtin_new, free, 
158    __builtin_delete, calloc, realloc, memalign, and friends.
159
160    None of these functions are called directly - they are not meant to
161    be found by the dynamic linker.  But ALL client calls to malloc()
162    and friends wind up here eventually.  They get called because
163    vg_replace_malloc installs a bunch of code redirects which causes
164    Valgrind to use these functions rather than the ones they're
165    replacing.
166 */
167
168
169 /*---------------------- malloc ----------------------*/
170
171 /* Generate a replacement for 'fnname' in object 'soname', which calls
172    'vg_replacement' to allocate memory.  If that fails, return NULL.
173 */
174 #define ALLOC_or_NULL(soname, fnname, vg_replacement) \
175    \
176    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \
177    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n)  \
178    { \
179       void* v; \
180       \
181       if (!init_done) init(); \
182       MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
183       \
184       v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
185       MALLOC_TRACE(" = %p\n", v ); \
186       return v; \
187    }
188
189 #define ZONEALLOC_or_NULL(soname, fnname, vg_replacement) \
190    \
191    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, SizeT n); \
192    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, SizeT n)  \
193    { \
194       void* v; \
195       \
196       if (!init_done) init(); \
197       MALLOC_TRACE(#fnname "(%p, %llu)", zone, (ULong)n ); \
198       \
199       v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
200       MALLOC_TRACE(" = %p\n", v ); \
201       return v; \
202    }
203
204
205 /* Generate a replacement for 'fnname' in object 'soname', which calls
206    'vg_replacement' to allocate memory.  If that fails, it bombs the
207    system.
208 */
209 #define ALLOC_or_BOMB(soname, fnname, vg_replacement)  \
210    \
211    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \
212    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n)  \
213    { \
214       void* v; \
215       \
216       if (!init_done) init(); \
217       MALLOC_TRACE(#fnname "(%llu)", (ULong)n );        \
218       \
219       v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
220       MALLOC_TRACE(" = %p\n", v ); \
221       if (NULL == v) { \
222          VALGRIND_PRINTF_BACKTRACE( \
223             "new/new[] failed and should throw an exception, but Valgrind\n"); \
224          VALGRIND_PRINTF_BACKTRACE( \
225             "   cannot throw exceptions and so is aborting instead.  Sorry.\n"); \
226             _exit(1); \
227       } \
228       return v; \
229    }
230
231 // Each of these lines generates a replacement function:
232 //     (from_so, from_fn,  v's replacement)
233
234 // malloc
235 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, malloc,      malloc);
236 ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
237 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
238 ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc_common, malloc);
239 #elif defined(VGO_darwin)
240 ZONEALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc_zone_malloc, malloc);
241 #endif
242
243
244 /*---------------------- new ----------------------*/
245
246 // operator new(unsigned int), not mangled (for gcc 2.96)
247 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  builtin_new,    __builtin_new);
248 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       builtin_new,    __builtin_new);
249
250 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  __builtin_new,  __builtin_new);
251 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       __builtin_new,  __builtin_new);
252
253 // operator new(unsigned int), GNU mangling
254 #if VG_WORDSIZE == 4
255  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj,          __builtin_new);
256  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwj,          __builtin_new);
257 #endif
258
259 // operator new(unsigned long), GNU mangling
260 #if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGO_darwin)
261  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm,          __builtin_new);
262  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwm,          __builtin_new);
263 #endif
264
265 // operator new(unsigned long), ARM/cfront mangling
266 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
267  ALLOC_or_BOMB(VG_Z_LIBC_DOT_A,       __nw__FUl,      __builtin_new);
268 #endif
269
270
271 /*---------------------- new nothrow ----------------------*/
272
273 // operator new(unsigned, std::nothrow_t const&), GNU mangling
274 #if VG_WORDSIZE == 4
275  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t,  __builtin_new);
276  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwjRKSt9nothrow_t,  __builtin_new);
277 #endif
278
279 // operator new(unsigned long, std::nothrow_t const&), GNU mangling
280 #if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) || defined(VGO_darwin)
281  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t,  __builtin_new);
282  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwmRKSt9nothrow_t,  __builtin_new);
283 #endif
284
285 // operator new(unsigned long, std::nothrow_t const&), ARM/cfront mangling
286 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
287  ALLOC_or_NULL(VG_Z_LIBC_DOT_A,    __nw__FUlRCQ2_3std9nothrow_t, __builtin_new);
288 #endif
289
290
291 /*---------------------- new [] ----------------------*/
292
293 // operator new[](unsigned int), not mangled (for gcc 2.96)
294 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  __builtin_vec_new, __builtin_vec_new );
295 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       __builtin_vec_new, __builtin_vec_new );
296
297 // operator new[](unsigned int), GNU mangling
298 #if VG_WORDSIZE == 4
299  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj,             __builtin_vec_new );
300  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znaj,             __builtin_vec_new );
301 #endif
302
303 // operator new[](unsigned long), GNU mangling
304 #if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) || defined(VGO_darwin)
305  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam,             __builtin_vec_new );
306  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znam,             __builtin_vec_new );
307 #endif
308
309 // operator new[](unsigned long), ARM/cfront mangling
310 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
311  ALLOC_or_BOMB(VG_Z_LIBC_DOT_A,       __vn__FUl,         __builtin_vec_new);
312 #endif
313
314
315 /*---------------------- new [] nothrow ----------------------*/
316
317 // operator new[](unsigned, std::nothrow_t const&), GNU mangling
318 #if VG_WORDSIZE == 4
319  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
320  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnajRKSt9nothrow_t, __builtin_vec_new );
321 #endif
322
323 // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
324 #if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) || defined(VGO_darwin)
325  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
326  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnamRKSt9nothrow_t, __builtin_vec_new );
327 #endif
328
329 // operator new [](unsigned long, std::nothrow_t const&), ARM/cfront mangling
330 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
331  ALLOC_or_BOMB(VG_Z_LIBC_DOT_A,   __vn__FUlRCQ2_3std9nothrow_t, __builtin_vec_new );
332 #endif
333
334
335 /*---------------------- free ----------------------*/
336
337 /* Generate a replacement for 'fnname' in object 'soname', which calls
338    'vg_replacement' to free previously allocated memory.
339 */
340 #define ZONEFREE(soname, fnname, vg_replacement) \
341    \
342    void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, void *p); \
343    void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *zone, void *p)  \
344    { \
345       if (!init_done) init(); \
346       MALLOC_TRACE(#vg_replacement "(%p, %p)\n", zone, p ); \
347       if (p == NULL)  \
348          return; \
349       (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
350    }
351
352 #define FREE(soname, fnname, vg_replacement) \
353    \
354    void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p); \
355    void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p)  \
356    { \
357       if (!init_done) init(); \
358       MALLOC_TRACE(#vg_replacement "(%p)\n", p ); \
359       if (p == NULL)  \
360          return; \
361       (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
362    }
363
364 // free
365 FREE(VG_Z_LIBSTDCXX_SONAME,  free,                 free );
366 FREE(VG_Z_LIBC_SONAME,       free,                 free );
367 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
368 FREE(VG_Z_LIBC_SONAME,       free_common,          free );
369 #elif defined(VGO_darwin)
370 ZONEFREE(VG_Z_LIBC_SONAME,   malloc_zone_free,     free );
371 #endif
372
373
374 /*---------------------- cfree ----------------------*/
375
376 // cfree
377 FREE(VG_Z_LIBSTDCXX_SONAME,  cfree,                free );
378 FREE(VG_Z_LIBC_SONAME,       cfree,                free );
379
380
381 /*---------------------- delete ----------------------*/
382 // operator delete(void*), not mangled (for gcc 2.96)
383 FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_delete,     __builtin_delete );
384 FREE(VG_Z_LIBC_SONAME,        __builtin_delete,     __builtin_delete );
385
386 // operator delete(void*), GNU mangling
387 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPv,               __builtin_delete );
388 FREE(VG_Z_LIBC_SONAME,       _ZdlPv,               __builtin_delete );
389
390 // operator delete(void*), ARM/cfront mangling
391 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
392 FREE(VG_Z_LIBC_DOT_A,        __dl__FPv,            __builtin_delete );
393 #endif
394
395
396 /*---------------------- delete nothrow ----------------------*/
397
398 // operator delete(void*, std::nothrow_t const&), GNU mangling
399 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
400 FREE(VG_Z_LIBC_SONAME,      _ZdlPvRKSt9nothrow_t,  __builtin_delete );
401
402
403 /*---------------------- delete [] ----------------------*/
404 // operator delete[](void*), not mangled (for gcc 2.96)
405 FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_vec_delete, __builtin_vec_delete );
406 FREE(VG_Z_LIBC_SONAME,        __builtin_vec_delete, __builtin_vec_delete );
407
408 // operator delete[](void*), GNU mangling
409 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPv,               __builtin_vec_delete );
410 FREE(VG_Z_LIBC_SONAME,       _ZdaPv,               __builtin_vec_delete );
411
412 // operator delete[](void*), ARM/cfront mangling
413 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
414 FREE(VG_Z_LIBC_DOT_A,        __vd__FPv,            __builtin_vec_delete );
415 #endif
416
417
418 /*---------------------- delete [] nothrow ----------------------*/
419
420 // operator delete[](void*, std::nothrow_t const&), GNU mangling
421 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
422 FREE(VG_Z_LIBC_SONAME,       _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
423
424
425 /*---------------------- calloc ----------------------*/
426
427 #define ZONECALLOC(soname, fnname) \
428    \
429    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT nmemb, SizeT size ); \
430    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT nmemb, SizeT size )  \
431    { \
432       void* v; \
433       \
434       if (!init_done) init(); \
435       MALLOC_TRACE("calloc(%p, %llu,%llu)", zone, (ULong)nmemb, (ULong)size ); \
436       \
437       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
438       MALLOC_TRACE(" = %p\n", v ); \
439       return v; \
440    }
441
442 #define CALLOC(soname, fnname) \
443    \
444    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ); \
445    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size )  \
446    { \
447       void* v; \
448       \
449       if (!init_done) init(); \
450       MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \
451       \
452       /* Protect against overflow.  See bug 24078. (that bug number is
453          invalid.  Which one really?) */ \
454       /* But don't use division, since that produces an external symbol
455          reference on ARM, in the form of a call to __aeabi_uidiv.  It's
456          normally OK, because ld.so manages to resolve it to something in the
457          executable, or one of its shared objects.  But that isn't guaranteed
458          to be the case, and it has been observed to fail in rare cases, eg:
459             echo x | valgrind /bin/sed -n "s/.*-\>\ //p"
460          So instead compute the high word of the product and check it is zero. */ \
461       if (umulHW(size, nmemb) != 0) return NULL; \
462       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
463       MALLOC_TRACE(" = %p\n", v ); \
464       return v; \
465    }
466
467 CALLOC(VG_Z_LIBC_SONAME, calloc);
468 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
469 CALLOC(VG_Z_LIBC_SONAME, calloc_common);
470 #elif defined(VGO_darwin)
471 ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
472 #endif
473
474
475 /*---------------------- realloc ----------------------*/
476
477 #define ZONEREALLOC(soname, fnname) \
478    \
479    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, void* ptrV, SizeT new_size );\
480    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, void* ptrV, SizeT new_size ) \
481    { \
482       void* v; \
483       \
484       if (!init_done) init(); \
485       MALLOC_TRACE("realloc(%p,%p,%llu)", zone, ptrV, (ULong)new_size ); \
486       \
487       if (ptrV == NULL) \
488          /* We need to call a malloc-like function; so let's use \
489             one which we know exists. GrP fixme use zonemalloc instead? */ \
490          return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,malloc) (new_size); \
491       if (new_size <= 0) { \
492          VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,free)(ptrV); \
493          MALLOC_TRACE(" = 0\n"); \
494          return NULL; \
495       } \
496       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
497       MALLOC_TRACE(" = %p\n", v ); \
498       return v; \
499    }
500
501 #define REALLOC(soname, fnname) \
502    \
503    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size );\
504    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size ) \
505    { \
506       void* v; \
507       \
508       if (!init_done) init(); \
509       MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \
510       \
511       if (ptrV == NULL) \
512          /* We need to call a malloc-like function; so let's use \
513             one which we know exists. */ \
514          return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,malloc) (new_size); \
515       if (new_size <= 0) { \
516          VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,free)(ptrV); \
517          MALLOC_TRACE(" = 0\n"); \
518          return NULL; \
519       } \
520       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
521       MALLOC_TRACE(" = %p\n", v ); \
522       return v; \
523    }
524
525 REALLOC(VG_Z_LIBC_SONAME, realloc);
526 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
527 REALLOC(VG_Z_LIBC_SONAME, realloc_common);
528 #elif defined(VGO_darwin)
529 ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
530 #endif
531
532
533 /*---------------------- memalign ----------------------*/
534
535 #define ZONEMEMALIGN(soname, fnname) \
536    \
537    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT alignment, SizeT n ); \
538    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT alignment, SizeT n ) \
539    { \
540       void* v; \
541       \
542       if (!init_done) init(); \
543       MALLOC_TRACE("memalign(%p, al %llu, size %llu)", \
544                    zone, (ULong)alignment, (ULong)n );  \
545       \
546       /* Round up to minimum alignment if necessary. */ \
547       if (alignment < VG_MIN_MALLOC_SZB) \
548          alignment = VG_MIN_MALLOC_SZB; \
549       \
550       /* Round up to nearest power-of-two if necessary (like glibc). */ \
551       while (0 != (alignment & (alignment - 1))) alignment++; \
552       \
553       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
554       MALLOC_TRACE(" = %p\n", v ); \
555       return v; \
556    }
557
558 #define MEMALIGN(soname, fnname) \
559    \
560    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ); \
561    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n )  \
562    { \
563       void* v; \
564       \
565       if (!init_done) init(); \
566       MALLOC_TRACE("memalign(al %llu, size %llu)", \
567                    (ULong)alignment, (ULong)n ); \
568       \
569       /* Round up to minimum alignment if necessary. */ \
570       if (alignment < VG_MIN_MALLOC_SZB) \
571          alignment = VG_MIN_MALLOC_SZB; \
572       \
573       /* Round up to nearest power-of-two if necessary (like glibc). */ \
574       while (0 != (alignment & (alignment - 1))) alignment++; \
575       \
576       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
577       MALLOC_TRACE(" = %p\n", v ); \
578       return v; \
579    }
580
581 MEMALIGN(VG_Z_LIBC_SONAME, memalign);
582 #if defined(VGO_darwin)
583 ZONEMEMALIGN(VG_Z_LIBC_SONAME, malloc_zone_memalign);
584 #endif
585
586
587 /*---------------------- valloc ----------------------*/
588
589 static int local__getpagesize ( void ) {
590 #  if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
591    return 4096; /* kludge - toc problems prevent calling getpagesize() */
592 #  else
593    extern int getpagesize (void);
594    return getpagesize();
595 #  endif
596 }
597
598 #define VALLOC(soname, fnname) \
599    \
600    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ); \
601    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size )  \
602    { \
603       static int pszB = 0; \
604       if (pszB == 0) \
605          pszB = local__getpagesize(); \
606       return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign) \
607                 ((SizeT)pszB, size); \
608    }
609
610 #define ZONEVALLOC(soname, fnname) \
611    \
612    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT size ); \
613    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void *zone, SizeT size )  \
614    { \
615       static int pszB = 0; \
616       extern int getpagesize (void); \
617       if (pszB == 0) \
618          pszB = getpagesize(); \
619       return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign) \
620                 ((SizeT)pszB, size); \
621    }
622
623 VALLOC(VG_Z_LIBC_SONAME, valloc);
624 #if defined(VGO_darwin)
625 ZONEVALLOC(VG_Z_LIBC_SONAME, malloc_zone_valloc);
626 #endif
627
628
629 /*---------------------- mallopt ----------------------*/
630
631 /* Various compatibility wrapper functions, for glibc and libstdc++. */
632
633 #define MALLOPT(soname, fnname) \
634    \
635    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ); \
636    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value )  \
637    { \
638       /* In glibc-2.2.4, 1 denotes a successful return value for \
639          mallopt */ \
640       return 1; \
641    }
642
643 MALLOPT(VG_Z_LIBC_SONAME, mallopt);
644
645
646 /*---------------------- malloc_trim ----------------------*/
647 // Documentation says:
648 //   malloc_trim(size_t pad);
649 // 
650 //   If possible, gives memory back to the system (via negative arguments to
651 //   sbrk) if there is unused memory at the `high' end of the malloc pool.
652 //   You can call this after freeing large blocks of memory to potentially
653 //   reduce the system-level memory requirements of a program. However, it
654 //   cannot guarantee to reduce memory.  Under some allocation patterns,
655 //   some large free blocks of memory will be locked between two used
656 //   chunks, so they cannot be given back to the system.
657 // 
658 //   The `pad' argument to malloc_trim represents the amount of free
659 //   trailing space to leave untrimmed. If this argument is zero, only the
660 //   minimum amount of memory to maintain internal data structures will be
661 //   left (one page or less). Non-zero arguments can be supplied to maintain
662 //   enough trailing space to service future expected allocations without
663 //   having to re-obtain memory from the system.
664 // 
665 //   Malloc_trim returns 1 if it actually released any memory, else 0. On
666 //   systems that do not support "negative sbrks", it will always return 0. 
667 //
668 // For simplicity, we always return 0.
669 #define MALLOC_TRIM(soname, fnname) \
670    \
671    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ); \
672    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad )  \
673    { \
674       /* 0 denotes that malloc_trim() either wasn't able \
675          to do anything, or was not implemented */ \
676       return 0; \
677    }
678
679 MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
680
681
682 /*---------------------- posix_memalign ----------------------*/
683
684 #define POSIX_MEMALIGN(soname, fnname) \
685    \
686    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \
687                                                  SizeT alignment, SizeT size ); \
688    int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \
689                                                  SizeT alignment, SizeT size )  \
690    { \
691       void *mem; \
692       \
693       /* Test whether the alignment argument is valid.  It must be \
694          a power of two multiple of sizeof (void *).  */ \
695       if (alignment % sizeof (void *) != 0 \
696           || (alignment & (alignment - 1)) != 0) \
697          return VKI_EINVAL; \
698       \
699       mem = VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign)(alignment, size); \
700       \
701       if (mem != NULL) { \
702         *memptr = mem; \
703         return 0; \
704       } \
705       \
706       return VKI_ENOMEM; \
707    }
708
709 POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
710 #if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
711 /* 27 Nov 07: it appears that xlc links into executables, a
712    posix_memalign, which calls onwards to memalign_common, with the
713    same args. */
714 POSIX_MEMALIGN(VG_Z_LIBC_SONAME, memalign_common);
715 #endif
716
717
718 /*---------------------- malloc_usable_size ----------------------*/
719
720 #define MALLOC_USABLE_SIZE(soname, fnname) \
721    \
722    SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ); \
723    SizeT VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p )  \
724    {  \
725       SizeT pszB; \
726       \
727       if (!init_done) init(); \
728       MALLOC_TRACE("malloc_usable_size(%p)", p ); \
729       if (NULL == p) \
730          return 0; \
731       \
732       pszB = (SizeT)VALGRIND_NON_SIMD_CALL1( info.tl_malloc_usable_size, p ); \
733       MALLOC_TRACE(" = %llu\n", (ULong)pszB ); \
734       \
735       return pszB; \
736    }
737
738 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
739 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
740
741
742 /*---------------------- (unimplemented) ----------------------*/
743
744 /* Bomb out if we get any of these. */
745
746 static void panic(const char *str)
747 {
748    VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s\n", str);
749    _exit(99);
750    *(int *)0 = 'x';
751 }
752
753 #define PANIC(soname, fnname) \
754    \
755    void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
756    void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void )  \
757    { \
758       panic(#fnname); \
759    }
760
761 PANIC(VG_Z_LIBC_SONAME, pvalloc);
762 PANIC(VG_Z_LIBC_SONAME, malloc_get_state);
763 PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
764
765 #define MALLOC_STATS(soname, fnname) \
766    \
767    void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
768    void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void )  \
769    { \
770       /* Valgrind's malloc_stats implementation does nothing. */ \
771    } 
772
773 MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats);
774
775
776 /*---------------------- mallinfo ----------------------*/
777
778 // mi must be static;  if it is auto then Memcheck thinks it is
779 // uninitialised when used by the caller of this function, because Memcheck
780 // doesn't know that the call to mallinfo fills in mi.
781 #define MALLINFO(soname, fnname) \
782    \
783    struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
784    struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void )  \
785    { \
786       static struct vg_mallinfo mi; \
787       if (!init_done) init(); \
788       MALLOC_TRACE("mallinfo()\n"); \
789       (void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \
790       return mi; \
791    }
792
793 MALLINFO(VG_Z_LIBC_SONAME, mallinfo);
794
795
796 #if defined(VGO_darwin)
797
798 static vki_malloc_zone_t vg_default_zone = {
799     NULL, // reserved
800     NULL, // reserved
801     NULL, // GrP fixme malloc_size
802     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_malloc), 
803     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_calloc), 
804     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_valloc), 
805     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_free), 
806     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_realloc), 
807     NULL, // GrP fixme destroy
808     "ValgrindMallocZone", 
809     NULL, // batch_malloc
810     NULL, // batch_free
811     NULL, // GrP fixme introspect
812     2,  // version (GrP fixme 3?)
813     // DDD: this field exists in Mac OS 10.6, but not 10.5.
814     #if 0
815     (void*)VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, malloc_zone_memalign)
816     #endif
817 };
818
819 #define DEFAULT_ZONE(soname, fnname) \
820    \
821    void *VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \
822    void *VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void )  \
823    { \
824       return &vg_default_zone; \
825    }
826
827 #if defined(VGO_darwin)
828 DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_zone_from_ptr);
829 DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone);
830 #endif
831
832 // GrP fixme bypass libc's use of zone->introspect->check
833 #define ZONE_CHECK(soname, fnname) \
834                                    \
835    int VG_REPLACE_FUNCTION_ZU(soname, fnname)(void* zone); \
836    int VG_REPLACE_FUNCTION_ZU(soname, fnname)(void* zone)  \
837    { \
838       return 1; \
839    }
840
841 #if defined(VGO_darwin)
842 ZONE_CHECK(VG_Z_LIBC_SONAME, malloc_zone_check);    
843 #endif
844
845 #endif
846
847
848 /* All the code in here is unused until this function is called */
849
850 __attribute__((constructor))
851 static void init(void)
852 {
853    int res;
854
855    // This doesn't look thread-safe, but it should be ok... Bart says:
856    //   
857    //   Every program I know of calls malloc() at least once before calling
858    //   pthread_create().  So init_done gets initialized before any thread is
859    //   created, and is only read when multiple threads are active
860    //   simultaneously.  Such an access pattern is safe.
861    //
862    //   If the assignment to the variable init_done would be triggering a race
863    //   condition, both DRD and Helgrind would report this race.
864    // 
865    //   By the way, although the init() function in
866    //   coregrind/m_replacemalloc/vg_replace_malloc.c has been declared
867    //   __attribute__((constructor)), it is not safe to remove the variable
868    //   init_done. This is because it is possible that malloc() and hence
869    //   init() gets called before shared library initialization finished.
870    //
871    if (init_done)
872       return;
873
874    init_done = 1;
875
876    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__GET_MALLOCFUNCS, &info,
877                               0, 0, 0, 0);
878 }
879
880 /*--------------------------------------------------------------------*/
881 /*--- end                                                          ---*/
882 /*--------------------------------------------------------------------*/