about summary refs log tree commit diff
path: root/malloc/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r--malloc/malloc.c266
1 files changed, 175 insertions, 91 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 840655f4db..7e71e9777a 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -179,7 +179,7 @@
      Define to enable debugging. Adds fairly extensive assertion-based
      checking to help track down memory errors, but noticeably slows down
      execution.
-  MALLOC_HOOKS              (default: NOT defined)
+  MALLOC_HOOKS             (default: NOT defined)
      Define to enable support run-time replacement of the allocation
      functions through user-defined `hooks'.
   REALLOC_ZERO_BYTES_FREES (default: NOT defined)
@@ -298,7 +298,7 @@
 #if __STD_C
 # include <stddef.h>   /* for size_t */
 # if defined(_LIBC) || defined(MALLOC_HOOKS)
-#  include <stdlib.h>  /* for getenv() */
+#  include <stdlib.h>  /* for getenv(), abort() */
 # endif
 #else
 # include <sys/types.h>
@@ -315,13 +315,6 @@ extern "C" {
 
 #include <stdio.h>    /* needed for malloc_stats */
 
-/* We must not pollute the name space in the GNU libc.  */
-#ifdef _LIBC
-#define malloc_stats __malloc_stats
-#define malloc_usable_size __malloc_usable_size
-#define malloc_trim __malloc_trim
-#endif
-
 
 /*
   Compile-time options
@@ -878,6 +871,9 @@ extern Void_t*     sbrk();
 #define pvALLOc         __libc_pvalloc
 #define mALLINFo        __libc_mallinfo
 #define mALLOPt         __libc_mallopt
+#define mALLOC_STATs    __malloc_stats
+#define mALLOC_USABLE_SIZe __malloc_usable_size
+#define mALLOC_TRIm     __malloc_trim
 
 #else
 
@@ -890,6 +886,9 @@ extern Void_t*     sbrk();
 #define pvALLOc         pvalloc
 #define mALLINFo        mallinfo
 #define mALLOPt         mallopt
+#define mALLOC_STATs    malloc_stats
+#define mALLOC_USABLE_SIZe malloc_usable_size
+#define mALLOC_TRIm     malloc_trim
 
 #endif
 
@@ -908,12 +907,9 @@ Void_t* vALLOc(size_t);
 Void_t* pvALLOc(size_t);
 Void_t* cALLOc(size_t, size_t);
 void    cfree(Void_t*);
-int     __malloc_trim(size_t);
-int     malloc_trim(size_t);
-size_t  __malloc_usable_size(Void_t*);
-size_t  malloc_usable_size(Void_t*);
-void    __malloc_stats(void);
-void    malloc_stats(void);
+int     mALLOC_TRIm(size_t);
+size_t  mALLOC_USABLE_SIZe(Void_t*);
+void    mALLOC_STATs(void);
 int     mALLOPt(int, int);
 struct mallinfo mALLINFo(void);
 #else
@@ -928,12 +924,9 @@ Void_t* vALLOc();
 Void_t* pvALLOc();
 Void_t* cALLOc();
 void    cfree();
-int     __malloc_trim();
-int     malloc_trim();
-size_t  _malloc_usable_size();
-size_t  malloc_usable_size();
-void    __malloc_stats();
-void    malloc_stats();
+int     mALLOC_TRIm();
+size_t  mALLOC_USABLE_SIZe();
+void    mALLOC_STATs();
 int     mALLOPt();
 struct mallinfo mALLINFo();
 #endif
@@ -1166,9 +1159,9 @@ typedef struct _heap_info {
 static void      chunk_free(arena *ar_ptr, mchunkptr p);
 static mchunkptr chunk_alloc(arena *ar_ptr, INTERNAL_SIZE_T size);
 static mchunkptr chunk_realloc(arena *ar_ptr, mchunkptr oldp,
-			       INTERNAL_SIZE_T oldsize, INTERNAL_SIZE_T nb);
+                               INTERNAL_SIZE_T oldsize, INTERNAL_SIZE_T nb);
 static mchunkptr chunk_align(arena *ar_ptr, INTERNAL_SIZE_T nb,
-			     size_t alignment);
+                             size_t alignment);
 static int       main_trim(size_t pad);
 #ifndef NO_THREADS
 static int       heap_trim(heap_info *heap, size_t pad);
@@ -1178,6 +1171,8 @@ static Void_t*   malloc_check(size_t sz);
 static void      free_check(Void_t* mem);
 static Void_t*   realloc_check(Void_t* oldmem, size_t bytes);
 static Void_t*   memalign_check(size_t alignment, size_t bytes);
+static Void_t*   malloc_starter(size_t sz);
+static void      free_starter(Void_t* mem);
 #endif
 
 #else
@@ -1195,6 +1190,8 @@ static Void_t*   malloc_check();
 static void      free_check();
 static Void_t*   realloc_check();
 static Void_t*   memalign_check();
+static Void_t*   malloc_starter();
+static void      free_starter();
 #endif
 
 #endif
@@ -1434,7 +1431,7 @@ static arena main_arena = {
  IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
  IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
     },
-    NULL, /* next */
+    &main_arena, /* next */
     0, /* size */
 #if THREAD_STATS
     0, 0, 0, /* stat_lock_direct, stat_lock_loop, stat_lock_wait */
@@ -1489,8 +1486,9 @@ static unsigned long max_mmapped_mem = 0;
 
 
 
-/* Already initialized?  */
-int __malloc_initialized;
+
+/* Already initialized? */
+int __malloc_initialized = 0;
 
 
 /* Initialization routine. */
@@ -1507,11 +1505,22 @@ ptmalloc_init __MALLOC_P((void))
 #endif
 {
 #if defined(_LIBC) || defined(MALLOC_HOOKS)
+  __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size));
+  void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr));
   const char* s;
 #endif
 
   if(__malloc_initialized) return;
   __malloc_initialized = 1;
+#if defined(_LIBC) || defined(MALLOC_HOOKS)
+  /* With some threads implementations, creating thread-specific data
+     or initializing a mutex may call malloc() itself.  Provide a
+     simple starter version (realloc() won't work). */
+  save_malloc_hook = __malloc_hook;
+  save_free_hook = __free_hook;
+  __malloc_hook = malloc_starter;
+  __free_hook = free_starter;
+#endif
 #if defined(_LIBC)
   /* Initialize the pthreads interface. */
   if (__pthread_initialize != NULL)
@@ -1525,6 +1534,8 @@ ptmalloc_init __MALLOC_P((void))
 #endif
 #if defined(_LIBC) || defined(MALLOC_HOOKS)
   s = getenv("MALLOC_CHECK_");
+  __malloc_hook = save_malloc_hook;
+  __free_hook = save_free_hook;
   if(s) {
     if(s[0]) mallopt(M_CHECK_ACTION, (int)(s[0] - '0'));
     malloc_check_init();
@@ -1598,7 +1609,8 @@ malloc_check_init()
   __free_hook = free_check;
   __realloc_hook = realloc_check;
   __memalign_hook = memalign_check;
-  fprintf(stderr, "Using debugging hooks\n");
+  if(check_action == 1)
+    fprintf(stderr, "malloc: using debugging hooks\n");
 }
 
 #endif
@@ -1821,17 +1833,16 @@ grow_heap(h, diff) heap_info *h; long diff;
 /* arena_get() acquires an arena and locks the corresponding mutex.
    First, try the one last locked successfully by this thread.  (This
    is the common case and handled with a macro for speed.)  Then, loop
-   over the singly linked list of arenas.  If no arena is readily
-   available, create a new one.  */
+   once over the circularly linked list of arenas.  If no arena is
+   readily available, create a new one. */
 
 #define arena_get(ptr, size) do { \
   Void_t *vptr = NULL; \
   ptr = (arena *)tsd_getspecific(arena_key, vptr); \
   if(ptr && !mutex_trylock(&ptr->mutex)) { \
     THREAD_STAT(++(ptr->stat_lock_direct)); \
-  } else { \
+  } else \
     ptr = arena_get2(ptr, (size)); \
-  } \
 } while(0)
 
 static arena *
@@ -1847,17 +1858,27 @@ arena_get2(a_tsd, size) arena *a_tsd; size_t size;
   int i;
   unsigned long misalign;
 
-  /* Check the singly-linked list for unlocked arenas. */
-  if(a_tsd) {
-    for(a = a_tsd->next; a; a = a->next) {
-      if(!mutex_trylock(&a->mutex))
-        goto done;
+  if(!a_tsd)
+    a = a_tsd = &main_arena;
+  else {
+    a = a_tsd->next;
+    if(!a) {
+      /* This can only happen while initializing the new arena. */
+      (void)mutex_lock(&main_arena.mutex);
+      THREAD_STAT(++(main_arena.stat_lock_wait));
+      return &main_arena;
     }
   }
-  for(a = &main_arena; a != a_tsd; a = a->next) {
-    if(!mutex_trylock(&a->mutex))
-      goto done;
-  }
+
+  /* Check the global, circularly linked list for available arenas. */
+  do {
+    if(!mutex_trylock(&a->mutex)) {
+      THREAD_STAT(++(a->stat_lock_loop));
+      tsd_setspecific(arena_key, (Void_t *)a);
+      return a;
+    }
+    a = a->next;
+  } while(a != a_tsd);
 
   /* Nothing immediately available, so generate a new arena. */
   h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT));
@@ -1866,7 +1887,9 @@ arena_get2(a_tsd, size) arena *a_tsd; size_t size;
   a = h->ar_ptr = (arena *)(h+1);
   for(i=0; i<NAV; i++)
     init_bin(a, i);
+  a->next = NULL;
   a->size = h->size;
+  tsd_setspecific(arena_key, (Void_t *)a);
   mutex_init(&a->mutex);
   i = mutex_lock(&a->mutex); /* remember result */
 
@@ -1887,9 +1910,7 @@ arena_get2(a_tsd, size) arena *a_tsd; size_t size;
   if(i) /* locking failed; keep arena for further attempts later */
     return 0;
 
-done:
   THREAD_STAT(++(a->stat_lock_loop));
-  tsd_setspecific(arena_key, (Void_t *)a);
   return a;
 }
 
@@ -2890,7 +2911,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
 static mchunkptr
 #if __STD_C
 chunk_realloc(arena* ar_ptr, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
-             INTERNAL_SIZE_T nb)
+              INTERNAL_SIZE_T nb)
 #else
 chunk_realloc(ar_ptr, oldp, oldsize, nb)
 arena* ar_ptr; mchunkptr oldp; INTERNAL_SIZE_T oldsize, nb;
@@ -3339,9 +3360,9 @@ void cfree(mem) Void_t *mem;
 */
 
 #if __STD_C
-int malloc_trim(size_t pad)
+int mALLOC_TRIm(size_t pad)
 #else
-int malloc_trim(pad) size_t pad;
+int mALLOC_TRIm(pad) size_t pad;
 #endif
 {
   int res;
@@ -3475,9 +3496,9 @@ heap_trim(heap, pad) heap_info *heap; size_t pad;
 */
 
 #if __STD_C
-size_t malloc_usable_size(Void_t* mem)
+size_t mALLOC_USABLE_SIZe(Void_t* mem)
 #else
-size_t malloc_usable_size(mem) Void_t* mem;
+size_t mALLOC_USABLE_SIZe(mem) Void_t* mem;
 #endif
 {
   mchunkptr p;
@@ -3603,7 +3624,7 @@ dump_heap(heap) heap_info *heap;
 
 */
 
-void malloc_stats()
+void mALLOC_STATs()
 {
   int i;
   arena *ar_ptr;
@@ -3613,7 +3634,7 @@ void malloc_stats()
   long stat_lock_direct = 0, stat_lock_loop = 0, stat_lock_wait = 0;
 #endif
 
-  for(i=0, ar_ptr = &main_arena; ar_ptr; ar_ptr = ar_ptr->next, i++) {
+  for(i=0, ar_ptr = &main_arena;; i++) {
     malloc_update_mallinfo(ar_ptr, &mi);
     fprintf(stderr, "Arena %d:\n", i);
     fprintf(stderr, "system bytes     = %10u\n", (unsigned int)mi.arena);
@@ -3627,10 +3648,14 @@ void malloc_stats()
 #endif
 #if !defined(NO_THREADS) && MALLOC_DEBUG > 1
     if(ar_ptr != &main_arena) {
+      (void)mutex_lock(&ar_ptr->mutex);
       heap_info *heap = heap_for_ptr(top(ar_ptr));
       while(heap) { dump_heap(heap); heap = heap->prev; }
+      (void)mutex_unlock(&ar_ptr->mutex);
     }
 #endif
+    ar_ptr = ar_ptr->next;
+    if(ar_ptr == &main_arena) break;
   }
   fprintf(stderr, "Total (incl. mmap):\n");
   fprintf(stderr, "system bytes     = %10u\n", system_b);
@@ -3713,26 +3738,7 @@ int mALLOPt(param_number, value) int param_number; int value;
       return 0;
   }
 }
-
-#ifdef _LIBC
-weak_alias (__libc_calloc, __calloc) weak_alias (__libc_calloc, calloc)
-weak_alias (__libc_free, __cfree) weak_alias (__libc_free, cfree)
-weak_alias (__libc_free, __free) weak_alias (__libc_free, free)
-weak_alias (__libc_malloc, __malloc) weak_alias (__libc_malloc, malloc)
-weak_alias (__libc_memalign, __memalign) weak_alias (__libc_memalign, memalign)
-weak_alias (__libc_realloc, __realloc) weak_alias (__libc_realloc, realloc)
-weak_alias (__libc_valloc, __valloc) weak_alias (__libc_valloc, valloc)
-weak_alias (__libc_pvalloc, __pvalloc) weak_alias (__libc_pvalloc, pvalloc)
-weak_alias (__libc_mallinfo, __mallinfo) weak_alias (__libc_mallinfo, mallinfo)
-weak_alias (__libc_mallopt, __mallopt) weak_alias (__libc_mallopt, mallopt)
 
-#undef malloc_stats
-weak_alias (__malloc_stats, malloc_stats)
-#undef malloc_usable_size
-weak_alias (__malloc_usable_size, malloc_usable_size)
-#undef malloc_trim
-weak_alias (__malloc_trim, malloc_trim)
-#endif
 
 
 #if defined(_LIBC) || defined(MALLOC_HOOKS)
@@ -3741,7 +3747,7 @@ weak_alias (__malloc_trim, malloc_trim)
    byte per chunk; still this will catch most cases of double frees or
    overruns. */
 
-#define MAGICBYTE ((char)0xd7)
+#define MAGICBYTE(p) ( ( ((unsigned)p >> 3) ^ ((unsigned)p >> 11)) & 0xFF )
 
 /* Convert a pointer to be free()d or realloc()ed to a valid chunk
    pointer.  If the provided pointer is not valid, return NULL.  The
@@ -3760,29 +3766,35 @@ mem2chunk_check(mem) Void_t* mem;
   p = mem2chunk(mem);
   if(!aligned_OK(p)) return NULL;
   if( (char*)p>=sbrk_base && (char*)p<(sbrk_base+sbrked_mem) ) {
-    /* Must be a chunk in conventional memory. */
+    /* Must be a chunk in conventional heap memory. */
     if(chunk_is_mmapped(p) ||
        ( (sz = chunksize(p)), ((char*)p + sz)>=(sbrk_base+sbrked_mem) ) ||
-       sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) ) return NULL;
-    if(*((char*)p + sz + (SIZE_SZ-1)) != MAGICBYTE) return NULL;
-    *((char*)p + sz + (SIZE_SZ-1)) = 0;
+       sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) ||
+       ( !prev_inuse(p) && (p->prev_size&MALLOC_ALIGN_MASK ||
+                            (long)prev_chunk(p)<(long)sbrk_base ||
+                            next_chunk(prev_chunk(p))!=p) ))
+      return NULL;
+    if(*((unsigned char*)p + sz + (SIZE_SZ-1)) != MAGICBYTE(p))
+      return NULL;
+    *((unsigned char*)p + sz + (SIZE_SZ-1)) ^= 0xFF;
   } else {
     unsigned long offset, page_mask = malloc_getpagesize-1;
 
-    /* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of two
+    /* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two
        alignment relative to the beginning of a page.  Check this
        first. */
     offset = (unsigned long)mem & page_mask;
     if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 &&
-       offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 &&
-       offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 &&
-       offset<0x2000) ||
+        offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 &&
+        offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 &&
+        offset<0x2000) ||
        !chunk_is_mmapped(p) || (p->size & PREV_INUSE) ||
        ( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
        ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
       return NULL;
-    if(*((char*)p + sz - 1) != MAGICBYTE) return NULL;
-    *((char*)p + sz - 1) = 0;
+    if(*((unsigned char*)p + sz - 1) != MAGICBYTE(p))
+      return NULL;
+    *((unsigned char*)p + sz - 1) ^= 0xFF;
   }
   return p;
 }
@@ -3806,7 +3818,7 @@ malloc_check(sz) size_t sz;
     --nb;
   else
     nb += SIZE_SZ - 1;
-  *((char*)victim + nb) = MAGICBYTE;
+  *((unsigned char*)victim + nb) = MAGICBYTE(victim);
   return chunk2mem(victim);
 }
 
@@ -3820,8 +3832,10 @@ free_check(mem) Void_t* mem;
   mchunkptr p;
 
   if(!mem) return;
+  (void)mutex_lock(&main_arena.mutex);
   p = mem2chunk_check(mem);
   if(!p) {
+    (void)mutex_unlock(&main_arena.mutex);
     switch(check_action) {
     case 1:
       fprintf(stderr, "free(): invalid pointer %lx!\n", (long)(mem));
@@ -3833,11 +3847,14 @@ free_check(mem) Void_t* mem;
   }
 #if HAVE_MMAP
   if (chunk_is_mmapped(p)) {
+    (void)mutex_unlock(&main_arena.mutex);
     munmap_chunk(p);
     return;
   }
 #endif
-  (void)mutex_lock(&main_arena.mutex);
+#if 0 /* Erase freed memory. */
+  memset(mem, 0, chunksize(p) - (SIZE_SZ+1));
+#endif
   chunk_free(&main_arena, p);
   (void)mutex_unlock(&main_arena.mutex);
 }
@@ -3853,8 +3870,10 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes;
   INTERNAL_SIZE_T nb, oldsize;
 
   if (oldmem == 0) return malloc_check(bytes);
+  (void)mutex_lock(&main_arena.mutex);
   oldp = mem2chunk_check(oldmem);
   if(!oldp) {
+    (void)mutex_unlock(&main_arena.mutex);
     switch(check_action) {
     case 1:
       fprintf(stderr, "realloc(): invalid pointer %lx!\n", (long)(oldmem));
@@ -3868,7 +3887,6 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes;
 
   nb = request2size(bytes+1);
 
-  (void)mutex_lock(&main_arena.mutex);
 #if HAVE_MMAP
   if (chunk_is_mmapped(oldp)) {
 #if HAVE_MREMAP
@@ -3878,19 +3896,31 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes;
       /* Note the extra SIZE_SZ overhead. */
       if(oldsize - SIZE_SZ >= nb) newp = oldp; /* do nothing */
       else {
-       /* Must alloc, copy, free. */
-       newp = chunk_alloc(&main_arena, nb);
-       if (newp) {
-         MALLOC_COPY(chunk2mem(newp), oldmem, oldsize - 2*SIZE_SZ);
-         munmap_chunk(oldp);
-       }
+        /* Must alloc, copy, free. */
+        newp = chunk_alloc(&main_arena, nb);
+        if (newp) {
+          MALLOC_COPY(chunk2mem(newp), oldmem, oldsize - 2*SIZE_SZ);
+          munmap_chunk(oldp);
+        }
       }
 #if HAVE_MREMAP
     }
 #endif
-  } else
+  } else {
 #endif /* HAVE_MMAP */
     newp = chunk_realloc(&main_arena, oldp, oldsize, nb);
+#if 0 /* Erase freed memory. */
+    nb = chunksize(newp);
+    if(oldp<newp || oldp>=chunk_at_offset(newp, nb)) {
+      memset((char*)oldmem + 2*sizeof(mbinptr), 0,
+             oldsize - (2*sizeof(mbinptr)+2*SIZE_SZ+1));
+    } else if(nb > oldsize+SIZE_SZ) {
+      memset((char*)chunk2mem(newp) + oldsize, 0, nb - (oldsize+SIZE_SZ));
+    }
+#endif
+#if HAVE_MMAP
+  }
+#endif
   (void)mutex_unlock(&main_arena.mutex);
 
   if(!newp) return NULL;
@@ -3899,7 +3929,7 @@ realloc_check(oldmem, bytes) Void_t* oldmem; size_t bytes;
     --nb;
   else
     nb += SIZE_SZ - 1;
-  *((char*)newp + nb) = MAGICBYTE;
+  *((unsigned char*)newp + nb) = MAGICBYTE(newp);
   return chunk2mem(newp);
 }
 
@@ -3926,12 +3956,66 @@ memalign_check(alignment, bytes) size_t alignment; size_t bytes;
     --nb;
   else
     nb += SIZE_SZ - 1;
-  *((char*)p + nb) = MAGICBYTE;
+  *((unsigned char*)p + nb) = MAGICBYTE(p);
   return chunk2mem(p);
 }
 
+/* The following hooks are used when the global initialization in
+   ptmalloc_init() hasn't completed yet. */
+
+static Void_t*
+#if __STD_C
+malloc_starter(size_t sz)
+#else
+malloc_starter(sz) size_t sz;
+#endif
+{
+  mchunkptr victim = chunk_alloc(&main_arena, request2size(sz));
+
+  return victim ? chunk2mem(victim) : 0;
+}
+
+static void
+#if __STD_C
+free_starter(Void_t* mem)
+#else
+free_starter(mem) Void_t* mem;
+#endif
+{
+  mchunkptr p;
+
+  if(!mem) return;
+  p = mem2chunk(mem);
+#if HAVE_MMAP
+  if (chunk_is_mmapped(p)) {
+    munmap_chunk(p);
+    return;
+  }
+#endif
+  chunk_free(&main_arena, p);
+}
+
 #endif /* defined(_LIBC) || defined(MALLOC_HOOKS) */
 
+
+
+#ifdef _LIBC
+weak_alias (__libc_calloc, __calloc) weak_alias (__libc_calloc, calloc)
+weak_alias (__libc_free, __cfree) weak_alias (__libc_free, cfree)
+weak_alias (__libc_free, __free) weak_alias (__libc_free, free)
+weak_alias (__libc_malloc, __malloc) weak_alias (__libc_malloc, malloc)
+weak_alias (__libc_memalign, __memalign) weak_alias (__libc_memalign, memalign)
+weak_alias (__libc_realloc, __realloc) weak_alias (__libc_realloc, realloc)
+weak_alias (__libc_valloc, __valloc) weak_alias (__libc_valloc, valloc)
+weak_alias (__libc_pvalloc, __pvalloc) weak_alias (__libc_pvalloc, pvalloc)
+weak_alias (__libc_mallinfo, __mallinfo) weak_alias (__libc_mallinfo, mallinfo)
+weak_alias (__libc_mallopt, __mallopt) weak_alias (__libc_mallopt, mallopt)
+
+weak_alias (__malloc_stats, malloc_stats)
+weak_alias (__malloc_usable_size, malloc_usable_size)
+weak_alias (__malloc_trim, malloc_trim)
+#endif
+
 /*
 
 History: