void leaky::analyze(int thread) { int *countArray = new int[usefulSymbols]; int *flagArray = new int[usefulSymbols]; //Zero our function call counter memset(countArray, 0, sizeof(countArray[0])*usefulSymbols); // reset hit counts for(int i=0; i<usefulSymbols; i++) { externalSymbols[i]->timerHit = 0; externalSymbols[i]->regClear(); } // The flag array is used to prevent counting symbols multiple times // if functions are called recursively. In order to keep from having // to zero it on each pass through the loop, we mark it with the value // of stacks on each trip through the loop. This means we can determine // if we have seen this symbol for this stack trace w/o having to reset // from the prior stacktrace. memset(flagArray, -1, sizeof(flagArray[0])*usefulSymbols); if (cleo) fprintf(outputfd,"m-Start\n"); // This loop walks through all the call stacks we recorded // --last, --start and --end can restrict it, as can excludes/includes stacks = 0; for(malloc_log_entry* lep=firstLogEntry; lep < lastLogEntry; lep = reinterpret_cast<malloc_log_entry*>(&lep->pcs[lep->numpcs])) { if ((thread != 0 && lep->thread != thread) || excluded(lep) || !included(lep)) { continue; } ++stacks; // How many stack frames did we collect u_int n = (lep->numpcs < stackDepth) ? lep->numpcs : stackDepth; char** pcp = &lep->pcs[n-1]; int idx=-1, parrentIdx=-1; // Init idx incase n==0 if (cleo) { // This loop walks through every symbol in the call stack. By walking it // backwards we know who called the function when we get there. char type = 's'; for (int i=n-1; i>=0; --i, --pcp) { idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if(idx>=0) { // Skip over bogus __restore_rt frames that realtime profiling // can introduce. if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) { --pcp; --i; idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if (idx < 0) { continue; } } Symbol **sp=&externalSymbols[idx]; char *symname = htmlify((*sp)->name); fprintf(outputfd,"%c-%s\n",type,symname); delete [] symname; } // else can't find symbol - ignore type = 'c'; } } else { // This loop walks through every symbol in the call stack. By walking it // backwards we know who called the function when we get there. for (int i=n-1; i>=0; --i, --pcp) { idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if(idx>=0) { // Skip over bogus __restore_rt frames that realtime profiling // can introduce. if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) { --pcp; --i; idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if (idx < 0) { continue; } } // If we have not seen this symbol before count it and mark it as seen if(flagArray[idx]!=stacks && ((flagArray[idx]=stacks) || true)) { ++countArray[idx]; } // We know who we are and we know who our parrent is. Count this if(parrentIdx>=0) { externalSymbols[parrentIdx]->regChild(idx); externalSymbols[idx]->regParrent(parrentIdx); } // inside if() so an unknown in the middle of a stack won't break // the link! parrentIdx=idx; } } // idx should be the function that we were in when we received the signal. if(idx>=0) { ++externalSymbols[idx]->timerHit; } } } if (!cleo) generateReportHTML(outputfd, countArray, stacks, thread); }
void leaky::analyze() { int *countArray = new int[usefulSymbols]; int *flagArray = new int[usefulSymbols]; //Zero our function call counter memset(countArray, 0, sizeof(countArray[0])*usefulSymbols); // The flag array is used to prevent counting symbols multiple times // if functions are called recursively. In order to keep from having // to zero it on each pass through the loop, we mark it with the value // of stacks on each trip through the loop. This means we can determine // if we have seen this symbol for this stack trace w/o having to reset // from the prior stacktrace. memset(flagArray, -1, sizeof(flagArray[0])*usefulSymbols); // This loop walks through all the call stacks we recorded stacks = 0; for(malloc_log_entry* lep=firstLogEntry; lep < lastLogEntry; lep = reinterpret_cast<malloc_log_entry*>(&lep->pcs[lep->numpcs])) { if (excluded(lep) || !included(lep)) continue; ++stacks; // How many stack frames did we collect // This loop walks through every symbol in the call stack. By walking it // backwards we know who called the function when we get there. u_int n = (lep->numpcs < stackDepth) ? lep->numpcs : stackDepth; char** pcp = &lep->pcs[n-1]; int idx=-1, parrentIdx=-1; // Init idx incase n==0 for(int i=n-1; i>=0; --i, --pcp, parrentIdx=idx) { idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if(idx>=0) { // Skip over bogus __restore_rt frames that realtime profiling // can introduce. if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { --pcp; --i; idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); if (idx < 0) { continue; } } // If we have not seen this symbol before count it and mark it as seen if(flagArray[idx]!=stacks && ((flagArray[idx]=stacks) || true)) { ++countArray[idx]; } // We know who we are and we know who our parrent is. Count this if(parrentIdx>=0) { externalSymbols[parrentIdx].regChild(idx); externalSymbols[idx].regParrent(parrentIdx); } } } // idx should be the function that we were in when we recieved the signal. if(idx>=0) { ++externalSymbols[idx].timerHit; } } generateReportHTML(stdout, countArray, stacks); }