/* * $XConsortium: ibmPlumber.c,v 1.2 91/07/16 13:09:22 jap Exp $ * * Copyright IBM Corporation 1987,1988,1989,1990,1991 * * All Rights Reserved * * License to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of IBM not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * */ /* plumber.c - check malloc arena for coreleaks author: WJHansen, CMU/ITC (c) Copyright IBM Corporation, 1986 Uses the IDENTIFY version of malloc, which stores the return address in the header of each block. Produces a table showing a description of the set of blocks produced from each calling address. WARNING: if an application does sbrk's of its own, the arena will be in multiple segments. The code here only processes the last of these. */ #define IDENTIFY #include #include "ibmMalloc.h" #ifndef IDENTIFY plumber () { } #else static struct callerdata { struct callerdata *left, *right; char *caller; int nblks; long totsize; int loseq, hiseq, losize, hisize; } *data; plumber (outf) FILE *outf; { register struct arenastate *A = GetMallocArena(); register int nextseq = A->SeqNo; register struct freehdr *t, *f; /* scan free list to find segment trailers and scan each segment */ CheckAllocs("plumber start"); data = NULL; t = A->arenaend; f = ((struct freetrlr *)(t+1))->Front; /* scan the last arena segment for active blocks */ for (; fSize))) if (testbit(f->Size, ACTIVE) && f->seqnocaller = p->caller; td->nblks = 1; td->loseq = td->hiseq = p->seqno; td->losize = td->hisize = td->totsize = clearbits(p->Size); } else if (p->caller < td->caller) storedata (p, &(td->left)); else if (p->caller > td->caller) storedata (p, &(td->right)); else { /* == */ int size = clearbits(p->Size); td->nblks++; if (p->seqnoloseq) td->loseq = p->seqno; else if (p->seqno>td->hiseq) td->hiseq = p->seqno; if (sizelosize) td->losize = size; else if (size>td->hisize) td->hisize = size; td->totsize += size; } } static printandfreedata(d, outf) register struct callerdata *d; FILE *outf; { if (d) { printandfreedata(d->left, outf); fprintf (outf, "0x%-8lx%10d%10d%9d-%-10d%9d-%-10d\n", d->caller, d->nblks, d->totsize, d->losize, d->hisize, d->loseq, d->hiseq); printandfreedata(d->right, outf); free(d); } } /* * calloc - allocate and clear memory block */ #define CHARPERINT (sizeof(int)/sizeof(char)) #define NULL 0 #ifdef AIXV3 /* check here */ /* DPS run into big problem here */ #else char * calloc(num, size) unsigned num, size; { #define FIRSTARG num register char *mp; register int *q; register m; num *= size; mp = malloc(num); if (mp == NULL) return(NULL); /* Stamp pc of caller of calloc in malloc header */ (((struct hdr *)mp)-1)->caller = *(((char **)&FIRSTARG)-RETADDROFF); q = (int *) mp; m = (num+CHARPERINT-1)/CHARPERINT; while (--m>=0) *q++ = 0; return (mp); } #endif cfree(p, num, size) char *p; unsigned num, size; { free(p); } #endif