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