Home | History | Annotate | Download | only in m_replacemalloc
      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 (at) 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__))
    117 static 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. */
    132 static 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. */
    146 static 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 */
    175 static struct vg_mallocfunc_info info;
    176 static int init_done;
    177 
    178 /* Startup hook - called as init section */
    179 __attribute__((constructor))
    180 static 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 
    927 static 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 
   1004 static 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. */
   1017 static 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 
   1046 DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone);
   1047 DEFAULT_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 
   1058 ZONE_FROM_PTR(VG_Z_LIBC_SONAME, malloc_zone_from_ptr);
   1059 ZONE_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))
   1081 static 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