Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Public Attributes
leaky Struct Reference

#include <leaky.h>

Collaboration diagram for leaky:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 leaky ()
 ~leaky ()
void initialize (int argc, char **argv)
void open ()
void usageError ()
void LoadMap ()
void analyze ()
void dumpLog ()
void dumpEntryToLog (malloc_log_entry *lep)
void insertAddress (u_long address, malloc_log_entry *lep)
void removeAddress (u_long address, malloc_log_entry *lep)
void displayStackTrace (FILE *out, malloc_log_entry *lep)
void ReadSymbols (const char *fileName, u_long aBaseAddress)
void ReadSharedLibrarySymbols ()
void setupSymbols (const char *fileName)
SymbolfindSymbol (u_long address)
bool excluded (malloc_log_entry *lep)
bool included (malloc_log_entry *lep)
void buildLeakGraph ()
SymbolfindLeakGraphRoot (Symbol *aStart, Symbol *aEnd)
void dumpLeakGraph ()
void dumpLeakTree (TreeNode *aNode, int aIndent)
bool ShowThisEntry (malloc_log_entry *lep)
bool IsRefcnt (malloc_log_entry *lep) const

Static Public Member Functions

static void indentBy (int aCount)

Public Attributes

char * applicationName
char * logFile
char * progFile
int dumpLeaks
int dumpGraph
int dumpHTML
int quiet
int dumpEntireLog
int showAddress
bool dumpRefcnts
u_int stackDepth
int mappedLogFile
malloc_log_entryfirstLogEntry
malloc_log_entrylastLogEntry
u_int buckets
MallocDictdict
MallocDictrefcntDict
u_long mallocs
u_long reallocs
u_long frees
u_long totalMalloced
u_long errors
u_long totalLeaked
int sfd
SymbolexternalSymbols
u_int usefulSymbols
u_int numExternalSymbols
StrSet exclusions
u_long lowestSymbolAddr
u_long highestSymbolAddr
LoadMapEntryloadMap
TreeNoderootList
StrSet roots
StrSet includes

Detailed Description

Definition at line 102 of file leaky.h.


Constructor & Destructor Documentation

Definition at line 115 of file leaky.cpp.

{
  delete dict;
}

Member Function Documentation

Definition at line 514 of file leaky.cpp.

