/* Author: Mark Moraes */ /*LINTLIBRARY*/ #include "defs.h" #include "globals.h" RCSID("$Id: dumpheap.c,v 1.2 1999/12/30 03:26:07 mea Exp $") int __m_prblock(p, is_end_ptr, fp) univptr_t p; int is_end_ptr; FILE *fp; { Word *blk = (Word *) p; Word *blkend; ulong tag; ulong blksize; char buf[512]; /* long enough for the sprintfs below */ if (blk == NULL) return 0; if ( ! PTR_IN_HEAP(blk)) { sprintf(buf, "# ** pointer 0x%lx not in heap\n", (ulong) blk); fputs(buf, fp); return 0; } blksize = SIZE(blk); tag = TAG(blk); if (is_end_ptr) { blkend = blk; blk -= blksize - 1; } else { blkend = blk + blksize - 1; } (void) sprintf(buf, "# %s blk: 0x%lx to 0x%lx, %lu (0x%lx) words", tag == FREE ? "Free" : "Allocated", (ulong) blk, (ulong) blkend, blksize, blksize); (void) fputs(buf, fp); if ( is_end_ptr && ! PTR_IN_HEAP(blk)) { sprintf(buf, "# ** start pointer 0x%lx not in heap\n", (ulong) blk); fputs(buf, fp); return 0; } if ( !is_end_ptr && ! PTR_IN_HEAP(blkend)) { sprintf(buf, "# ** end pointer 0x%lx not in heap\n", (ulong) blk); fputs(buf, fp); return 0; } if (tag == FREE) { int i, n; char *cp; (void) sprintf(buf, "# next=0x%lx, prev=0x%lx\n", (ulong) NEXT(blkend), (ulong) PREV(blkend)); (void) fputs(buf, fp); /* Make sure free block is filled with FREEMAGIC */ n = (blksize - FREE_OVERHEAD) * sizeof(Word); cp = (char *) (blk + FREEHEADERWORDS); #ifdef DEBUG for (i = 0; i < n; i++, cp++) { if (*cp != FREEMAGIC) { (void) fputs("# ** modified after free().\n", fp); break; } } #endif } else { #ifdef DEBUG (void) sprintf(buf, "# really %lu bytes\n", (ulong) REALSIZE(blk)); (void) fputs(buf, fp); #endif } if (TAG(blk) == FREE) { if( ! VALID_NEXT_PTR(blkend)) (void) fputs("# ** bad next pointer\n", fp); if( ! VALID_PREV_PTR(blkend)) (void) fputs("# ** bad prev pointer\n", fp); } else { if ( ! VALID_MAGIC(blk)) (void) fputs("# ** end of block overwritten\n", fp); } if ( ! VALID_START_SIZE_FIELD(blk)) { /* At some systems the size_t is 64 bits, while long is "mere" 32 bits (32-bit systems usually..) */ sprintf(buf, "# ** bad size field: tags = 0x%lx, 0x%lx\n", (unsigned long) SIZEFIELD(blk), (unsigned long) SIZEFIELD(blkend)); (void) fputs(buf, fp); return 0; } (void) fflush(fp); return 1; } /* * Similar to malloc_verify except that it prints the heap as it goes along. * The only ASSERTs in this routine are those that would cause it to wander * off into the sunset because of corrupt tags. */ void mal_heapdump(fp) FILE *fp; { REGISTER Word *ptr; REGISTER Word *blk; REGISTER Word *blkend; int i; char buf[512]; /* long enough for the sprintfs below */ if (_malloc_loword == NULL) { /* Nothing malloc'ed yet */ (void) fputs("# Null heap - nothing malloc'ed yet\n", fp); return; } (void) fputs("# Heap printout:\n", fp); (void) fputs("# Free list rover pointers:\n", fp); sprintf(buf, "# First non-null bin is %d\n", _malloc_firstbin); (void) fputs(buf, fp); for (i = 0; i < MAXBINS; i++) { if ((ptr = _malloc_rovers[i]) == NULL) continue; (void) sprintf(buf, "# %d: 0x%lx\n", i, (ulong) ptr); (void) fputs(buf, fp); if ( ! PTR_IN_HEAP(ptr)) (void) fputs("# ** not in heap\n", fp); if ( ! VALID_END_SIZE_FIELD(ptr)) (void) fputs("# ** bad end size field\n", fp); if ( ! VALID_NEXT_PTR(ptr)) (void) fputs("# ** bad next pointer\n", fp); if ( ! VALID_PREV_PTR(ptr)) (void) fputs("# ** bad prev pointer\n", fp); } if (_malloc_rovers[MAXBINS] != NULL) { (void) sprintf(buf, "# ** rover terminator is 0x%lx, fixing\n", (ulong) _malloc_rovers[MAXBINS]); (void) fputs(buf, fp); _malloc_rovers[MAXBINS] = NULL; } for (ptr = _malloc_mem; ptr != NULL; ptr = ptr->next) { /* print the arena */ (void) sprintf(buf, "# Arena from 0x%lx to 0x%lx, %lu (0x%lx) words\n", (ulong) ptr, (ulong) (ptr + SIZE(ptr+1)), (ulong) SIZE(ptr+1)+1, (ulong) SIZE(ptr+1)+1); (void) fputs(buf, fp); (void) sprintf(buf, "# Next arena is 0x%lx\n", (ulong)ptr->next); (void) fputs(buf, fp); (void) fflush(fp); ASSERT(SIZEFIELD(ptr+1) == SIZEFIELD(ptr + SIZE(ptr+1)), "# mal_dumpheap: corrupt malloc arena"); blkend = ptr + SIZE(ptr + 1); for(blk = ptr + ARENASTART; blk < blkend; blk += SIZE(blk)) { ASSERT(__m_prblock((univptr_t) blk, 0, fp), "# mal_dumpheap: corrupt block"); } } (void) fputs("# ==============\n", fp); (void) fflush(fp); }