OSDN Git Service

Improve malloc debugging support.
authorMiles Bader <miles@lsi.nec.co.jp>
Thu, 21 Nov 2002 06:06:22 +0000 (06:06 -0000)
committerMiles Bader <miles@lsi.nec.co.jp>
Thu, 21 Nov 2002 06:06:22 +0000 (06:06 -0000)
extra/Configs/Config.in
libc/stdlib/malloc/Makefile
libc/stdlib/malloc/free.c
libc/stdlib/malloc/heap_debug.c
libc/stdlib/malloc/malloc.c
libc/stdlib/malloc/malloc.h
libc/stdlib/malloc/malloc_debug.c [new file with mode: 0644]
libc/stdlib/malloc/realloc.c

index 3b5fcf1..089c1b4 100644 (file)
@@ -367,4 +367,15 @@ config SUPPORT_LD_DEBUG_EARLY
          to debug the uClibc shared library loader early initialization,
          answer Y.  Mere mortals answer N.
 
+config UCLIBC_MALLOC_DEBUGGING
+       bool "Build malloc with debugging support"
+       depends MALLOC
+       default n
+       help
+         Answer Y here to compile extra debugging support code into malloc.
+         Malloc debugging output may then be enabled at runtime using
+         the MALLOC_DEBUG environment variable.  Because this increases
+         the size of malloc appreciably (due to strings etc), you
+         should say N unless you need to debug a malloc problem.
+
 endmenu
index 9752762..d722d1d 100644 (file)
@@ -27,6 +27,16 @@ include $(TOPDIR)Rules.mak
 # calloc.c can be found at uClibc/libc/stdlib/calloc.c 
 CSRC = malloc.c free.c realloc.c memalign.c \
        heap_alloc.c heap_alloc_at.c heap_free.c
