OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / uClibc / libc / stdlib / malloc / heap_debug.c
1 /*
2  * libc/stdlib/malloc/heap_debug.c -- optional heap debugging routines
3  *
4  *  Copyright (C) 2002  NEC Corporation
5  *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
6  *
7  * This file is subject to the terms and conditions of the GNU Lesser
8  * General Public License.  See the file COPYING.LIB in the main
9  * directory of this archive for more details.
10  *
11  * Written by Miles Bader <miles@gnu.org>
12  */
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <unistd.h>
19
20
21 #include "malloc.h"
22 #include "heap.h"
23
24
25 #ifdef HEAP_DEBUGGING
26 int __heap_debug = 0;
27 #endif
28
29
30 static void
31 __heap_dump_freelist (struct heap_free_area *heap)
32 {
33   struct heap_free_area *fa;
34   for (fa = heap; fa; fa = fa->next)
35     __malloc_debug_printf (0,
36                            "0x%lx:  0x%lx - 0x%lx  (%d)\tP=0x%lx, N=0x%lx",
37                            (long)fa,
38                            (long)HEAP_FREE_AREA_START (fa),
39                            (long)HEAP_FREE_AREA_END (fa),
40                            fa->size,
41                            (long)fa->prev,
42                            (long)fa->next);
43 }
44
45 /* Output a text representation of HEAP to stderr, labelling it with STR.  */
46 void
47 __heap_dump (struct heap_free_area *heap, const char *str)
48 {
49   static smallint recursed;
50
51   if (! recursed)
52     {
53       __heap_check (heap, str);
54
55       recursed = 1;
56
57       __malloc_debug_printf (1, "%s: heap @0x%lx:", str, (long)heap);
58       __heap_dump_freelist (heap);
59       __malloc_debug_indent (-1);
60
61       recursed = 0;
62     }
63 }
64
65
66 /* Output an error message to stderr, and exit.  STR is printed with the
67    failure message.  */
68 static void attribute_noreturn
69 __heap_check_failure (struct heap_free_area *heap, struct heap_free_area *fa,
70                       const char *str, char *fmt, ...)
71 {
72   va_list val;
73
74   if (str)
75     fprintf (stderr, "\nHEAP CHECK FAILURE %s: ", str);
76   else
77     fprintf (stderr, "\nHEAP CHECK FAILURE: ");
78
79   va_start (val, fmt);
80   vfprintf (stderr, fmt, val);
81   va_end (val);
82
83   fprintf (stderr, "\n");
84
85   __malloc_debug_set_indent (0);
86   __malloc_debug_printf (1, "heap dump:");
87   __heap_dump_freelist (heap);
88
89   _exit (22);
90 }
91
92 /* Do some consistency checks on HEAP.  If they fail, output an error
93    message to stderr, and exit.  STR is printed with the failure message.  */
94 void
95 __heap_check (struct heap_free_area *heap, const char *str)
96 {
97   typedef unsigned long ul_t;
98   struct heap_free_area *fa, *prev;
99   struct heap_free_area *first_fa = heap;
100
101   if (first_fa && first_fa->prev)
102     __heap_check_failure (heap, first_fa, str,
103 "first free-area has non-zero prev pointer:\n\
104     first free-area = 0x%lx\n\
105     (0x%lx)->prev   = 0x%lx\n",
106                               (ul_t)first_fa,
107                               (ul_t)first_fa, (ul_t)first_fa->prev);
108
109   for (prev = 0, fa = first_fa; fa; prev = fa, fa = fa->next)
110     {
111       if (((ul_t)HEAP_FREE_AREA_END (fa) & (HEAP_GRANULARITY - 1))
112           || (fa->size & (HEAP_GRANULARITY - 1)))
113         __heap_check_failure (heap, fa, str, "alignment error:\n\
114     (0x%lx)->start = 0x%lx\n\
115     (0x%lx)->size  = 0x%lx\n",
116                               (ul_t)fa,
117                               (ul_t)HEAP_FREE_AREA_START (fa),
118                               (ul_t)fa, fa->size);
119
120       if (fa->prev != prev)
121         __heap_check_failure (heap, fa, str, "prev pointer corrupted:\n\
122     (0x%lx)->next = 0x%lx\n\
123     (0x%lx)->prev = 0x%lx\n",
124                               (ul_t)prev, (ul_t)prev->next,
125                               (ul_t)fa, (ul_t)fa->prev);
126
127       if (prev)
128         {
129           ul_t start = (ul_t)HEAP_FREE_AREA_START (fa);
130           ul_t prev_end = (ul_t)HEAP_FREE_AREA_END (prev);
131
132           if (prev_end >= start)
133             __heap_check_failure (heap, fa, str,
134                                   "start %s with prev free-area end:\n\
135     (0x%lx)->prev  = 0x%lx\n\
136     (0x%lx)->start = 0x%lx\n\
137     (0x%lx)->end   = 0x%lx\n",
138                                   (prev_end == start ? "unmerged" : "overlaps"),
139                                   (ul_t)fa, (ul_t)prev,
140                                   (ul_t)fa, start,
141                                   (ul_t)prev, prev_end);
142         }
143     }
144 }