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-2013 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) || 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. */
    132 static 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. */
    147 static 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 */
    176 static struct vg_mallocfunc_info info;
    177 static int init_done;
    178 #define DO_INIT if (UNLIKELY(!init_done)) init()
    179 
    180 /* Startup hook - called as init section */
    181 __attribute__((constructor))
    182 static 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 */
    211 static 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 
    961 static 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 
   1038 static 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. */
   1053 static 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 
   1082 DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone);
   1083 DEFAULT_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 
   1094 ZONE_FROM_PTR(VG_Z_LIBC_SONAME, malloc_zone_from_ptr);
   1095 ZONE_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))
   1118 static 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