+
+# Turn on malloc debugging if requested
+ifeq ($(UCLIBC_MALLOC_DEBUGGING),y)
+CSRC += malloc_debug.c heap_debug.c
+CFLAGS += -DMALLOC_DEBUGGING -DHEAP_DEBUGGING
+ifeq ($(UCLIBC_UCLINUX_BROKEN_MUNMAP),y)
+CFLAGS += -DMALLOC_MMB_DEBUGGING
+endif
+endif
+
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 
@@ -37,10 +47,10 @@ $(LIBC): ar-target
 ar-target: $(OBJS)
        $(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
-$(COBJS): %.o : %.c
+# Depend on uClinux_config.h to cache changes in __UCLIBC_MALLOC_DEBUGGING__
+$(COBJS): %.o : %.c ../../../include/bits/uClibc_config.h
        $(CC) $(CFLAGS) -c $< -o $@
        $(STRIPTOOL) -x -R .note -R .comment $*.o
 
 clean:
        rm -f *.[oa] *~ core
-
index a00f996..3b2ec65 100644 (file)
@@ -31,7 +31,7 @@ free_to_heap (void *mem, struct heap *heap)
 
   /* Normal free.  */
 
-  MALLOC_DEBUG ("free: 0x%lx (base = 0x%lx, total_size = %d)\n",
+  MALLOC_DEBUG (1, "free: 0x%lx (base = 0x%lx, total_size = %d)",
                (long)mem, (long)MALLOC_BASE (mem), MALLOC_SIZE (mem));
 
   size = MALLOC_SIZE (mem);
@@ -76,7 +76,7 @@ free_to_heap (void *mem, struct heap *heap)
         reasonably cheap.  */
       if ((void *)end != sbrk (0))
        {
-         MALLOC_DEBUG ("  not unmapping: 0x%lx - 0x%lx (%ld bytes)\n",
+         MALLOC_DEBUG (-1, "not unmapping: 0x%lx - 0x%lx (%ld bytes)",
                        start, end, end - start);
          __malloc_unlock_sbrk ();
          __heap_unlock (heap);
@@ -84,7 +84,7 @@ free_to_heap (void *mem, struct heap *heap)
        }
 #endif
 
-      MALLOC_DEBUG ("  unmapping: 0x%lx - 0x%lx (%ld bytes)\n",
+      MALLOC_DEBUG (0, "unmapping: 0x%lx - 0x%lx (%ld bytes)",
                    start, end, end - start);
 
       /* Remove FA from the heap.  */
@@ -119,7 +119,8 @@ free_to_heap (void *mem, struct heap *heap)
         exactly as we got them from mmap, so scan through our list of
         mmapped blocks, and return them in order.  */
 
-      MALLOC_MMB_DEBUG ("  walking mmb list for region 0x%x[%d]...\n", start, end - start);
+      MALLOC_MMB_DEBUG (1, "walking mmb list for region 0x%x[%d]...",
+                       start, end - start);
 
       prev_mmb = 0;
       mmb = __malloc_mmapped_blocks;
@@ -127,7 +128,7 @@ free_to_heap (void *mem, struct heap *heap)
             && ((mmb_end = (mmb_start = (unsigned long)mmb->mem) + mmb->size)
                 <= end))
        {
-         MALLOC_MMB_DEBUG ("    considering mmb at 0x%x: 0x%x[%d]\n",
+         MALLOC_MMB_DEBUG (1, "considering mmb at 0x%x: 0x%x[%d]",
                            (unsigned)mmb, mmb_start, mmb_end - mmb_start);
 
          if (mmb_start >= start
@@ -143,18 +144,20 @@ free_to_heap (void *mem, struct heap *heap)
                   this block, so give up.  */
                break;
 
-             MALLOC_MMB_DEBUG ("      unmapping mmb at 0x%x: 0x%x[%d]\n",
+             MALLOC_MMB_DEBUG (1, "unmapping mmb at 0x%x: 0x%x[%d]",
                                (unsigned)mmb, mmb_start, mmb_end - mmb_start);
 
              if (mmb_start != start)
                /* We're going to unmap a part of the heap that begins after
                   start, so put the intervening region back into the heap.  */
                {
-                 MALLOC_MMB_DEBUG ("        putting intervening region back into heap: 0x%x[%d]\n",
+                 MALLOC_MMB_DEBUG (0, "putting intervening region back into heap: 0x%x[%d]",
                                    start, mmb_start - start);
                  __heap_free (heap, (void *)start, mmb_start - start);
                }
 
+             MALLOC_MMB_DEBUG_INDENT (-1);
+
              /* Unlink MMB from the list.  */
              if (prev_mmb)
                prev_mmb->next = next_mmb;
@@ -194,17 +197,21 @@ free_to_heap (void *mem, struct heap *heap)
              prev_mmb = mmb;
              mmb = mmb->next;
            }
+
+         MALLOC_MMB_DEBUG_INDENT (-1);
        }
 
       if (start != end)
        /* Hmm, well there's something we couldn't unmap, so put it back
           into the heap.  */
        {
-         MALLOC_MMB_DEBUG ("    putting tail region back into heap: 0x%x[%d]\n",
+         MALLOC_MMB_DEBUG (0, "putting tail region back into heap: 0x%x[%d]",
                            start, end - start);
          __heap_free (heap, (void *)start, end - start);
        }
 
+      MALLOC_MMB_DEBUG_INDENT (-1);
+
 # else /* !__UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
 
       /* MEM/LEN may not be page-aligned, so we have to page-align them,
@@ -241,6 +248,8 @@ free_to_heap (void *mem, struct heap *heap)
 
 #endif /* MALLOC_USE_SBRK */
     }
+
+  MALLOC_DEBUG_INDENT (-1);
 }
 
 void
index 85ed156..c1a1273 100644 (file)
@@ -16,6 +16,7 @@
 #include <stdarg.h>
 #include <string.h>
 
+#include "malloc.h"
 #include "heap.h"
 
 
@@ -29,14 +30,14 @@ __heap_dump_freelist (struct heap *heap)
 {
   struct heap_free_area *fa;
   for (fa = heap->free_areas; fa; fa = fa->next)
-    fprintf (stderr,
-            "    0x%lx:  0x%lx - 0x%lx  (%d)\tP=0x%lx, N=0x%lx\n",
-            (long)fa,
-            (long)HEAP_FREE_AREA_START (fa),
-            (long)HEAP_FREE_AREA_END (fa),
-            fa->size,
-            (long)fa->prev,
-            (long)fa->next);
+    __malloc_debug_printf (0,
+                          "0x%lx:  0x%lx - 0x%lx  (%d)\tP=0x%lx, N=0x%lx",
+                          (long)fa,
+                          (long)HEAP_FREE_AREA_START (fa),
+                          (long)HEAP_FREE_AREA_END (fa),
+                          fa->size,
+                          (long)fa->prev,
+                          (long)fa->next);
 }
 
 /* Output a text representation of HEAP to stderr, labelling it with STR.  */
@@ -51,8 +52,9 @@ __heap_dump (struct heap *heap, const char *str)
 
       recursed = 1;
 
-      fprintf (stderr, "  %s: heap @0x%lx:\n", str, (long)heap);
+      __malloc_debug_printf (1, "%s: heap @0x%lx:", str, (long)heap);
       __heap_dump_freelist (heap);
+      __malloc_debug_indent (-1);
 
       recursed = 0;
     }
@@ -76,7 +78,10 @@ __heap_check_failure (struct heap *heap, struct heap_free_area *fa,
   vfprintf (stderr, fmt, val);
   va_end (val);
 
-  fprintf (stderr, "\nheap dump:\n");
+  putc ('\n', stderr);
+
+  __malloc_debug_set_indent (0);
+  __malloc_debug_printf (1, "heap dump:");
   __heap_dump_freelist (heap);
 
   exit (22);
index b23d566..4466367 100644 (file)
@@ -29,10 +29,6 @@ struct heap __malloc_heap = HEAP_INIT_WITH_FA (initial_fa);
 malloc_mutex_t __malloc_sbrk_lock;
 #endif /* MALLOC_USE_LOCKING && MALLOC_USE_SBRK */
 
-#ifdef MALLOC_DEBUGGING
-int __malloc_debug = 0;
-#endif
-
 
 #ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
 /* A list of all malloc_mmb structures describing blocsk that
@@ -44,10 +40,6 @@ struct malloc_mmb *__malloc_mmapped_blocks = 0;
    annoying ways.  */
 HEAP_DECLARE_STATIC_FREE_AREA (initial_mmb_fa, 48); /* enough for 3 mmbs */
 struct heap __malloc_mmb_heap = HEAP_INIT_WITH_FA (initial_mmb_fa);
-
-# ifdef MALLOC_MMB_DEBUGGING
-int __malloc_mmb_debug = 0;
-# endif
 #endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
 
 
@@ -56,7 +48,7 @@ malloc_from_heap (size_t size, struct heap *heap)
 {
   void *mem;
 
-  MALLOC_DEBUG ("malloc: %d bytes\n", size);
+  MALLOC_DEBUG (1, "malloc: %d bytes", size);
 
   /* Include extra space to record the size of the allocated block.  */
   size += MALLOC_HEADER_SIZE;
@@ -121,7 +113,7 @@ malloc_from_heap (size_t size, struct heap *heap)
          struct malloc_mmb *mmb, *prev_mmb, *new_mmb;
 #endif
 
-         MALLOC_DEBUG ("  adding memory: 0x%lx - 0x%lx (%d bytes)\n",
+         MALLOC_DEBUG (1, "adding system memroy to heap: 0x%lx - 0x%lx (%d bytes)",
                        (long)block, (long)block + block_size, block_size);
 
          /* Get back the heap lock.  */
@@ -130,6 +122,8 @@ malloc_from_heap (size_t size, struct heap *heap)
          /* Put BLOCK into the heap.  */
          __heap_free (heap, block, block_size);
 
+         MALLOC_DEBUG_INDENT (-1);
+
          /* Try again to allocate.  */
          mem = __heap_alloc (heap, &size);
 
@@ -155,7 +149,7 @@ malloc_from_heap (size_t size, struct heap *heap)
          else
            __malloc_mmapped_blocks = new_mmb;
 
-         MALLOC_MMB_DEBUG ("  new mmb at 0x%x: 0x%x[%d]\n",
+         MALLOC_MMB_DEBUG (0, "new mmb at 0x%x: 0x%x[%d]",
                            (unsigned)new_mmb,
                            (unsigned)new_mmb->mem, block_size);
 #endif /* !MALLOC_USE_SBRK && __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
@@ -167,9 +161,11 @@ malloc_from_heap (size_t size, struct heap *heap)
     {
       mem = MALLOC_SETUP (mem, size);
 
-      MALLOC_DEBUG ("  malloc: returning 0x%lx (base:0x%lx, total_size:%d)\n",
+      MALLOC_DEBUG (-1, "malloc: returning 0x%lx (base:0x%lx, total_size:%ld)",
                    (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem));
     }
+  else
+    MALLOC_DEBUG (-1, "malloc: returning 0");
 
   return mem;
 }
@@ -177,5 +173,16 @@ malloc_from_heap (size_t size, struct heap *heap)
 void *
 malloc (size_t size)
 {
+#ifdef MALLOC_DEBUGGING
+  static int debugging_initialized = 0;
+  if (! debugging_initialized)
+    {
+      debugging_initialized = 1;
+      __malloc_debug_init ();
+    }
+  if (__malloc_check)
+    __heap_check (&__malloc_heap, "malloc");
+#endif
+
   return malloc_from_heap (size, &__malloc_heap);
 }
index db0fb9b..7fe8b60 100644 (file)
@@ -78,12 +78,18 @@ extern struct heap __malloc_mmb_heap;
    about mmap block allocation/freeing by the `uclinux broken munmap' code
    to stderr, when the variable __malloc_mmb_debug is set to true. */
 #ifdef MALLOC_MMB_DEBUGGING
-#include <stdio.h>
+# include <stdio.h>
 extern int __malloc_mmb_debug;
-#define MALLOC_MMB_DEBUG(fmt, args...) \
-  (__malloc_mmb_debug ? fprintf (stderr, fmt , ##args) : 0)
+# define MALLOC_MMB_DEBUG(indent, fmt, args...)                                      \
+   (__malloc_mmb_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0)
+# define MALLOC_MMB_DEBUG_INDENT(indent)                                     \
+   (__malloc_mmb_debug ? __malloc_debug_indent (indent) : 0)
+# ifndef MALLOC_DEBUGGING
+#  define MALLOC_DEBUGGING
+# endif
 #else /* !MALLOC_MMB_DEBUGGING */
-#define MALLOC_MMB_DEBUG(fmt, args...) (void)0
+# define MALLOC_MMB_DEBUG(fmt, args...) (void)0
+# define MALLOC_MMB_DEBUG_INDENT(indent) (void)0
 #endif /* MALLOC_MMB_DEBUGGING */
 
 #endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
@@ -158,13 +164,30 @@ extern malloc_mutex_t __malloc_sbrk_lock;
 /* Define MALLOC_DEBUGGING to cause malloc to emit debugging info to stderr
    when the variable __malloc_debug is set to true. */
 #ifdef MALLOC_DEBUGGING
-#include <stdio.h>
-extern int __malloc_debug;
-#define MALLOC_DEBUG(fmt, args...) \
-  (__malloc_debug ? fprintf (stderr, fmt , ##args) : 0)
-#else
-#define MALLOC_DEBUG(fmt, args...) (void)0
-#endif
+
+extern int __malloc_debug, __malloc_check;
+
+# define MALLOC_DEBUG(indent, fmt, args...)                                  \
+   (__malloc_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0)
+# define MALLOC_DEBUG_INDENT(indent)                                         \
+   (__malloc_debug ? __malloc_debug_indent (indent) : 0)
+
+extern int __malloc_debug_cur_indent;
+
+/* Print FMT and args indented at the current debug print level, followed
+   by a newline, and change the level by INDENT.  */
+extern void __malloc_debug_printf (int indent, const char *fmt, ...);
+
+/* Change the current debug print level by INDENT.  */
+#define __malloc_debug_indent(indent) (__malloc_debug_cur_indent += indent)
+
+/* Set the current debug print level to LEVEL.  */
+#define __malloc_debug_set_indent(level) (__malloc_debug_cur_indent = level)
+
+#else /* !MALLOC_DEBUGGING */
+# define MALLOC_DEBUG(fmt, args...) (void)0
+# define MALLOC_DEBUG_INDENT(indent) (void)0
+#endif /* MALLOC_DEBUGGING */
 
 
 /* Return SZ rounded down to POWER_OF_2_SIZE (which must be power of 2).  */
diff --git a/libc/stdlib/malloc/malloc_debug.c b/libc/stdlib/malloc/malloc_debug.c
new file mode 100644 (file)
index 0000000..20a37f2
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * libc/stdlib/malloc/malloc_debug.c -- malloc debugging support
+ *
+ *  Copyright (C) 2002  NEC Corporation
+ *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License.  See the file COPYING.LIB in the main
+ * directory of this archive for more details.
+ * 
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "malloc.h"
+#include "heap.h"
+
+#ifdef MALLOC_DEBUGGING
+int __malloc_debug = 0, __malloc_check = 0;
+#endif
+
+#ifdef MALLOC_MMB_DEBUGGING
+int __malloc_mmb_debug = 0;
+#endif
+
+/* Debugging output is indented this may levels.  */
+int __malloc_debug_cur_indent = 0;
+
+
+/* Print FMT and args indented at the current debug print level, followed
+   by a newline, and change the level by INDENT.  */
+void
+__malloc_debug_printf (int indent, const char *fmt, ...)
+{
+  int i;
+  va_list val;
+
+  for (i = 0; i < __malloc_debug_cur_indent; i++)
+    fputs ("   ", stderr);
+
+  va_start (val, fmt);
+  vfprintf (stderr, fmt, val);
+  va_end (val);
+
+  putc ('\n', stderr);
+
+  __malloc_debug_indent (indent);
+}
+
+void
+__malloc_debug_init (void)
+{
+  char *ev = getenv ("MALLOC_DEBUG");
+  if (ev)
+    {
+      int val = atoi (ev);
+      if (val & 1)
+       __malloc_check = 1;
+
+#ifdef MALLOC_DEBUGGING
+      if (val & 2)
+       __malloc_debug = 1;
+#endif
+#ifdef MALLOC_MMB_DEBUGGING
+      if (val & 4)
+       __malloc_mmb_debug = 1;
+#endif
+
+#ifdef HEAP_DEBUGGING
+      if (val & 8)
+       __heap_debug = 1;
+#endif
+
+      if (val)
+       __malloc_debug_printf
+         (0, "malloc_debug: initialized to %d (check = %d, dump = %d, dump_mmb = %d, dump_heap = %d)",
+          val,
+          !!(val & 1), !!(val & 2),
+          !!(val & 4), !!(val & 8));
+    }
+}
index 9bfe951..d4e0d9c 100644 (file)
@@ -43,7 +43,7 @@ realloc (void *mem, size_t new_size)
      allocation unit (SIZE is already guaranteed to be so).*/
   new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE);
 
-  MALLOC_DEBUG ("realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)\n",
+  MALLOC_DEBUG (1, "realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)",
                (long)mem, new_size, (long)base_mem, size);
 
   if (new_size > size)
@@ -81,9 +81,10 @@ realloc (void *mem, size_t new_size)
     }
 
   if (mem)
-    MALLOC_DEBUG ("  realloc: returning 0x%lx"
-                 " (base:0x%lx, total_size:%d)\n",
+    MALLOC_DEBUG (-1, "realloc: returning 0x%lx (base:0x%lx, total_size:%d)",
                  (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem));
+  else
+    MALLOC_DEBUG (-1, "realloc: returning 0");
 
   return mem;
 }