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-2013 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/* Assignment of behavioural equivalence class tags: 1NNNP is intended
74   to be reserved for the Valgrind core.  Current usage:
75
76   10010 ALLOC_or_NULL
77   10020 ZONEALLOC_or_NULL
78   10030 ALLOC_or_BOMB
79   10040 ZONEFREE
80   10050 FREE
81   10060 ZONECALLOC
82   10070 CALLOC
83   10080 ZONEREALLOC
84   10090 REALLOC
85   10100 ZONEMEMALIGN
86   10110 MEMALIGN
87   10120 VALLOC
88   10130 ZONEVALLOC
89   10140 MALLOPT
90   10150 MALLOC_TRIM
91   10160 POSIX_MEMALIGN
92   10170 MALLOC_USABLE_SIZE
93   10180 PANIC
94   10190 MALLOC_STATS
95   10200 MALLINFO
96   10210 DEFAULT_ZONE
97   10220 ZONE_CHECK
98*/
99
100/* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
101   mangling, could be supported properly by the redirects in this
102   module.  Except we can't because it doesn't put its allocation
103   functions in libpgc.so but instead hardwires them into the
104   compilation unit holding main(), which makes them impossible to
105   intercept directly.  Fortunately those fns seem to route everything
106   through to malloc/free.
107
108   mid-06: could be improved, since we can now intercept in the main
109   executable too.
110*/
111
112
113
114/* Call here to exit if we can't continue.  On Android we can't call
115   _exit for some reason, so we have to blunt-instrument it. */
116__attribute__ ((__noreturn__))
117static inline void my_exit ( int x )
118{
119#  if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android)
120   __asm__ __volatile__(".word 0xFFFFFFFF");
121   while (1) {}
122#  elif defined(VGPV_x86_linux_android)
123   __asm__ __volatile__("ud2");
124   while (1) {}
125#  else
126   extern __attribute__ ((__noreturn__)) void _exit(int status);
127   _exit(x);
128#  endif
129}
130
131/* Same problem with getpagesize. */
132static inline int my_getpagesize ( void )
133{
134#  if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
135      || defined(VGPV_mips32_linux_android)
136   return 4096; /* kludge - link failure on Android, for some reason */
137#  else
138   extern int getpagesize (void);
139   return getpagesize();
140#  endif
141}
142
143
144/* Compute the high word of the double-length unsigned product of U
145   and V.  This is for calloc argument overflow checking; see comments
146   below.  Algorithm as described in Hacker's Delight, chapter 8. */
147static UWord umulHW ( UWord u, UWord v )
148{
149   UWord u0, v0, w0, rHi;
150   UWord u1, v1, w1,w2,t;
151   UWord halfMask  = sizeof(UWord)==4 ? (UWord)0xFFFF
152                                      : (UWord)0xFFFFFFFFULL;
153   UWord halfShift = sizeof(UWord)==4 ? 16 : 32;
154   u0  = u & halfMask;
155   u1  = u >> halfShift;
156   v0  = v & halfMask;
157   v1  = v >> halfShift;
158   w0  = u0 * v0;
159   t   = u1 * v0 + (w0 >> halfShift);
160   w1  = t & halfMask;
161   w2  = t >> halfShift;
162   w1  = u0 * v1 + w1;
163   rHi = u1 * v1 + w2 + (w1 >> halfShift);
164   return rHi;
165}
166
167
168/*------------------------------------------------------------*/
169/*--- Replacing malloc() et al                             ---*/
170/*------------------------------------------------------------*/
171
172/* This struct is initially empty.  Before the first use of any of
173   these functions, we make a client request which fills in the
174   fields.
175*/
176static struct vg_mallocfunc_info info;
177static int init_done;
178#define DO_INIT if (UNLIKELY(!init_done)) init()
179
180/* Startup hook - called as init section */
181__attribute__((constructor))
182static void init(void);
183
184#define MALLOC_TRACE(format, args...)  \
185   if (info.clo_trace_malloc) {        \
186      VALGRIND_INTERNAL_PRINTF(format, ## args ); }
187
188/* Below are new versions of malloc, __builtin_new, free,
189   __builtin_delete, calloc, realloc, memalign, and friends.
190
191   None of these functions are called directly - they are not meant to
192   be found by the dynamic linker.  But ALL client calls to malloc()
193   and friends wind up here eventually.  They get called because
194   vg_replace_malloc installs a bunch of code redirects which causes
195   Valgrind to use these functions rather than the ones they're
196   replacing.
197*/
198
199/* The replacement functions are running on the simulated CPU.
200   The code on the simulated CPU does not necessarily use
201   all arguments. E.g. args can be ignored and/or only given
202   to a NON SIMD call.
203   The definedness of such 'unused' arguments will not be verified
204   by memcheck.
205   A call to 'trigger_memcheck_error_if_undefined' allows
206   memcheck to detect such errors for the otherwise unused args.
207   Apart of allowing memcheck to detect an error, the function
208   trigger_memcheck_error_if_undefined has no effect and
209   has a minimal cost for other tools replacing malloc functions.
210*/
211static inline void trigger_memcheck_error_if_undefined ( ULong x )
212{
213   if (x == 0) __asm__ __volatile__( "" ::: "memory" );
214}
215
216/*---------------------- malloc ----------------------*/
217
218/* Generate a replacement for 'fnname' in object 'soname', which calls
219   'vg_replacement' to allocate memory.  If that fails, return NULL.
220*/
221#define ALLOC_or_NULL(soname, fnname, vg_replacement) \
222   \
223   void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n); \
224   void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n)  \
225   { \
226      void* v; \
227      \
228      DO_INIT; \
229      trigger_memcheck_error_if_undefined((ULong)n ); \
230      MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
231      \
232      v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
233      MALLOC_TRACE(" = %p\n", v ); \
234      return v; \
235   }
236
237#define ZONEALLOC_or_NULL(soname, fnname, vg_replacement) \
238   \
239   void* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n); \
240   void* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n)  \
241   { \
242      void* v; \
243      \
244      DO_INIT; \
245      trigger_memcheck_error_if_undefined((ULong)(UWord) zone);	\
246      trigger_memcheck_error_if_undefined((ULong) n); \
247      MALLOC_TRACE(#fnname "(%p, %llu)", zone, (ULong)n ); \
248      \
249      v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
250      MALLOC_TRACE(" = %p\n", v ); \
251      return v; \
252   }
253
254
255/* Generate a replacement for 'fnname' in object 'soname', which calls
256   'vg_replacement' to allocate memory.  If that fails, it bombs the
257   system.
258*/
259#define ALLOC_or_BOMB(soname, fnname, vg_replacement)  \
260   \
261   void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n); \
262   void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n)  \
263   { \
264      void* v; \
265      \
266      DO_INIT; \
267      trigger_memcheck_error_if_undefined((ULong) n); \
268      MALLOC_TRACE(#fnname "(%llu)", (ULong)n );        \
269      \
270      v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
271      MALLOC_TRACE(" = %p\n", v ); \
272      if (NULL == v) { \
273         VALGRIND_PRINTF( \
274            "new/new[] failed and should throw an exception, but Valgrind\n"); \
275         VALGRIND_PRINTF_BACKTRACE( \
276            "   cannot throw exceptions and so is aborting instead.  Sorry.\n"); \
277            my_exit(1); \
278      } \
279      return v; \
280   }
281
282// Each of these lines generates a replacement function:
283//     (from_so, from_fn,  v's replacement)
284// For some lines, we will also define a replacement function
285// whose only purpose is to be a soname synonym place holder
286// that can be replaced using --soname-synonyms.
287#define SO_SYN_MALLOC VG_SO_SYN(somalloc)
288
289// malloc
290#if defined(VGO_linux)
291 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, malloc,      malloc);
292 ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
293 ALLOC_or_NULL(SO_SYN_MALLOC,         malloc,      malloc);
294
295#elif defined(VGO_darwin)
296 ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
297 ALLOC_or_NULL(SO_SYN_MALLOC,         malloc,      malloc);
298 ZONEALLOC_or_NULL(VG_Z_LIBC_SONAME,  malloc_zone_malloc, malloc);
299 ZONEALLOC_or_NULL(SO_SYN_MALLOC,     malloc_zone_malloc, malloc);
300
301#endif
302
303
304/*---------------------- new ----------------------*/
305
306#if defined(VGO_linux)
307 // operator new(unsigned int), not mangled (for gcc 2.96)
308 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  builtin_new,    __builtin_new);
309 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       builtin_new,    __builtin_new);
310 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  __builtin_new,  __builtin_new);
311 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       __builtin_new,  __builtin_new);
312 // operator new(unsigned int), GNU mangling
313 #if VG_WORDSIZE == 4
314  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj,          __builtin_new);
315  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwj,          __builtin_new);
316  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znwj,          __builtin_new);
317 #endif
318 // operator new(unsigned long), GNU mangling
319 #if VG_WORDSIZE == 8
320  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm,          __builtin_new);
321  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwm,          __builtin_new);
322  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znwm,          __builtin_new);
323 #endif
324
325#elif defined(VGO_darwin)
326 // operator new(unsigned int), GNU mangling
327 #if VG_WORDSIZE == 4
328  //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj,          __builtin_new);
329  //ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwj,          __builtin_new);
330 #endif
331 // operator new(unsigned long), GNU mangling
332 #if 1 // FIXME: is this right?
333  //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm,          __builtin_new);
334  //ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znwm,          __builtin_new);
335 #endif
336
337#endif
338
339
340/*---------------------- new nothrow ----------------------*/
341
342#if defined(VGO_linux)
343 // operator new(unsigned, std::nothrow_t const&), GNU mangling
344 #if VG_WORDSIZE == 4
345  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t,  __builtin_new);
346  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwjRKSt9nothrow_t,  __builtin_new);
347  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnwjRKSt9nothrow_t,  __builtin_new);
348 #endif
349 // operator new(unsigned long, std::nothrow_t const&), GNU mangling
350 #if VG_WORDSIZE == 8
351  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t,  __builtin_new);
352  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwmRKSt9nothrow_t,  __builtin_new);
353  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnwmRKSt9nothrow_t,  __builtin_new);
354 #endif
355
356#elif defined(VGO_darwin)
357 // operator new(unsigned, std::nothrow_t const&), GNU mangling
358 #if VG_WORDSIZE == 4
359  //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t,  __builtin_new);
360  //ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwjRKSt9nothrow_t,  __builtin_new);
361 #endif
362 // operator new(unsigned long, std::nothrow_t const&), GNU mangling
363 #if 1 // FIXME: is this right?
364  //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t,  __builtin_new);
365  //ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnwmRKSt9nothrow_t,  __builtin_new);
366 #endif
367
368#endif
369
370
371/*---------------------- new [] ----------------------*/
372
373#if defined(VGO_linux)
374 // operator new[](unsigned int), not mangled (for gcc 2.96)
375 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME,  __builtin_vec_new, __builtin_vec_new );
376 ALLOC_or_BOMB(VG_Z_LIBC_SONAME,       __builtin_vec_new, __builtin_vec_new );
377 // operator new[](unsigned int), GNU mangling
378 #if VG_WORDSIZE == 4
379  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj,             __builtin_vec_new );
380  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znaj,             __builtin_vec_new );
381  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znaj,             __builtin_vec_new );
382 #endif
383 // operator new[](unsigned long), GNU mangling
384 #if VG_WORDSIZE == 8
385  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam,             __builtin_vec_new );
386  ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znam,             __builtin_vec_new );
387  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znam,             __builtin_vec_new );
388 #endif
389
390#elif defined(VGO_darwin)
391 // operator new[](unsigned int), GNU mangling
392 #if VG_WORDSIZE == 4
393  //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj,             __builtin_vec_new );
394  //ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znaj,             __builtin_vec_new );
395 #endif
396 // operator new[](unsigned long), GNU mangling
397 #if 1 // FIXME: is this right?
398  //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam,             __builtin_vec_new );
399  //ALLOC_or_BOMB(VG_Z_LIBC_SONAME,      _Znam,             __builtin_vec_new );
400 #endif
401
402#endif
403
404
405/*---------------------- new [] nothrow ----------------------*/
406
407#if defined(VGO_linux)
408 // operator new[](unsigned, std::nothrow_t const&), GNU mangling
409 #if VG_WORDSIZE == 4
410  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
411  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnajRKSt9nothrow_t, __builtin_vec_new );
412  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnajRKSt9nothrow_t, __builtin_vec_new );
413 #endif
414 // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
415 #if VG_WORDSIZE == 8
416  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
417  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnamRKSt9nothrow_t, __builtin_vec_new );
418  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnamRKSt9nothrow_t, __builtin_vec_new );
419 #endif
420
421#elif defined(VGO_darwin)
422 // operator new[](unsigned, std::nothrow_t const&), GNU mangling
423 #if VG_WORDSIZE == 4
424  //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
425  //ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnajRKSt9nothrow_t, __builtin_vec_new );
426 #endif
427 // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
428 #if 1 // FIXME: is this right?
429  //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
430  //ALLOC_or_NULL(VG_Z_LIBC_SONAME,      _ZnamRKSt9nothrow_t, __builtin_vec_new );
431 #endif
432
433#endif
434
435
436/*---------------------- free ----------------------*/
437
438/* Generate a replacement for 'fnname' in object 'soname', which calls
439   'vg_replacement' to free previously allocated memory.
440*/
441#define ZONEFREE(soname, fnname, vg_replacement) \
442   \
443   void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p); \
444   void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p)  \
445   { \
446      DO_INIT; \
447      trigger_memcheck_error_if_undefined((ULong)(UWord) zone);	\
448      MALLOC_TRACE(#fnname "(%p, %p)\n", zone, p ); \
449      if (p == NULL)  \
450         return; \
451      (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
452   }
453
454#define FREE(soname, fnname, vg_replacement) \
455   \
456   void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p); \
457   void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p)  \
458   { \
459      DO_INIT; \
460      MALLOC_TRACE(#fnname "(%p)\n", p ); \
461      if (p == NULL)  \
462         return; \
463      (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
464   }
465
466
467#if defined(VGO_linux)
468 FREE(VG_Z_LIBSTDCXX_SONAME,  free,                 free );
469 FREE(VG_Z_LIBC_SONAME,       free,                 free );
470 FREE(SO_SYN_MALLOC,          free,                 free );
471
472#elif defined(VGO_darwin)
473 FREE(VG_Z_LIBC_SONAME,       free,                 free );
474 FREE(SO_SYN_MALLOC,          free,                 free );
475 ZONEFREE(VG_Z_LIBC_SONAME,   malloc_zone_free,     free );
476 ZONEFREE(SO_SYN_MALLOC,      malloc_zone_free,     free );
477
478#endif
479
480
481/*---------------------- cfree ----------------------*/
482
483// cfree
484#if defined(VGO_linux)
485 FREE(VG_Z_LIBSTDCXX_SONAME,  cfree,                free );
486 FREE(VG_Z_LIBC_SONAME,       cfree,                free );
487 FREE(SO_SYN_MALLOC,          cfree,                free );
488
489#elif defined(VGO_darwin)
490 //FREE(VG_Z_LIBSTDCXX_SONAME,  cfree,                free );
491 //FREE(VG_Z_LIBC_SONAME,       cfree,                free );
492
493#endif
494
495
496/*---------------------- delete ----------------------*/
497
498#if defined(VGO_linux)
499 // operator delete(void*), not mangled (for gcc 2.96)
500 FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_delete,     __builtin_delete );
501 FREE(VG_Z_LIBC_SONAME,        __builtin_delete,     __builtin_delete );
502 // operator delete(void*), GNU mangling
503 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPv,               __builtin_delete );
504 FREE(VG_Z_LIBC_SONAME,       _ZdlPv,               __builtin_delete );
505 FREE(SO_SYN_MALLOC,          _ZdlPv,               __builtin_delete );
506
507#elif defined(VGO_darwin)
508 // operator delete(void*), GNU mangling
509 //FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPv,               __builtin_delete );
510 //FREE(VG_Z_LIBC_SONAME,       _ZdlPv,               __builtin_delete );
511
512#endif
513
514
515/*---------------------- delete nothrow ----------------------*/
516
517#if defined(VGO_linux)
518 // operator delete(void*, std::nothrow_t const&), GNU mangling
519 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
520 FREE(VG_Z_LIBC_SONAME,      _ZdlPvRKSt9nothrow_t,  __builtin_delete );
521 FREE(SO_SYN_MALLOC,         _ZdlPvRKSt9nothrow_t,  __builtin_delete );
522
523#elif defined(VGO_darwin)
524 // operator delete(void*, std::nothrow_t const&), GNU mangling
525 //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
526 //FREE(VG_Z_LIBC_SONAME,      _ZdlPvRKSt9nothrow_t,  __builtin_delete );
527
528#endif
529
530
531/*---------------------- delete [] ----------------------*/
532
533#if defined(VGO_linux)
534 // operator delete[](void*), not mangled (for gcc 2.96)
535 FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_vec_delete, __builtin_vec_delete );
536 FREE(VG_Z_LIBC_SONAME,        __builtin_vec_delete, __builtin_vec_delete );
537 // operator delete[](void*), GNU mangling
538 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPv,               __builtin_vec_delete );
539 FREE(VG_Z_LIBC_SONAME,       _ZdaPv,               __builtin_vec_delete );
540 FREE(SO_SYN_MALLOC,          _ZdaPv,               __builtin_vec_delete );
541
542#elif defined(VGO_darwin)
543 // operator delete[](void*), not mangled (for gcc 2.96)
544 //FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_vec_delete, __builtin_vec_delete );
545 //FREE(VG_Z_LIBC_SONAME,        __builtin_vec_delete, __builtin_vec_delete );
546 // operator delete[](void*), GNU mangling
547 //FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPv,               __builtin_vec_delete );
548 //FREE(VG_Z_LIBC_SONAME,       _ZdaPv,               __builtin_vec_delete );
549
550#endif
551
552
553/*---------------------- delete [] nothrow ----------------------*/
554
555#if defined(VGO_linux)
556 // operator delete[](void*, std::nothrow_t const&), GNU mangling
557 FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
558 FREE(VG_Z_LIBC_SONAME,       _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
559 FREE(SO_SYN_MALLOC,          _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
560
561#elif defined(VGO_darwin)
562 // operator delete[](void*, std::nothrow_t const&), GNU mangling
563 //FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
564 //FREE(VG_Z_LIBC_SONAME,       _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
565
566#endif
567
568
569/*---------------------- calloc ----------------------*/
570
571#define ZONECALLOC(soname, fnname) \
572   \
573   void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
574            ( void *zone, SizeT nmemb, SizeT size ); \
575   void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
576            ( void *zone, SizeT nmemb, SizeT size )  \
577   { \
578      void* v; \
579      \
580      DO_INIT; \
581      trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
582      trigger_memcheck_error_if_undefined((ULong) nmemb); \
583      trigger_memcheck_error_if_undefined((ULong) size); \
584      MALLOC_TRACE("zone_calloc(%p, %llu,%llu)", zone, (ULong)nmemb, (ULong)size ); \
585      \
586      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
587      MALLOC_TRACE(" = %p\n", v ); \
588      return v; \
589   }
590
591#define CALLOC(soname, fnname) \
592   \
593   void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
594            ( SizeT nmemb, SizeT size ); \
595   void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
596            ( SizeT nmemb, SizeT size )  \
597   { \
598      void* v; \
599      \
600      DO_INIT; \
601      MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \
602      \
603      /* Protect against overflow.  See bug 24078. (that bug number is
604         invalid.  Which one really?) */ \
605      /* But don't use division, since that produces an external symbol
606         reference on ARM, in the form of a call to __aeabi_uidiv.  It's
607         normally OK, because ld.so manages to resolve it to something in the
608         executable, or one of its shared objects.  But that isn't guaranteed
609         to be the case, and it has been observed to fail in rare cases, eg:
610            echo x | valgrind /bin/sed -n "s/.*-\>\ //p"
611         So instead compute the high word of the product and check it is zero. */ \
612      if (umulHW(size, nmemb) != 0) return NULL; \
613      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
614      MALLOC_TRACE(" = %p\n", v ); \
615      return v; \
616   }
617
618#if defined(VGO_linux)
619 CALLOC(VG_Z_LIBC_SONAME, calloc);
620 CALLOC(SO_SYN_MALLOC,    calloc);
621
622#elif defined(VGO_darwin)
623 CALLOC(VG_Z_LIBC_SONAME, calloc);
624 CALLOC(SO_SYN_MALLOC,    calloc);
625 ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
626 ZONECALLOC(SO_SYN_MALLOC,    malloc_zone_calloc);
627
628#endif
629
630
631/*---------------------- realloc ----------------------*/
632
633#define ZONEREALLOC(soname, fnname) \
634   \
635   void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
636            ( void *zone, void* ptrV, SizeT new_size ); \
637   void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
638            ( void *zone, void* ptrV, SizeT new_size ) \
639   { \
640      void* v; \
641      \
642      DO_INIT; \
643      MALLOC_TRACE("zone_realloc(%p,%p,%llu)", zone, ptrV, (ULong)new_size ); \
644      \
645      if (ptrV == NULL) \
646         /* We need to call a malloc-like function; so let's use \
647            one which we know exists. GrP fixme use zonemalloc instead? */ \
648         return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
649                   (new_size); \
650      if (new_size <= 0) { \
651         VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
652         MALLOC_TRACE(" = 0\n"); \
653         return NULL; \
654      } \
655      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
656      MALLOC_TRACE(" = %p\n", v ); \
657      return v; \
658   }
659
660#define REALLOC(soname, fnname) \
661   \
662   void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
663            ( void* ptrV, SizeT new_size );\
664   void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
665            ( void* ptrV, SizeT new_size ) \
666   { \
667      void* v; \
668      \
669      DO_INIT; \
670      MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \
671      \
672      if (ptrV == NULL) \
673         /* We need to call a malloc-like function; so let's use \
674            one which we know exists. */ \
675         return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
676                   (new_size); \
677      if (new_size <= 0) { \
678         VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
679         MALLOC_TRACE(" = 0\n"); \
680         return NULL; \
681      } \
682      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
683      MALLOC_TRACE(" = %p\n", v ); \
684      return v; \
685   }
686
687#if defined(VGO_linux)
688 REALLOC(VG_Z_LIBC_SONAME, realloc);
689 REALLOC(SO_SYN_MALLOC,    realloc);
690
691#elif defined(VGO_darwin)
692 REALLOC(VG_Z_LIBC_SONAME, realloc);
693 REALLOC(SO_SYN_MALLOC,    realloc);
694 ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
695 ZONEREALLOC(SO_SYN_MALLOC,    malloc_zone_realloc);
696
697#endif
698
699
700/*---------------------- memalign ----------------------*/
701
702#define ZONEMEMALIGN(soname, fnname) \
703   \
704   void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
705            ( void *zone, SizeT alignment, SizeT n ); \
706   void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
707            ( void *zone, SizeT alignment, SizeT n ) \
708   { \
709      void* v; \
710      \
711      DO_INIT; \
712      trigger_memcheck_error_if_undefined((ULong)(UWord) zone);	\
713      trigger_memcheck_error_if_undefined((ULong) n); \
714      MALLOC_TRACE("zone_memalign(%p, al %llu, size %llu)", \
715                   zone, (ULong)alignment, (ULong)n );  \
716      \
717      /* Round up to minimum alignment if necessary. */ \
718      if (alignment < VG_MIN_MALLOC_SZB) \
719         alignment = VG_MIN_MALLOC_SZB; \
720      \
721      /* Round up to nearest power-of-two if necessary (like glibc). */ \
722      while (0 != (alignment & (alignment - 1))) alignment++; \
723      \
724      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
725      MALLOC_TRACE(" = %p\n", v ); \
726      return v; \
727   }
728
729#define MEMALIGN(soname, fnname) \
730   \
731   void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
732            ( SizeT alignment, SizeT n ); \
733   void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
734            ( SizeT alignment, SizeT n )  \
735   { \
736      void* v; \
737      \
738      DO_INIT; \
739      trigger_memcheck_error_if_undefined((ULong) n); \
740      MALLOC_TRACE("memalign(al %llu, size %llu)", \
741                   (ULong)alignment, (ULong)n ); \
742      \
743      /* Round up to minimum alignment if necessary. */ \
744      if (alignment < VG_MIN_MALLOC_SZB) \
745         alignment = VG_MIN_MALLOC_SZB; \
746      \
747      /* Round up to nearest power-of-two if necessary (like glibc). */ \
748      while (0 != (alignment & (alignment - 1))) alignment++; \
749      \
750      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
751      MALLOC_TRACE(" = %p\n", v ); \
752      return v; \
753   }
754
755#if defined(VGO_linux)
756 MEMALIGN(VG_Z_LIBC_SONAME, memalign);
757 MEMALIGN(SO_SYN_MALLOC,    memalign);
758
759#elif defined(VGO_darwin)
760 MEMALIGN(VG_Z_LIBC_SONAME, memalign);
761 MEMALIGN(SO_SYN_MALLOC,    memalign);
762 ZONEMEMALIGN(VG_Z_LIBC_SONAME, malloc_zone_memalign);
763 ZONEMEMALIGN(SO_SYN_MALLOC,    malloc_zone_memalign);
764
765#endif
766
767
768/*---------------------- valloc ----------------------*/
769
770#define VALLOC(soname, fnname) \
771   \
772   void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ); \
773   void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ) \
774   { \
775      static int pszB = 0; \
776      if (pszB == 0) \
777         pszB = my_getpagesize(); \
778      return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
779                ((SizeT)pszB, size); \
780   }
781
782#define ZONEVALLOC(soname, fnname) \
783   \
784   void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
785            ( void *zone, SizeT size ); \
786   void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
787            ( void *zone, SizeT size )  \
788   { \
789      static int pszB = 0; \
790      if (pszB == 0) \
791         pszB = my_getpagesize(); \
792      trigger_memcheck_error_if_undefined((ULong)(UWord) zone);	      \
793      return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
794                ((SizeT)pszB, size); \
795   }
796
797#if defined(VGO_linux)
798 VALLOC(VG_Z_LIBC_SONAME, valloc);
799 VALLOC(SO_SYN_MALLOC, valloc);
800
801#elif defined(VGO_darwin)
802 VALLOC(VG_Z_LIBC_SONAME, valloc);
803 VALLOC(SO_SYN_MALLOC, valloc);
804 ZONEVALLOC(VG_Z_LIBC_SONAME, malloc_zone_valloc);
805 ZONEVALLOC(SO_SYN_MALLOC,    malloc_zone_valloc);
806
807#endif
808
809
810/*---------------------- mallopt ----------------------*/
811
812/* Various compatibility wrapper functions, for glibc and libstdc++. */
813
814#define MALLOPT(soname, fnname) \
815   \
816   int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ); \
817   int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ) \
818   { \
819      /* In glibc-2.2.4, 1 denotes a successful return value for \
820         mallopt */ \
821      trigger_memcheck_error_if_undefined((ULong) cmd); \
822      trigger_memcheck_error_if_undefined((ULong) value); \
823      return 1; \
824   }
825
826#if defined(VGO_linux)
827 MALLOPT(VG_Z_LIBC_SONAME, mallopt);
828 MALLOPT(SO_SYN_MALLOC,    mallopt);
829
830#elif defined(VGO_darwin)
831 //MALLOPT(VG_Z_LIBC_SONAME, mallopt);
832
833#endif
834
835
836/*---------------------- malloc_trim ----------------------*/
837// Documentation says:
838//   malloc_trim(size_t pad);
839//
840//   If possible, gives memory back to the system (via negative arguments to
841//   sbrk) if there is unused memory at the `high' end of the malloc pool.
842//   You can call this after freeing large blocks of memory to potentially
843//   reduce the system-level memory requirements of a program. However, it
844//   cannot guarantee to reduce memory.  Under some allocation patterns,
845//   some large free blocks of memory will be locked between two used
846//   chunks, so they cannot be given back to the system.
847//
848//   The `pad' argument to malloc_trim represents the amount of free
849//   trailing space to leave untrimmed. If this argument is zero, only the
850//   minimum amount of memory to maintain internal data structures will be
851//   left (one page or less). Non-zero arguments can be supplied to maintain
852//   enough trailing space to service future expected allocations without
853//   having to re-obtain memory from the system.
854//
855//   Malloc_trim returns 1 if it actually released any memory, else 0. On
856//   systems that do not support "negative sbrks", it will always return 0.
857//
858// For simplicity, we always return 0.
859#define MALLOC_TRIM(soname, fnname) \
860   \
861   int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ); \
862   int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ) \
863   { \
864      /* 0 denotes that malloc_trim() either wasn't able \
865         to do anything, or was not implemented */ \
866      trigger_memcheck_error_if_undefined((ULong) pad); \
867      return 0; \
868   }
869
870#if defined(VGO_linux)
871 MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
872 MALLOC_TRIM(SO_SYN_MALLOC,    malloc_trim);
873
874#elif defined(VGO_darwin)
875 //MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
876
877#endif
878
879
880/*---------------------- posix_memalign ----------------------*/
881
882#define POSIX_MEMALIGN(soname, fnname) \
883   \
884   int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
885          ( void **memptr, SizeT alignment, SizeT size ); \
886   int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
887          ( void **memptr, SizeT alignment, SizeT size ) \
888   { \
889      void *mem; \
890      \
891      /* Test whether the alignment argument is valid.  It must be \
892         a power of two multiple of sizeof (void *).  */ \
893      if (alignment % sizeof (void *) != 0 \
894          || (alignment & (alignment - 1)) != 0) \
895         return VKI_EINVAL; \
896      \
897      mem = VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
898               (alignment, size); \
899      \
900      if (mem != NULL) { \
901        *memptr = mem; \
902        return 0; \
903      } \
904      \
905      return VKI_ENOMEM; \
906   }
907
908#if defined(VGO_linux)
909 POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
910 POSIX_MEMALIGN(SO_SYN_MALLOC,    posix_memalign);
911
912#elif defined(VGO_darwin)
913 //POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
914
915#endif
916
917
918/*---------------------- malloc_usable_size ----------------------*/
919
920#define MALLOC_USABLE_SIZE(soname, fnname) \
921   \
922   SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ); \
923   SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ) \
924   {  \
925      SizeT pszB; \
926      \
927      DO_INIT; \
928      MALLOC_TRACE("malloc_usable_size(%p)", p ); \
929      if (NULL == p) \
930         return 0; \
931      \
932      pszB = (SizeT)VALGRIND_NON_SIMD_CALL1( info.tl_malloc_usable_size, p ); \
933      MALLOC_TRACE(" = %llu\n", (ULong)pszB ); \
934      \
935      return pszB; \
936   }
937
938#if defined(VGO_linux)
939 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
940 MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    malloc_usable_size);
941 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
942 MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    malloc_size);
943# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
944     || defined(VGPV_mips32_linux_android)
945  MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, dlmalloc_usable_size);
946  MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    dlmalloc_usable_size);
947# endif
948
949#elif defined(VGO_darwin)
950 //MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
951 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
952 MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    malloc_size);
953
954#endif
955
956
957/*---------------------- (unimplemented) ----------------------*/
958
959/* Bomb out if we get any of these. */
960
961static void panic(const char *str)
962{
963   VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s\n", str);
964   my_exit(99);
965   *(volatile int *)0 = 'x';
966}
967
968#define PANIC(soname, fnname) \
969   \
970   void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ); \
971   void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void )  \
972   { \
973      panic(#fnname); \
974   }
975
976#if defined(VGO_linux)
977 PANIC(VG_Z_LIBC_SONAME, pvalloc);
978 PANIC(VG_Z_LIBC_SONAME, malloc_get_state);
979 PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
980
981#elif defined(VGO_darwin)
982 PANIC(VG_Z_LIBC_SONAME, pvalloc);
983 PANIC(VG_Z_LIBC_SONAME, malloc_get_state);
984 PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
985
986#endif
987
988
989#define MALLOC_STATS(soname, fnname) \
990   \
991   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ); \
992   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void )  \
993   { \
994      /* Valgrind's malloc_stats implementation does nothing. */ \
995   }
996
997#if defined(VGO_linux)
998 MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats);
999 MALLOC_STATS(SO_SYN_MALLOC,    malloc_stats);
1000
1001#elif defined(VGO_darwin)
1002 //MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats);
1003
1004#endif
1005
1006
1007/*---------------------- mallinfo ----------------------*/
1008
1009// mi must be static;  if it is auto then Memcheck thinks it is
1010// uninitialised when used by the caller of this function, because Memcheck
1011// doesn't know that the call to mallinfo fills in mi.
1012#define MALLINFO(soname, fnname) \
1013   \
1014   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ); \
1015   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ) \
1016   { \
1017      static struct vg_mallinfo mi; \
1018      DO_INIT; \
1019      MALLOC_TRACE("mallinfo()\n"); \
1020      (void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \
1021      return mi; \
1022   }
1023
1024#if defined(VGO_linux)
1025 MALLINFO(VG_Z_LIBC_SONAME, mallinfo);
1026 MALLINFO(SO_SYN_MALLOC,    mallinfo);
1027
1028#elif defined(VGO_darwin)
1029 //MALLINFO(VG_Z_LIBC_SONAME, mallinfo);
1030
1031#endif
1032
1033
1034/*------------------ Darwin zone stuff ------------------*/
1035
1036#if defined(VGO_darwin)
1037
1038static size_t my_malloc_size ( void* zone, void* ptr )
1039{
1040   /* Implement "malloc_size" by handing the request through to the
1041      tool's .tl_usable_size method. */
1042   DO_INIT;
1043   trigger_memcheck_error_if_undefined((ULong)(UWord) zone);
1044   trigger_memcheck_error_if_undefined((ULong)(UWord) ptr);
1045   size_t res = (size_t)VALGRIND_NON_SIMD_CALL1(
1046                           info.tl_malloc_usable_size, ptr);
1047   return res;
1048}
1049
1050/* Note that the (void*) casts below are a kludge which stops
1051   compilers complaining about the fact that the the replacement
1052   functions aren't really of the right type. */
1053static vki_malloc_zone_t vg_default_zone = {
1054    NULL, // reserved1
1055    NULL, // reserved2
1056    (void*)my_malloc_size, // JRS fixme: is this right?
1057    (void*)VG_REPLACE_FUNCTION_EZU(10020,VG_Z_LIBC_SONAME,malloc_zone_malloc),
1058    (void*)VG_REPLACE_FUNCTION_EZU(10060,VG_Z_LIBC_SONAME,malloc_zone_calloc),
1059    (void*)VG_REPLACE_FUNCTION_EZU(10130,VG_Z_LIBC_SONAME,malloc_zone_valloc),
1060    (void*)VG_REPLACE_FUNCTION_EZU(10040,VG_Z_LIBC_SONAME,malloc_zone_free),
1061    (void*)VG_REPLACE_FUNCTION_EZU(10080,VG_Z_LIBC_SONAME,malloc_zone_realloc),
1062    NULL, // GrP fixme: destroy
1063    "ValgrindMallocZone",
1064    NULL, // batch_malloc
1065    NULL, // batch_free
1066    NULL, // GrP fixme: introspect
1067    2,  // version (GrP fixme 3?)
1068    NULL, /* memalign */   // DDD: this field exists in Mac OS 10.6, but not 10.5.
1069    NULL, /* free_definite_size */
1070    NULL, /* pressure_relief */
1071};
1072
1073
1074#define DEFAULT_ZONE(soname, fnname) \
1075   \
1076   void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ); \
1077   void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void )  \
1078   { \
1079      return &vg_default_zone; \
1080   }
1081
1082DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone);
1083DEFAULT_ZONE(SO_SYN_MALLOC,    malloc_default_zone);
1084
1085
1086#define ZONE_FROM_PTR(soname, fnname) \
1087   \
1088   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void* ptr ); \
1089   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void* ptr )  \
1090   { \
1091      return &vg_default_zone; \
1092   }
1093
1094ZONE_FROM_PTR(VG_Z_LIBC_SONAME, malloc_zone_from_ptr);
1095ZONE_FROM_PTR(SO_SYN_MALLOC,    malloc_zone_from_ptr);
1096
1097
1098// GrP fixme bypass libc's use of zone->introspect->check
1099#define ZONE_CHECK(soname, fnname) \
1100   \
1101   int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone); \
1102   int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone)  \
1103   { \
1104      trigger_memcheck_error_if_undefined((ULong) zone); \
1105      return 1; \
1106   }
1107
1108//ZONE_CHECK(VG_Z_LIBC_SONAME, malloc_zone_check);
1109
1110#endif /* defined(VGO_darwin) */
1111
1112
1113/*------------------ (startup related) ------------------*/
1114
1115/* All the code in here is unused until this function is called */
1116
1117__attribute__((constructor))
1118static void init(void)
1119{
1120   // This doesn't look thread-safe, but it should be ok... Bart says:
1121   //
1122   //   Every program I know of calls malloc() at least once before calling
1123   //   pthread_create().  So init_done gets initialized before any thread is
1124   //   created, and is only read when multiple threads are active
1125   //   simultaneously.  Such an access pattern is safe.
1126   //
1127   //   If the assignment to the variable init_done would be triggering a race
1128   //   condition, both DRD and Helgrind would report this race.
1129   //
1130   //   By the way, although the init() function in
1131   //   coregrind/m_replacemalloc/vg_replace_malloc.c has been declared
1132   //   __attribute__((constructor)), it is not safe to remove the variable
1133   //   init_done. This is because it is possible that malloc() and hence
1134   //   init() gets called before shared library initialization finished.
1135   //
1136   if (init_done)
1137      return;
1138
1139   init_done = 1;
1140
1141   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__GET_MALLOCFUNCS, &info,
1142                                   0, 0, 0, 0);
1143}
1144
1145/*--------------------------------------------------------------------*/
1146/*--- end                                                          ---*/
1147/*--------------------------------------------------------------------*/
1148