⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mprof.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * A tool designed to read a profiling output file produced by the mpatrol * library and display the profiling information that was obtained. */#include "tree.h"#include "graph.h"#include "getopt.h"#include "version.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#if MP_IDENT_SUPPORT#ident "$Id: mprof.c,v 1.34 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *mprof_id = "$Id: mprof.c,v 1.34 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#define PROGVERSION "1.3" /* the current version of this program *//* The flags used to parse the command line options. */typedef enum options_flags{    OF_ADDRESSES  = 'a',    OF_COUNTS     = 'c',    OF_GRAPHFILE  = 'g',    OF_HELP       = 'h',    OF_LEAKS      = 'l',    OF_STACKDEPTH = 'n',    OF_VERSION    = 'V',    OF_CALLGRAPH  = 'v'}options_flags;/* Structure containing statistics about the counts and totals of all of the * small, medium, large and extra large allocations and deallocations for a * particular call site. */typedef struct profiledata{    size_t acount[4]; /* total numbers of allocations */    size_t dcount[4]; /* total numbers of deallocations */    size_t atotal[4]; /* total numbers of allocated bytes */    size_t dtotal[4]; /* total numbers of deallocated bytes */}profiledata;/* Structure containing profiling details for a function in a call stack. */typedef struct profilenode{    treenode node;        /* tree node */    treenode tnode;       /* temporary tree node */    unsigned long parent; /* parent node */    void *addr;           /* return address */    unsigned long symbol; /* associated symbol */    unsigned long name;   /* associated symbol name */    unsigned long data;   /* profiling data */    profiledata tdata;    /* temporary profiling data */    unsigned char flags;  /* temporary flags */}profilenode;/* Structure representing a vertex in the allocation call graph. */typedef struct vertex{    treenode node;       /* tree node */    graphnode gnode;     /* graph node */    profilenode *pnode;  /* profiling node */    unsigned long index; /* vertex index */}vertex;/* Structure representing an edge in the allocation call graph. */typedef struct edge{    listnode node;       /* list node */    graphedge gnode;     /* edge node */    profiledata data;    /* profiling data */    unsigned char flags; /* temporary flags */}edge;/* The version of the mpatrol library which produced the profiling output file. */static unsigned long version;/* The total number of allocations and deallocations. */static size_t acount, dcount;/* The total bytes of allocations and deallocations. */static size_t atotal, dtotal;/* The allocation and deallocation bins. */static size_t *acounts, *dcounts;/* The total bytes of large allocations and deallocations. */static size_t atotals, dtotals;/* The number of allocation bins. */static size_t binsize;/* The allocations and deallocations for all call sites. */static profiledata *data;/* The number of profiledata structures for all call sites. */static size_t datasize;/* The profiling details for all call sites. */static profilenode *nodes;/* The number of profilenode structures for all call sites. */static size_t nodesize;/* The array containing the symbol addresses. */static void **addrs;/* The string table containing the symbol names. */static char *symbols;/* The small, medium and large allocation boundaries. */static size_t sbound, mbound, lbound;/* The tree containing profiling details for all call sites. */static treeroot proftree;/* The tree containing temporary profiling details for all call sites. */static treeroot temptree;/* The list of edges in the allocation call graph. */static listhead edgelist;/* The allocation call graph. */static graphhead graph;/* The profiling output file produced by mpatrol. */static FILE *proffile;/* The graph specification file optionally produced by mprof. */static FILE *graphfile;/* The filename used to invoke this tool. */static char *progname;/* Indicates if different allocation points within single functions should * be noted when displaying the profiling tables. */static int useaddresses;/* Indicates if the emphasis will be on allocation counts rather than * allocated bytes when displaying the profiling tables. */static int showcounts;/* Indicates if memory leaks rather than memory allocations should be written * to the graph specification file. */static int showleaks;/* Indicates the maximum stack depth to use when comparing function call * stacks for the memory leak table. */static unsigned long maxstack;/* Indicates if the allocation call graph should be displayed. */static int showgraph;/* The table describing all recognised options. */static option options_table[] ={    {"addresses", OF_ADDRESSES, NULL,     "\tSpecifies that different call sites from within the same function\n"     "\tare to be differentiated and that the names of all functions should\n"     "\tbe displayed with their call site offset in bytes.\n"},    {"call-graph", OF_CALLGRAPH, NULL,     "\tSpecifies that the allocation call graph should be displayed.\n"},    {"counts", OF_COUNTS, NULL,     "\tSpecifies that certain tables should be sorted by the number of\n"     "\tallocations or deallocations rather than the total number of bytes\n"     "\tallocated or deallocated.\n"},    {"graph-file", OF_GRAPHFILE, "file",     "\tSpecifies that the allocation call graph should also be written to a\n"     "\tgraph specification file for later visualisation with dot.\n"},    {"help", OF_HELP, NULL,     "\tDisplays this quick-reference option summary.\n"},    {"leaks", OF_LEAKS, NULL,     "\tSpecifies that memory leaks rather than memory allocations are to be\n"     "\twritten to the graph specification file.\n"},    {"stack-depth", OF_STACKDEPTH, "depth",     "\tSpecifies the maximum stack depth to display and also use when\n"     "\tcalculating if one call site has the same call stack as another call\n"     "\tsite.\n"},    {"version", OF_VERSION, NULL,     "\tDisplays the version number of this program.\n"},    NULL};/* Clear the statistics for a set of profiling data. */staticvoidcleardata(profiledata *a){    size_t i;    for (i = 0; i < 4; i++)    {        a->acount[i] = 0;        a->dcount[i] = 0;        a->atotal[i] = 0;        a->dtotal[i] = 0;    }}/* Sum the statistics from two sets of profiling data. */staticvoidsumdata(profiledata *a, profiledata *b){    size_t i;    for (i = 0; i < 4; i++)    {        a->acount[i] += b->acount[i];        a->dcount[i] += b->dcount[i];        a->atotal[i] += b->atotal[i];        a->dtotal[i] += b->dtotal[i];    }}/* Compare two function call stacks. */staticintcomparestack(profilenode *n, profilenode *p, int c){    size_t i;    for (i = 1; (c != 0) || (maxstack == 0) || (i < maxstack); i++)    {        if ((n->parent == 0) || (p->parent == 0))            return ((n->parent == 0) && (p->parent == 0));        n = &nodes[n->parent - 1];        p = &nodes[p->parent - 1];        if ((n->addr != p->addr) && (useaddresses || (n->symbol == 0) ||             (n->symbol != p->symbol)))            return 0;    }    return 1;}/* Byte-swap a block of memory. */staticvoidbyteswap(void *b, size_t n){    char *s, *t;    char c;    s = (char *) b;    t = (char *) b + n - 1;    while (s < t)    {        c = *s;        *s++ = *t;        *t-- = c;    }}/* Read an entry from the profiling output file. */staticvoidgetentry(void *d, size_t l, size_t n, int b){    size_t i;    if (fread(d, l, n, proffile) != n)    {        fprintf(stderr, "%s: Error reading file\n", progname);        exit(EXIT_FAILURE);    }    /* Byte-swap all of the elements if necessary.     */    if (b != 0)        for (i = 0; i < n; i++)        {            byteswap(d, l);            d = (char *) d + l;        }}/* Read all of the data from the profiling output file. */staticvoidreadfile(void){    char s[4];    profiledata *d;    profilenode *p;    size_t i;    unsigned long n;    int b;    /* When reading the profiling output file, we assume that if it begins and     * ends with the magic sequence of characters then it is a valid profiling     * output file from the mpatrol library.  There are probably an infinite     * number of checks we could do to ensure that the rest of the data in the     * file is valid, but that would be overcomplicated and probably slow this     * program down.  However, if the file is only partially written then the     * getentry() function will catch the error before we do something silly.     */    getentry(s, sizeof(char), 4, 0);    if (memcmp(s, MP_PROFMAGIC, 4) != 0)    {        fprintf(stderr, "%s: Invalid file format\n", progname);        exit(EXIT_FAILURE);    }    /* The following test allows us to read profiling output files that were     * produced on a different processor architecture.  If the next word in the     * file does not contain the value 1 then we have to byte-swap any further     * data that we read from the file.  Note that this test only works if the     * word size is the same on both machines.     */    getentry(&i, sizeof(size_t), 1, 0);    b = (i != 1);    /* Get the version number of the mpatrol library which produced the     * profiling output file.  The profiling file format changed to include the     * version number at mpatrol 1.3.0 so we can't reliably read files produced     * before then.  We also assume that we can't read files produced by later     * versions of mpatrol.     */    getentry(&version, sizeof(unsigned long), 1, b);    if (version < 10300)    {        fprintf(stderr, "%s: Profiling file version too old\n", progname);        exit(EXIT_FAILURE);    }    else if (version / 100 > MP_VERNUM / 100)    {        fprintf(stderr, "%s: Profiling file version too new\n", progname);        exit(EXIT_FAILURE);    }    getentry(&sbound, sizeof(size_t), 1, b);    getentry(&mbound, sizeof(size_t), 1, b);    getentry(&lbound, sizeof(size_t), 1, b);    /* Read the allocation and deallocation bins.     */    getentry(&binsize, sizeof(size_t), 1, b);    if (binsize > 0)    {        if (((acounts = (size_t *) malloc(binsize * sizeof(size_t))) == NULL) ||            ((dcounts = (size_t *) malloc(binsize * sizeof(size_t))) == NULL))        {            fprintf(stderr, "%s: Out of memory\n", progname);            exit(EXIT_FAILURE);        }        getentry(acounts, sizeof(size_t), binsize, b);        getentry(&atotals, sizeof(size_t), 1, b);        getentry(dcounts, sizeof(size_t), binsize, b);        getentry(&dtotals, sizeof(size_t), 1, b);        for (i = 0; i < binsize; i++)        {            acount += acounts[i];            dcount += dcounts[i];            if (i == binsize - 1)            {                atotal += atotals;                dtotal += dtotals;            }            else            {                atotal += acounts[i] * (i + 1);                dtotal += dcounts[i] * (i + 1);            }        }    }    /* Read the profiling data structures.     */    getentry(&datasize, sizeof(size_t), 1, b);    if (datasize > 0)    {        if ((data = (profiledata *) malloc(datasize * sizeof(profiledata))) ==            NULL)        {            fprintf(stderr, "%s: Out of memory\n", progname);            exit(EXIT_FAILURE);        }        for (i = 0; i < datasize; i++)        {            getentry(&n, sizeof(unsigned long), 1, b);            d = &data[n - 1];            getentry(d->acount, sizeof(size_t), 4, b);            getentry(d->atotal, sizeof(size_t), 4, b);            getentry(d->dcount, sizeof(size_t), 4, b);            getentry(d->dtotal, sizeof(size_t), 4, b);        }    }    /* Read the statistics for every call site.     */    getentry(&nodesize, sizeof(size_t), 1, b);    if (nodesize > 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -