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 143 144
|
/*
* 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 <unistd.h>
#include "malloc.h"
#include "heap.h"
#ifdef HEAP_DEBUGGING
int __heap_debug = 0;
#endif
static void
__heap_dump_freelist (struct heap_free_area *heap)
{
struct heap_free_area *fa;
for (fa = heap; 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_free_area *heap, const char *str)
{
static smallint recursed;
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 attribute_noreturn
__heap_check_failure (struct heap_free_area *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);
fprintf (stderr, "\n");
__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_free_area *heap, const char *str)
{
typedef unsigned long ul_t;
struct heap_free_area *fa, *prev;
struct heap_free_area *first_fa = heap;
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);
}
}
}
|