{
  malloc_log_entry* lep = firstLogEntry;
  while (lep < lastLogEntry) {
    switch (lep->type) {
      case malloc_log_malloc:
      case malloc_log_new:
       mallocs++;
       if (lep->address) {
         totalMalloced += lep->size;
         insertAddress((u_long) lep->address, lep);
       }
       break;

      case malloc_log_realloc:
       if (lep->oldaddress) {
         removeAddress((u_long) lep->oldaddress, lep);
       }
       if (lep->address) {
         insertAddress((u_long) lep->address, lep);
       }
       reallocs++;
       break;

      case malloc_log_free:
      case malloc_log_delete:
       if (lep->address) {
         removeAddress((u_long) lep->address, lep);
       }
       frees++;
       break;
      case malloc_log_addref:
       if (dumpRefcnts) {
         if (lep->size == 0) {
           // Initial addref
           u_long addr = (u_long) lep->address;
           malloc_log_entry** lepp = refcntDict->find(addr);
           if (!lepp) {
             refcntDict->add(addr, lep);
           }
         }
       }
       break;
      case malloc_log_release:
       if (dumpRefcnts) {
         if (lep->oldaddress == 0) {
           // Final release
           u_long addr = (u_long) lep->address;
           malloc_log_entry** lepp = refcntDict->find(addr);
           if (lepp) {
             refcntDict->remove(addr);
           }
         }
       }
       break;
    }
    lep = (malloc_log_entry*) &lep->pcs[lep->numpcs];
  }

  dict->rewind();
  while (NULL != (lep = dict->next())) {
    totalLeaked += lep->size;
  }

  if (!quiet) {
    printf("# of mallocs = %ld\n", mallocs);
    printf("# of reallocs = %ld\n", reallocs);
    printf("# of frees = %ld\n", frees);
    printf("# of errors = %ld\n", errors);
    printf("Total bytes allocated = %ld\n", totalMalloced);
    printf("Total bytes leaked = %ld\n", totalLeaked);
    printf("Average bytes per malloc = %g\n",
          float(totalMalloced)/mallocs);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 590 of file leaky.cpp.

{
  // For each leak
  malloc_log_entry* lep;
  dict->rewind();
  while (NULL != (lep = dict->next())) {
    if (ShowThisEntry(lep)) {
      char** basepcp = &lep->pcs[0];
      char** pcp = &lep->pcs[lep->numpcs - 1];

      // Find root for this allocation
      Symbol* sym = findSymbol((u_long) *pcp);
      TreeNode* node = sym->root;
      if (!node) {
       sym->root = node = new TreeNode(sym);

       // Add root to list of roots
       if (roots.IsEmpty()) {
         node->nextRoot = rootList;
         rootList = node;
       }
      }
      pcp--;

      // Build tree underneath the root
      for (; pcp >= basepcp; pcp--) {
       // Share nodes in the tree until there is a divergence
       sym = findSymbol((u_long) *pcp);
       if (!sym) {
         break;
       }
       TreeNode* nextNode = node->GetDirectDescendant(sym);
       if (!nextNode) {
         // Make a new node at the point of divergence
         nextNode = node->AddDescendant(sym);
       }

       // See if the symbol is to be a user specified root. If it is,
       // and we haven't already stuck it on the root-list do so now.
       if (!sym->root && !roots.IsEmpty() && roots.contains(sym->name)) {
         sym->root = nextNode;
         nextNode->nextRoot = rootList;
         rootList = nextNode;
       }

       if (pcp == basepcp) {
         nextNode->bytesLeaked += lep->size;
       }
       else {
         node->descendantBytesLeaked += lep->size;
       }

       node = nextNode;
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 389 of file leaky.cpp.

{
  char** pcp = &lep->pcs[0];
  u_int n = (lep->numpcs < stackDepth) ? lep->numpcs : stackDepth;
  for (u_int i = 0; i < n; i++, pcp++) {
    u_long addr = (u_long) *pcp;
    Symbol* sp = findSymbol(addr);
    if (sp) {
      fputs(sp->name, out);
      if (showAddress) {
       fprintf(out, "[%p]", (char*)addr);
      }
    }
    else {
      fprintf(out, "<%p>", (char*)addr);
    }
    fputc(' ', out);
  }
  fputc('\n', out);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 420 of file leaky.cpp.

{
  printf("%-10s %08lx %5ld ",
        typeFromLog[lep->type],
        lep->address, lep->size);
  if (IsRefcnt(lep)) {
    printf("%08ld", lep->oldaddress);
  }
  else {
    printf("%08lx", lep->oldaddress);
  }
  printf(" --> ");
  displayStackTrace(stdout, lep);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 659 of file leaky.cpp.

{ 
  if (dumpHTML) {
    printf("<html><head><title>Leaky Graph</title>\n");
    printf("<style src=\"resource:/res/leaky/leaky.css\"></style>\n");
    printf("<script src=\"resource:/res/leaky/leaky.js\"></script>\n");
    printf("</head><body><div class=\"key\">\n");
    printf("Key:<br>\n");
    printf("<span class=b>Bytes directly leaked</span><br>\n");
    printf("<span class=d>Bytes leaked by descendants</span></div>\n");
  }

#if 0
  Symbol* base = externalSymbols;
  Symbol* end = externalSymbols + usefulSymbols;
  while (base < end) {
    Symbol* sym = findLeakGraphRoot(base, end);
    if (!sym) break;
    dumpLeakTree(sym->root, 0);
    base = sym + 1;
  }
#else
  TreeNode* root = rootList;
  while (root) {
    dumpLeakTree(root, 0);
    root = root->nextRoot;
  }
#endif
  if (dumpHTML) {
    printf("</body></html>\n");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void leaky::dumpLeakTree ( TreeNode aNode,
int  aIndent 
)

Definition at line 692 of file leaky.cpp.

{
  Symbol* sym = aNode->symbol;
  if (dumpHTML) {
    printf("<div class=\"n\">\n");
    if (aNode->HasDescendants()) {
      printf("<img onmouseout=\"O(event);\" onmouseover=\"I(event);\" ");
      printf("onclick=\"C(event);\" src=\"resource:/res/leaky/%s.gif\">",
            aIndent > 1 ? "close" : "open");
    }
    printf("<span class=s>%s</span><span class=b>%ld</span>",
          sym->name,
          aNode->bytesLeaked);
    printf("<span class=d>%ld</span>\n",
          aNode->descendantBytesLeaked);
  }
  else {
    indentBy(aIndent);
    printf("%s bytesLeaked=%ld (%ld from kids)\n", 
          sym->name,
          aNode->bytesLeaked,
          aNode->descendantBytesLeaked);
  }

  TreeNode* node = aNode->descendants;
  int kidNum = 0;
  while (node) {
    sym = node->symbol;
    dumpLeakTree(node, aIndent + 1);
    kidNum++;
    node = node->nextSibling;
  }

  if (dumpHTML) {
    printf("</div>");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 443 of file leaky.cpp.

{
  if (dumpRefcnts) {
      malloc_log_entry* lep;
      refcntDict->rewind();
      while (NULL != (lep = refcntDict->next())) {
       if (ShowThisEntry(lep)) {
         // Now we get slow...
         u_long addr = lep->address;
         malloc_log_entry* lep2 = firstLogEntry;
         while (lep2 < lastLogEntry) {
           if (lep2->address == addr) {
             dumpEntryToLog(lep2);
           }
           lep2 = (malloc_log_entry*) &lep2->pcs[lep2->numpcs];
         }
       }
      }
  }
  else {
    if (dumpEntireLog) {
      malloc_log_entry* lep = firstLogEntry;
      while (lep < lastLogEntry) {
       if (ShowThisEntry(lep)) {
         dumpEntryToLog(lep);
       }
       lep = (malloc_log_entry*) &lep->pcs[lep->numpcs];
      }
    } else {
      malloc_log_entry* lep;
      dict->rewind();
      while (NULL != (lep = dict->next())) {
       if (ShowThisEntry(lep)) {
         dumpEntryToLog(lep);
       }
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 353 of file leaky.cpp.

{
  if (exclusions.IsEmpty()) {
    return false;
  }

  char** pcp = &lep->pcs[0];
  u_int n = lep->numpcs;
  for (u_int i = 0; i < n; i++, pcp++) {
    Symbol* sp = findSymbol((u_long) *pcp);
    if (sp && exclusions.contains(sp->name)) {
      return true;
    }
  }
  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Symbol * leaky::findLeakGraphRoot ( Symbol aStart,
Symbol aEnd 
)

Definition at line 648 of file leaky.cpp.

{
  while (aStart < aEnd) {
    if (aStart->root) {
      return aStart;
    }
    aStart++;
  }
  return NULL;
}

Here is the caller graph for this function:

Definition at line 324 of file leaky.cpp.

{
  u_int base = 0;
  u_int limit = usefulSymbols - 1;
  Symbol* end = &externalSymbols[limit];
  while (base <= limit) {
    u_int midPoint = (base + limit)>>1;
    Symbol* sp = &externalSymbols[midPoint];
    if (addr < sp->address) {
      if (midPoint == 0) {
       return NULL;
      }
      limit = midPoint - 1;
    } else {
      if (sp+1 < end) {
       if (addr < (sp+1)->address) {
         return sp;
       }
      } else {
       return sp;
      }
      base = midPoint + 1;
    }
  }
  return NULL;
}

Here is the caller graph for this function:

Definition at line 370 of file leaky.cpp.

{
  if (includes.IsEmpty()) {
    return true;
  }

  char** pcp = &lep->pcs[0];
  u_int n = lep->numpcs;
  for (u_int i = 0; i < n; i++, pcp++) {
    Symbol* sp = findSymbol((u_long) *pcp);
    if (sp && includes.contains(sp->name)) {
      return true;
    }
  }
  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void leaky::indentBy ( int  aCount) [inline, static]

Definition at line 189 of file leaky.h.

                                   {
    while (--aCount >= 0) fputs("  ", stdout);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void leaky::initialize ( int  argc,
char **  argv 
)

Definition at line 128 of file leaky.cpp.

{
  applicationName = argv[0];
  applicationName = strrchr(applicationName, '/');
  if (!applicationName) {
    applicationName = argv[0];
  } else {
    applicationName++;
  }

  int arg;
  int errflg = 0;
  while ((arg = getopt(argc, argv, "adEe:gh:i:r:Rs:tqx")) != -1) {
    switch (arg) {
      case '?':
       errflg++;
       break;
      case 'a':
       dumpEntireLog = TRUE;
       break;
      case 'A':
       showAddress = TRUE;
       break;
      case 'd':
       dumpLeaks = TRUE;
       if (dumpGraph) errflg++;
       break;
      case 'R':
       dumpRefcnts = true;
       break;
      case 'e':
       exclusions.add(optarg);
       break;
      case 'g':
       dumpGraph = TRUE;
       if (dumpLeaks) errflg++;
       break;
      case 'r':
       roots.add(optarg);
       if (!includes.IsEmpty()) {
         errflg++;
       }
       break;
      case 'i':
       includes.add(optarg);
       if (!roots.IsEmpty()) {
         errflg++;
       }
       break;
      case 'h':
       buckets = atoi(optarg);
       if ((buckets < 0) || (buckets > MaxBuckets)) {
         buckets = MaxBuckets;
         fprintf(stderr, "%s: buckets is invalid, using %d\n",
                (char*) applicationName,
                buckets);
       }
       break;
      case 's':
       stackDepth = atoi(optarg);
       if (stackDepth < 2) {
         stackDepth = 2;
       }
       break;
      case 'x':
       dumpHTML = TRUE;
       break;
      case 'q':
       quiet = TRUE;
       break;
    }
  }
  if (errflg || ((argc - optind) < 2)) {
    usageError();
  }
  progFile = argv[optind++];
  logFile = argv[optind];

  dict = new MallocDict(buckets);
  if (dumpRefcnts) {
    refcntDict = new MallocDict(buckets);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 485 of file leaky.cpp.

{
  malloc_log_entry** lepp = dict->find(address);
  if (lepp) {
    assert(*lepp);
    if (!quiet) {
      printf("Address %lx allocated twice\n", address);
      displayStackTrace(stdout, lep);
    }
    errors++;
  } else {
    dict->add(address, lep);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool leaky::IsRefcnt ( malloc_log_entry lep) const [inline]

Definition at line 184 of file leaky.h.

                                             {
    return (lep->type == malloc_log_addref) ||
      (lep->type == malloc_log_release);
  }

Here is the caller graph for this function:

Definition at line 228 of file leaky.cpp.

{
  malloc_map_entry mme;
  char name[1000];

  int fd = ::open("malloc-map", O_RDONLY);
  if (fd < 0) {
    perror("open: malloc-map");
    exit(-1);
  }
  for (;;) {
    int nb = read(fd, &mme, sizeof(mme));
    if (nb != sizeof(mme)) break;
    nb = read(fd, name, mme.nameLen);
    if (nb != (int)mme.nameLen) break;
    name[mme.nameLen] = 0;
    if (!quiet) {
      printf("%s @ %lx\n", name, mme.address);
    }

    LoadMapEntry* lme = new LoadMapEntry;
    lme->address = mme.address;
    lme->name = strdup(name);
    lme->next = loadMap;
    loadMap = lme;
  }
  close(fd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 257 of file leaky.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 295 of file leaky.cpp.

{
  LoadMapEntry* lme = loadMap;
  while (NULL != lme) {
    ReadSymbols(lme->name, lme->address);
    lme = lme->next;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void leaky::ReadSymbols ( const char *  fileName,
u_long  aBaseAddress 
)

Here is the caller graph for this function:

Definition at line 500 of file leaky.cpp.

{
  malloc_log_entry** lepp = dict->find(address);
  if (!lepp) {
    if (!quiet) {
      printf("Free of unallocated %lx\n", address);
      displayStackTrace(stdout, lep);
    }
    errors++;
  } else {
    dict->remove(address);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void leaky::setupSymbols ( const char *  fileName)

Definition at line 304 of file leaky.cpp.

{
  // Read in symbols from the program
  ReadSymbols(fileName, 0);

  // Read in symbols from the .so's
  ReadSharedLibrarySymbols();

  if (!quiet) {
    printf("A total of %d symbols were loaded\n", usefulSymbols);
  }

  // Now sort them
  qsort(externalSymbols, usefulSymbols, sizeof(Symbol), symbolOrder);
  lowestSymbolAddr = externalSymbols[0].address;
  highestSymbolAddr = externalSymbols[usefulSymbols-1].address;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 435 of file leaky.cpp.

{
  if ((!dumpRefcnts || IsRefcnt(lep)) && !excluded(lep) && included(lep)) {
    return true;
  }
  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 120 of file leaky.cpp.

{
  fprintf(stderr,
         "Usage: %s [-aAEdfgqxR] [-e name] [-s depth] [-h hash-buckets] [-r root|-i symbol] prog log\n",
         (char*) applicationName);
  exit(-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 109 of file leaky.h.

Definition at line 125 of file leaky.h.

Definition at line 126 of file leaky.h.

Definition at line 117 of file leaky.h.

Definition at line 114 of file leaky.h.

Definition at line 115 of file leaky.h.

Definition at line 113 of file leaky.h.

Definition at line 119 of file leaky.h.

Definition at line 133 of file leaky.h.

Definition at line 140 of file leaky.h.

Definition at line 137 of file leaky.h.

Definition at line 123 of file leaky.h.

Definition at line 131 of file leaky.h.

Definition at line 142 of file leaky.h.

Definition at line 149 of file leaky.h.

Definition at line 124 of file leaky.h.

Definition at line 144 of file leaky.h.

Definition at line 110 of file leaky.h.

Definition at line 141 of file leaky.h.

Definition at line 129 of file leaky.h.

Definition at line 122 of file leaky.h.

Definition at line 139 of file leaky.h.

Definition at line 111 of file leaky.h.

Definition at line 116 of file leaky.h.

Definition at line 130 of file leaky.h.

Definition at line 127 of file leaky.h.

Definition at line 146 of file leaky.h.

Definition at line 148 of file leaky.h.

Definition at line 136 of file leaky.h.

Definition at line 118 of file leaky.h.

Definition at line 120 of file leaky.h.

Definition at line 134 of file leaky.h.

Definition at line 132 of file leaky.h.

Definition at line 138 of file leaky.h.


The documentation for this struct was generated from the following files: