OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / 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
19 libc_hidden_proto(vfprintf)
20 libc_hidden_proto(fprintf)
21
22 #include "malloc.h"
23 #include "heap.h"
24
25
26 #ifdef HEAP_DEBUGGING
27 int __heap_debug = 0;
28 #endif
29
30
31 static void
32 __heap_dump_freelist (struct heap *heap)
33 {
34   struct heap_free_area *fa;
35   for (fa = heap->free_areas; fa; fa = fa->next)
36     __malloc_debug_printf (0,
37                            "0x%lx:  0x%lx - 0x%lx  (%d)\tP=0x%lx, N=0x%lx",
38                            (long)fa,
39                            (long)HEAP_FREE_AREA_START (fa),
40                            (long)HEAP_FREE_AREA_END (fa),
41                            fa->size,
42                            (long)fa->prev,
43                            (long)fa->next);
44 }
45
46 /* Output a text representation of HEAP to stderr, labelling it with STR.  */
47 void
48 __heap_dump (struct heap *heap, const char *str)
49 {
50   static int recursed = 0;
51
52   if (! recursed)
53     {
54       __heap_check (heap, str);
55
56       recursed = 1;
57
58       __malloc_debug_printf (1, "%s: heap @0x%lx:", str, (long)heap);
59       __heap_dump_freelist (heap);
60       __malloc_debug_indent (-1);
61
62       recursed = 0;
63     }
64 }
65
66
67 /* Output an error message to stderr, and exit.  STR is printed with the
68    failure message.  */
69 static void
70 __heap_check_failure (struct heap *heap, struct heap_free_area *fa,
71                       const char *str, char *fmt, ...)
72 {
73   va_list val;
74
75   if (str)
76     fprintf (stderr, "\nHEAP CHECK FAILURE %s: ", str);
77   else
78     fprintf (stderr, "\nHEAP CHECK FAILURE: ");
79
80   va_start (val, fmt);
81   vfprintf (stderr, fmt, val);
82   va_end (val);
83
84   __putc ('\n', stderr);
85
86   __malloc_debug_set_indent (0);
87   __malloc_debug_printf (1, "heap dump:");
88   __heap_dump_freelist (heap);
89
90   __exit (22);
91 }
92
93 /* Do some consistency checks on HEAP.  If they fail, output an error
94    message to stderr, and exit.  STR is printed with the failure message.  */
95 void
96 __heap_check (struct heap *heap, const char *str)
97 {
98   typedef unsigned long ul_t;
99   struct heap_free_area *fa, *prev;
100   struct heap_free_area *first_fa = heap->free_areas;
101
102   if (first_fa && first_fa->prev)
103     __heap_check_failure (heap, first_fa, str,
104 "first free-area has non-zero prev pointer:\n\
105     first free-area = 0x%lx\n\
106     (0x%lx)->prev   = 0x%lx\n",
107                               (ul_t)first_fa,
108                               (ul_t)first_fa, (ul_t)first_fa->prev);
109
110   for (prev = 0, fa = first_fa; fa; prev = fa, fa = fa->next)
111     {
112       if (((ul_t)HEAP_FREE_AREA_END (fa) & (HEAP_GRANULARITY - 1))
113           || (fa->size & (HEAP_GRANULARITY - 1)))
114         __heap_check_failure (heap, fa, str, "alignment error:\n\
115     (0x%lx)->start = 0x%lx\n\
116     (0x%lx)->size  = 0x%lx\n",
117                               (ul_t)fa,
118                               (ul_t)HEAP_FREE_AREA_START (fa),
119                               (ul_t)fa, fa->size);
120
121       if (fa->prev != prev)
122         __heap_check_failure (heap, fa, str, "prev pointer corrupted:\n\
123     (0x%lx)->next = 0x%lx\n\
124     (0x%lx)->prev = 0x%lx\n",
125                               (ul_t)prev, (ul_t)prev->next,
126                               (ul_t)fa, (ul_t)fa->prev);
127
128       if (prev)
129         {
130           ul_t start = (ul_t)HEAP_FREE_AREA_START (fa);
131           ul_t prev_end = (ul_t)HEAP_FREE_AREA_END (prev);
132
133           if (prev_end >= start)
134             __heap_check_failure (heap, fa, str,
135                                   "start %s with prev free-area end:\n\
136     (0x%lx)->prev  = 0x%lx\n\
137     (0x%lx)->start = 0x%lx\n\
138     (0x%lx)->end   = 0x%lx\n",
139                                   (prev_end == start ? "unmerged" : "overlaps"),
140                                   (ul_t)fa, (ul_t)prev,
141                                   (ul_t)fa, start,
142                                   (ul_t)prev, prev_end);
143         }
144     }
145 }