diff options
Diffstat (limited to 'libc/stdlib')
-rw-r--r-- | libc/stdlib/malloc/heap_debug.c | 83 |
1 files changed, 67 insertions, 16 deletions
diff --git a/libc/stdlib/malloc/heap_debug.c b/libc/stdlib/malloc/heap_debug.c index 1453a5a39..85ed15609 100644 --- a/libc/stdlib/malloc/heap_debug.c +++ b/libc/stdlib/malloc/heap_debug.c @@ -59,28 +59,79 @@ __heap_dump (struct heap *heap, const char *str) } +/* 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); + + fprintf (stderr, "\nheap dump:\n"); + __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; - for (prev = 0, fa = heap->free_areas; fa; prev = fa, fa = fa->next) - if (fa->prev != prev) - { - if (str) - fprintf (stderr, "\nHEAP CHECK FAILURE %s: ", str); - else - fprintf (stderr, "\nHEAP CHECK FAILURE: "); - - fprintf (stderr, - " prev pointer corrupted: P=0x%lx should be 0x%lx\n", - (long)fa->prev, (long)prev); - fprintf (stderr, "\nheap:\n"); + 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); - __heap_dump_freelist (heap); - - exit (22); - } + 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); + } + } } |