Ejemplo n.º 1
0
MP_GLOBAL
void
__mp_deleteallocs(allochead *h)
{
    /* We don't need to explicitly free any memory as this is dealt with
     * at a lower level by the heap manager.
     */
    __mp_deleteheap(&h->heap);
    h->table.free = NULL;
    h->table.size = 0;
    __mp_newlist(&h->list);
    __mp_newlist(&h->flist);
    __mp_newtree(&h->itree);
    __mp_newtree(&h->atree);
    __mp_newtree(&h->gtree);
    __mp_newtree(&h->ftree);
    h->isize = h->asize = h->gsize = h->fsize = 0;
    h->prot = MA_NOACCESS;
    h->protrecur = 0;
}
Ejemplo n.º 2
0
MP_GLOBAL
void
__mp_newheap(heaphead *h)
{
    struct { char x; heapnode y; } z;
    long n;

    __mp_newmemory(&h->memory);
    /* Determine the minimum alignment for a heap node on this system
     * and force the alignment to be a power of two.  This information
     * is used when initialising the slot table.
     */
    n = (char *) &z.y - &z.x;
    __mp_newslots(&h->table, sizeof(heapnode), __mp_poweroftwo(n));
    __mp_newtree(&h->itree);
    __mp_newtree(&h->dtree);
    h->isize = h->dsize = 0;
    h->prot = MA_NOACCESS;
    h->protrecur = 0;
    h->tracing = 0;
}
Ejemplo n.º 3
0
MP_GLOBAL
void
__mp_newallocs(allochead *h, size_t m, size_t s, unsigned char o,
               unsigned char a, unsigned char f, unsigned long u)
{
    struct { char x; allocnode y; } z;
    long n;

    __mp_newheap(&h->heap);
    /* Determine the minimum alignment for an allocation node on this
     * system and force the alignment to be a power of two.  This
     * information is used when initialising the slot table.
     */
    n = (char *) &z.y - &z.x;
    __mp_newslots(&h->table, sizeof(allocnode), __mp_poweroftwo(n));
    __mp_newlist(&h->list);
    __mp_newlist(&h->flist);
    __mp_newtree(&h->itree);
    __mp_newtree(&h->atree);
    __mp_newtree(&h->gtree);
    __mp_newtree(&h->ftree);
    h->isize = h->asize = h->gsize = h->fsize = 0;
    h->fmax = m;
    h->oflow = __mp_poweroftwo(s);
    h->obyte = o;
    h->abyte = a;
    h->fbyte = f;
    h->flags = u;
    if (h->flags & FLG_PAGEALLOC)
    {
        if (h->oflow == 0)
            h->oflow = 1;
        h->oflow = __mp_roundup(h->oflow, h->heap.memory.page);
    }
    h->prot = MA_NOACCESS;
    h->protrecur = 0;
}
Ejemplo n.º 4
0
static
void
directtable(void)
{
    profiledata *d;
    profilenode *n, *p;
    treenode *t;
    profiledata m;
    size_t i;
    unsigned long a, b, c;
    double e, f;

    cleardata(&m);
    printchar(' ', 31);
    fputs("DIRECT ALLOCATIONS\n\n", stdout);
    printchar(' ', 20);
    fprintf(stdout, "(0 < s <= %lu < m <= %lu < l <= %lu < x)\n\n",
            sbound, mbound, lbound);
    if (showcounts)
    {
        printchar(' ', 9);
        fputs("allocated", stdout);
        printchar(' ', 21);
        fputs("unfreed\n", stdout);
        printchar('-', 27);
        fputs("  ", stdout);
        printchar('-', 27);
        fputs("\n count       %   s  m  l  x   "
              "count       %   s  m  l  x     bytes  function\n\n", stdout);
    }
    else
    {
        printchar(' ', 10);
        fputs("allocated", stdout);
        printchar(' ', 23);
        fputs("unfreed\n", stdout);
        printchar('-', 29);
        fputs("  ", stdout);
        printchar('-', 29);
        fputs("\n   bytes       %   s  m  l  x     "
              "bytes       %   s  m  l  x   count  function\n\n", stdout);
    }
    for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = p)
    {
        p = (profilenode *) __mp_successor(&n->node);
        if (n->data != 0)
        {
            d = &n->tdata;
            sumdata(d, &data[n->data - 1]);
            while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses &&
                     (p->symbol != 0) && (p->symbol == n->symbol))))
            {
                if (p->data != 0)
                    sumdata(d, &data[p->data - 1]);
                p = (profilenode *) __mp_successor(&p->node);
            }
            a = 0;
            for (i = 0; i < 4; i++)
                if (showcounts)
                    a += d->acount[i];
                else
                    a += d->atotal[i];
            __mp_treeinsert(&temptree, &n->tnode, a);
            sumdata(&m, d);
        }
    }
    for (t = __mp_maximum(temptree.root); t != NULL; t = __mp_predecessor(t))
    {
        n = (profilenode *) ((char *) t - offsetof(profilenode, tnode));
        d = &n->tdata;
        a = t->key;
        b = c = 0;
        for (i = 0; i < 4; i++)
        {
            if (showcounts)
            {
                b += d->dcount[i];
                c += d->atotal[i];
            }
            else
            {
                b += d->dtotal[i];
                c += d->acount[i];
            }
            d->dcount[i] = d->acount[i] - d->dcount[i];
            d->dtotal[i] = d->atotal[i] - d->dtotal[i];
        }
        b = a - b;
        if (showcounts)
        {
            e = ((double) a / (double) acount) * 100.0;
            if (acount != dcount)
                f = ((double) b / (double) (acount - dcount)) * 100.0;
            else
                f = 0.0;
            fprintf(stdout, "%6lu  %6.2f ", a, e);
            printdata(d->acount, acount);
            fprintf(stdout, "  %6lu  %6.2f ", b, f);
            printdata(d->dcount, acount - dcount);
            fprintf(stdout, "  %8lu  ", c);
        }
        else
        {
            e = ((double) a / (double) atotal) * 100.0;
            if (atotal != dtotal)
                f = ((double) b / (double) (atotal - dtotal)) * 100.0;
            else
                f = 0.0;
            fprintf(stdout, "%8lu  %6.2f ", a, e);
            printdata(d->atotal, atotal);
            fprintf(stdout, "  %8lu  %6.2f ", b, f);
            printdata(d->dtotal, atotal - dtotal);
            fprintf(stdout, "  %6lu  ", c);
        }
        printsymbol(stdout, n);
        fputc('\n', stdout);
        cleardata(d);
    }
    for (i = 0; i < 4; i++)
    {
        m.dcount[i] = m.acount[i] - m.dcount[i];
        m.dtotal[i] = m.atotal[i] - m.dtotal[i];
    }
    if (temptree.size != 0)
        fputc('\n', stdout);
    if (showcounts)
    {
        fprintf(stdout, "%6lu         ", acount);
        printdata(m.acount, acount);
        fprintf(stdout, "  %6lu         ", acount - dcount);
        printdata(m.dcount, acount - dcount);
        fprintf(stdout, "  %8lu  total\n", atotal);
    }
    else
    {
        fprintf(stdout, "%8lu         ", atotal);
        printdata(m.atotal, atotal);
        fprintf(stdout, "  %8lu         ", atotal - dtotal);
        printdata(m.dtotal, atotal - dtotal);
        fprintf(stdout, "  %6lu  total\n", acount);
    }
    __mp_newtree(&temptree);
}
Ejemplo n.º 5
0
int
main(int argc, char **argv)
{
    char b[256];
    char *f, *g;
    int c, e, h, r, v;

    g = NULL;
    e = h = v = 0;
    r = EXIT_SUCCESS;
    maxstack = 1;
    progname = __mp_basename(argv[0]);
    while ((c = __mp_getopt(argc, argv, __mp_shortopts(b, options_table),
             options_table)) != EOF)
        switch (c)
        {
          case OF_ADDRESSES:
            useaddresses = 1;
            break;
          case OF_CALLGRAPH:
            showgraph = 1;
            break;
          case OF_COUNTS:
            showcounts = 1;
            break;
          case OF_GRAPHFILE:
            g = __mp_optarg;
            break;
          case OF_HELP:
            h = 1;
            break;
          case OF_LEAKS:
            showleaks = 1;
            break;
          case OF_STACKDEPTH:
            if (!__mp_getnum(progname, __mp_optarg, (long *) &maxstack, 1))
                e = 1;
            break;
          case OF_VERSION:
            v = 1;
            break;
          default:
            e = 1;
            break;
        }
    argc -= __mp_optindex;
    argv += __mp_optindex;
    if (v == 1)
    {
        fprintf(stdout, "%s %s\n%s %s\n\n", progname, PROGVERSION,
                __mp_copyright, __mp_author);
        fputs("This is free software, and you are welcome to redistribute it "
              "under certain\n", stdout);
        fputs("conditions; see the GNU Lesser General Public License for "
              "details.\n\n", stdout);
        fputs("For the latest mpatrol release and documentation,\n", stdout);
        fprintf(stdout, "visit %s.\n\n", __mp_homepage);
    }
    if (argc > 1)
        e = 1;
    if ((e == 1) || (h == 1))
    {
        fprintf(stdout, "Usage: %s [options] [file]\n\n", progname);
        if (h == 0)
            fprintf(stdout, "Type `%s --help' for a complete list of "
                    "options.\n", progname);
        else
            __mp_showopts(options_table);
        if (e == 1)
            exit(EXIT_FAILURE);
        exit(EXIT_SUCCESS);
    }
    if (argc == 1)
        f = argv[0];
    else
        f = MP_PROFFILE;
    acount = dcount = 0;
    atotal = dtotal = 0;
    acounts = dcounts = NULL;
    atotals = dtotals = 0;
    binsize = 0;
    data = NULL;
    datasize = 0;
    nodes = NULL;
    nodesize = 0;
    addrs = NULL;
    symbols = NULL;
    sbound = mbound = lbound = 0;
    __mp_newtree(&proftree);
    __mp_newtree(&temptree);
    __mp_newlist(&edgelist);
    __mp_newgraph(&graph);
    if (strcmp(f, "-") == 0)
        proffile = stdin;
    else if ((proffile = fopen(f, "rb")) == NULL)
    {
        fprintf(stderr, "%s: Cannot open file `%s'\n", progname, f);
        exit(EXIT_FAILURE);
    }
    readfile();
    fclose(proffile);
    bintable();
    fputs("\n\n", stdout);
    directtable();
    fputs("\n\n", stdout);
    leaktable();
    /* The reason that the allocation call graph is not used for the direct
     * allocation and memory leak tables is that the code to build and display
     * the allocation call graph was added much later.  Rather than convert
     * these tables to use the new call graph, I decided to keep the code that
     * already worked and only use the call graph for any new tables.
     */
    buildgraph();
    if (showgraph)
    {
        fputs("\n\n", stdout);
        callgraph();
    }
    if (g != NULL)
    {
        if (strcmp(g, "stdout") == 0)
            graphfile = stdout;
        else if (strcmp(g, "stderr") == 0)
            graphfile = stderr;
        else if ((graphfile = fopen(g, "w")) == NULL)
        {
            fprintf(stderr, "%s: Cannot open file `%s'\n", progname, g);
            r = EXIT_FAILURE;
        }
        if (r == EXIT_SUCCESS)
        {
            fprintf(graphfile, "/* produced by %s %s from %s */\n\n", progname,
                    PROGVERSION, f);
            if (showleaks)
                fputs("digraph \"memory leak call graph\"\n{\n", graphfile);
            else
                fputs("digraph \"allocation call graph\"\n{\n", graphfile);
            writegraph(NULL, &graph.start);
            fputs("}\n", graphfile);
            if ((graphfile != stdout) && (graphfile != stderr))
                fclose(graphfile);
        }
    }
    deletegraph();
    if (acounts != NULL)
        free(acounts);
    if (dcounts != NULL)
        free(dcounts);
    if (data != NULL)
        free(data);
    if (nodes != NULL)
        free(nodes);
    if (addrs != NULL)
        free(addrs);
    if (symbols != NULL)
        free(symbols);
    return r;
}
Ejemplo n.º 6
0
static
void
leaktable(void)
{
    profiledata *d;
    profilenode *n, *p;
    treenode *t;
    size_t i;
    unsigned long a, b, j, k;
    double e, f, g;

    printchar(' ', 34);
    fputs("MEMORY LEAKS\n\n", stdout);
    printchar(' ', 28);
    fprintf(stdout, "(maximum stack depth: %lu)\n\n", maxstack);
    printchar(' ', 16);
    fputs("unfreed", stdout);
    printchar(' ', 22);
    fputs("allocated\n", stdout);
    printchar('-', 40);
    fputs("  ", stdout);
    printchar('-', 16);
    if (showcounts)
        fputs("\n     %   count       %     bytes       %   "
              "count     bytes  function\n\n", stdout);
    else
        fputs("\n     %     bytes       %   count       %     "
              "bytes   count  function\n\n", stdout);
    for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = p)
    {
        p = (profilenode *) __mp_successor(&n->node);
        if ((n->data != 0) && !n->flags)
        {
            d = &n->tdata;
            sumdata(d, &data[n->data - 1]);
            while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses &&
                     (p->symbol != 0) && (p->symbol == n->symbol))))
            {
                if ((p->data != 0) && !p->flags && comparestack(n, p, 0))
                {
                    sumdata(d, &data[p->data - 1]);
                    p->flags = 1;
                }
                p = (profilenode *) __mp_successor(&p->node);
            }
            p = (profilenode *) __mp_successor(&n->node);
            a = 0;
            for (i = 0; i < 4; i++)
                if (showcounts)
                    a += d->acount[i] - d->dcount[i];
                else
                    a += d->atotal[i] - d->dtotal[i];
            if (a > 0)
                __mp_treeinsert(&temptree, &n->tnode, a);
        }
    }
    for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL;
         n = (profilenode *) __mp_successor(&n->node))
        n->flags = 0;
    for (t = __mp_maximum(temptree.root); t != NULL; t = __mp_predecessor(t))
    {
        n = (profilenode *) ((char *) t - offsetof(profilenode, tnode));
        d = &n->tdata;
        a = t->key;
        b = j = k = 0;
        for (i = 0; i < 4; i++)
            if (showcounts)
            {
                b += d->dtotal[i];
                j += d->acount[i];
                k += d->atotal[i];
            }
            else
            {
                b += d->dcount[i];
                j += d->atotal[i];
                k += d->acount[i];
            }
        b = k - b;
        e = ((double) a / (double) j) * 100.0;
        f = ((double) b / (double) k) * 100.0;
        if (showcounts)
        {
            g = ((double) a / (double) (acount - dcount)) * 100.0;
            fprintf(stdout, "%6.2f  %6lu  %6.2f  %8lu  %6.2f  %6lu  %8lu  ",
                    g, a, e, b, f, j, k);
        }
        else
        {
            g = ((double) a / (double) (atotal - dtotal)) * 100.0;
            fprintf(stdout, "%6.2f  %8lu  %6.2f  %6lu  %6.2f  %8lu  %6lu  ",
                    g, a, e, b, f, j, k);
        }
        printsymbol(stdout, n);
        fputc('\n', stdout);
        p = n;
        for (i = 1; (maxstack == 0) || (i < maxstack); i++)
        {
            if (p->parent == 0)
                break;
            p = &nodes[p->parent - 1];
            printchar(' ', 60);
            printsymbol(stdout, p);
            fputc('\n', stdout);
        }
        cleardata(d);
    }
    if (acount != 0)
        e = ((double) (acount - dcount) / (double) acount) * 100.0;
    else
        e = 0.0;
    if (atotal != 0)
        f = ((double) (atotal - dtotal) / (double) atotal) * 100.0;
    else
        f = 0.0;
    if (temptree.size != 0)
        fputc('\n', stdout);
    if (showcounts)
        fprintf(stdout, "        %6lu  %6.2f  %8lu  %6.2f  %6lu  %8lu  total\n",
                acount - dcount, e, atotal - dtotal, f, acount, atotal);
    else
        fprintf(stdout, "        %8lu  %6.2f  %6lu  %6.2f  %8lu  %6lu  total\n",
                atotal - dtotal, f, acount - dcount, e, atotal, acount);
    __mp_newtree(&temptree);
}
Ejemplo n.º 7
0
int
main(int argc, char **argv)
{
    struct { char x; void *y; } z;
    char b[256];
    char *f, *s, *t;
#if MP_GUI_SUPPORT
    XGCValues g;
#endif /* MP_GUI_SUPPORT */
    long n;
    int c, e, h, v;

#if MP_GUI_SUPPORT
    appwidget = XtVaAppInitialize(&appcontext, "MPTrace", options,
                                  XtNumber(options), &argc, argv, NULL, NULL);
    XtVaGetApplicationResources(appwidget, NULL, resources, XtNumber(resources),
                                NULL);
#endif /* MP_GUI_SUPPORT */
    s = t = NULL;
    e = h = v = 0;
    progname = __mp_basename(argv[0]);
    while ((c = __mp_getopt(argc, argv, __mp_shortopts(b, options_table),
             options_table)) != EOF)
        switch (c)
        {
          case OF_GUI:
#if MP_GUI_SUPPORT
            usegui = 1;
#endif /* MP_GUI_SUPPORT */
            break;
          case OF_HATFFILE:
            t = __mp_optarg;
            break;
          case OF_HELP:
            h = 1;
            break;
          case OF_SIMFILE:
            s = __mp_optarg;
            break;
          case OF_SOURCE:
            displaysource = 1;
            break;
          case OF_VERBOSE:
            verbose = 1;
            break;
          case OF_VERSION:
            v = 1;
            break;
          default:
            e = 1;
            break;
        }
    argc -= __mp_optindex;
    argv += __mp_optindex;
    if (v == 1)
    {
        fprintf(stdout, "%s %s\n%s %s\n\n", progname, PROGVERSION,
                __mp_copyright, __mp_author);
        fputs("This is free software, and you are welcome to redistribute it "
              "under certain\n", stdout);
        fputs("conditions; see the GNU Lesser General Public License for "
              "details.\n\n", stdout);
        fputs("For the latest mpatrol release and documentation,\n", stdout);
        fprintf(stdout, "visit %s.\n\n", __mp_homepage);
    }
    if (argc > 1)
        e = 1;
    if ((e == 1) || (h == 1))
    {
        fprintf(stdout, "Usage: %s [options] [file]\n\n", progname);
        if (h == 0)
            fprintf(stdout, "Type `%s --help' for a complete list of "
                    "options.\n", progname);
        else
            __mp_showopts(options_table);
        if (e == 1)
            exit(EXIT_FAILURE);
        exit(EXIT_SUCCESS);
    }
    if (argc == 1)
        f = argv[0];
    else
        f = MP_TRACEFILE;
    __mp_newtree(&alloctree);
    if (strcmp(f, "-") == 0)
        tracefile = stdin;
    else if ((tracefile = fopen(f, "rb")) == NULL)
    {
        fprintf(stderr, "%s: Cannot open file `%s'\n", progname, f);
        exit(EXIT_FAILURE);
    }
    currentevent = 0;
    bufferpos = buffer;
    bufferlen = 0;
    n = (char *) &z.y - &z.x;
    __mp_newslots(&table, sizeof(void *), __mp_poweroftwo(n));
    __mp_initslots(&table, tableslots, sizeof(tableslots));
    maxslots = 1;
    if (s != NULL)
    {
        if (strcmp(s, "stdout") == 0)
            simfile = stdout;
        else if (strcmp(s, "stderr") == 0)
            simfile = stderr;
        else if ((simfile = fopen(s, "w")) == NULL)
        {
            fprintf(stderr, "%s: Cannot open file `%s'\n", progname, s);
            exit(EXIT_FAILURE);
        }
        fprintf(simfile, "/* produced by %s %s from %s */\n\n\n", progname,
                PROGVERSION, f);
        fputs("#include <stdio.h>\n", simfile);
        fputs("#include <stdlib.h>\n\n\n", simfile);
        fputs("typedef struct event\n{\n", simfile);
        fputs("    unsigned long index;\n", simfile);
        fputs("    unsigned long size;\n", simfile);
        fputs("    char resize;\n", simfile);
        fputs("}\nevent;\n\n\n", simfile);
        fputs("static event events[] =\n{\n", simfile);
    }
    if (t != NULL)
    {
        if (strcmp(t, "stdout") == 0)
            hatffile = stdout;
        else if (strcmp(t, "stderr") == 0)
            hatffile = stderr;
        else if ((hatffile = fopen(t, "w")) == NULL)
        {
            fprintf(stderr, "%s: Cannot open file `%s'\n", progname, t);
            exit(EXIT_FAILURE);
        }
        fprintf(hatffile, "## Tracename: %s\n", t);
        fputs("## Author: Unknown\n", hatffile);
        fputs("## Date: Unknown\n", hatffile);
        fputs("## DTDURL: hatf.dtd\n", hatffile);
        fprintf(hatffile, "## Description: Converted to HATF by %s %s.\n\n",
                progname, PROGVERSION);
    }
    readfile();
#if MP_GUI_SUPPORT
    if (usegui)
    {
        appdisplay = XtDisplay(appwidget);
        appscreen = XtScreen(appwidget);
        addrscale = (((addrspace * 1048576) - 1) / (width * height)) + 1;
        /* Set up the main application window and scrollable drawing area.
         * Also set up a pixmap to backup the drawing area.
         */
        mainwidget = XtVaCreateManagedWidget("main",
                                             xmScrolledWindowWidgetClass,
                                             appwidget, XmNwidth, vwidth,
                                             XmNheight, vheight,
                                             XmNscrollingPolicy, XmAUTOMATIC,
                                             XmNscrollBarDisplayPolicy,
                                             XmAS_NEEDED, NULL);
        drawwidget = XtVaCreateManagedWidget("draw", xmDrawingAreaWidgetClass,
                                             mainwidget, XmNwidth, width,
                                             XmNheight, height, NULL);
        pixmap = XCreatePixmap(appdisplay, RootWindowOfScreen(appscreen), width,
                               height, DefaultDepthOfScreen(appscreen));
        /* Set up the graphics contexts that are used for drawing in different
         * colours.
         */
        g.foreground = uncol;
        ungc = XCreateGC(appdisplay, RootWindowOfScreen(appscreen),
                         GCForeground, &g);
        g.foreground = incol;
        ingc = XCreateGC(appdisplay, RootWindowOfScreen(appscreen),
                         GCForeground, &g);
        g.foreground = frcol;
        frgc = XCreateGC(appdisplay, RootWindowOfScreen(appscreen),
                         GCForeground, &g);
        g.foreground = alcol;
        algc = XCreateGC(appdisplay, RootWindowOfScreen(appscreen),
                         GCForeground, &g);
        /* Add a callback procedure to handle the refreshing of the drawing
         * area and also a work procedure to read events from the tracing
         * output file.  Then initialise the drawing area and enter the main X
         * application loop.
         */
        XtAddCallback(drawwidget, XmNexposeCallback,
                      (XtCallbackProc) redrawmemory, NULL);
        XtAppAddWorkProc(appcontext, (XtWorkProc) readevent, NULL);
        XtRealizeWidget(appwidget);
        XFillRectangle(appdisplay, XtWindow(drawwidget), ungc, 0, 0, width - 1,
                       height - 1);
        XFillRectangle(appdisplay, pixmap, ungc, 0, 0, width - 1, height - 1);
        XtAppMainLoop(appcontext);
    }
#endif /* MP_GUI_SUPPORT */
    return EXIT_SUCCESS;
}