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