Bug 863429: Fix jprof on debug builds, remove evilness NPOTB DONTBUILD rs=dbaron

This commit is contained in:
Randell Jesup 2013-04-19 09:54:16 -04:00
parent 6768e92c6a
commit 7852e2c3e4
6 changed files with 142 additions and 105 deletions

View File

@ -100,31 +100,49 @@ static bfd *find_debug_file(bfd *lib, const char *aFileName)
return debugFile;
}
#define NEXT_SYMBOL \
sp++; \
if (sp >= lastSymbol) { \
long n = numExternalSymbols + 10000; \
externalSymbols = (Symbol*) \
realloc(externalSymbols, (size_t) (sizeof(Symbol) * n)); \
lastSymbol = externalSymbols + n; \
sp = externalSymbols + numExternalSymbols; \
numExternalSymbols = n; \
// Use an indirect array to avoid copying tons of objects
Symbol ** leaky::ExtendSymbols(int num)
{
long n = numExternalSymbols + num;
externalSymbols = (Symbol**)
realloc(externalSymbols,
(size_t) (sizeof(externalSymbols[0]) * n));
Symbol *new_array = new Symbol[n];
for (int i = 0; i < num; i++) {
externalSymbols[i + numExternalSymbols] = &new_array[i];
}
lastSymbol = externalSymbols + n;
Symbol **sp = externalSymbols + numExternalSymbols;
numExternalSymbols = n;
return sp;
}
#define NEXT_SYMBOL do { sp++; \
if (sp >= lastSymbol) { \
sp = ExtendSymbols(16384); \
} \
} while (0)
void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
{
int initialSymbols = usefulSymbols;
if (NULL == externalSymbols) {
externalSymbols = (Symbol*) malloc(sizeof(Symbol) * 10000);
externalSymbols = (Symbol**) calloc(sizeof(Symbol*),10000);
Symbol *new_array = new Symbol[10000];
for (int i = 0; i < 10000; i++) {
externalSymbols[i] = &new_array[i];
}
numExternalSymbols = 10000;
}
Symbol* sp = externalSymbols + usefulSymbols;
Symbol* lastSymbol = externalSymbols + numExternalSymbols;
Symbol** sp = externalSymbols + usefulSymbols;
lastSymbol = externalSymbols + numExternalSymbols;
// Create a dummy symbol for the library so, if it doesn't have any
// symbols, we show it by library.
sp->Init(aFileName, aBaseAddress);
NEXT_SYMBOL
(*sp)->Init(aFileName, aBaseAddress);
NEXT_SYMBOL;
bfd_boolean kDynamic = (bfd_boolean) false;
@ -184,12 +202,12 @@ void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
// if ((syminfo.type == 'T') || (syminfo.type == 't')) {
const char* nm = bfd_asymbol_name(sym);
if (nm && nm[0]) {
char* dnm = NULL;
if (strncmp("__thunk", nm, 7)) {
dnm = cplus_demangle(nm, 1);
}
sp->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress);
NEXT_SYMBOL
char* dnm = NULL;
if (strncmp("__thunk", nm, 7)) {
dnm = cplus_demangle(nm, 1);
}
(*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress);
NEXT_SYMBOL;
}
// }
}
@ -199,7 +217,7 @@ void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
int interesting = sp - externalSymbols;
if (!quiet) {
printf("%s provided %d symbols\n", aFileName,
interesting - initialSymbols);
interesting - initialSymbols);
}
usefulSymbols = interesting;
}

View File

@ -4,7 +4,7 @@
#include "intcnt.h"
IntCount::IntCount() : numInts(0), iPair(0) { }
IntCount::IntCount() : numInts(0), iPair(nullptr) { }
IntCount::~IntCount() { delete [] iPair;}
int IntCount::getSize() {return numInts;}
int IntCount::getCount(int pos) {return iPair[pos].cnt;}
@ -19,49 +19,53 @@ void IntCount::clear()
int IntCount::countAdd(int index, int increment)
{
if(numInts) {
// Do a binary search to find the element
int divPoint = 0;
if(numInts) {
// Do a binary search to find the element
int divPoint = 0;
if(index>iPair[numInts-1].idx) {
if(index>iPair[numInts-1].idx) {
divPoint = numInts;
} else if(index<iPair[0].idx) {
} else if(index<iPair[0].idx) {
divPoint = 0;
} else {
} else {
int low=0, high=numInts-1;
int mid = (low+high)/2;
while(1) {
mid = (low+high)/2;
mid = (low+high)/2;
if(index<iPair[mid].idx) {
high = mid;
} else if(index>iPair[mid].idx) {
if(mid<numInts-1 && index<iPair[mid+1].idx) {
divPoint = mid+1;
break;
} else {
low = mid+1;
}
} else if(index==iPair[mid].idx) {
return iPair[mid].cnt += increment;
}
if(index<iPair[mid].idx) {
high = mid;
} else if(index>iPair[mid].idx) {
if(mid<numInts-1 && index<iPair[mid+1].idx) {
divPoint = mid+1;
break;
} else {
low = mid+1;
}
} else if(index==iPair[mid].idx) {
return iPair[mid].cnt += increment;
}
}
}
int i;
IntPair *tpair = new IntPair[numInts+1];
for(i=0; i<divPoint; i++) tpair[i] = iPair[i];
for(i=divPoint; i<numInts; i++) tpair[i+1] = iPair[i];
++numInts;
delete [] iPair;
iPair = tpair;
iPair[divPoint].idx = index;
iPair[divPoint].cnt = increment;
return increment;
} else {
iPair = new IntPair[1];
numInts = 1;
iPair[0].idx = index;
return iPair[0].cnt = increment;
}
int i;
IntPair *tpair = new IntPair[numInts+1];
for(i=0; i<divPoint; i++) {
tpair[i] = iPair[i];
}
for(i=divPoint; i<numInts; i++) {
tpair[i+1] = iPair[i];
}
++numInts;
delete [] iPair;
iPair = tpair;
iPair[divPoint].idx = index;
iPair[divPoint].cnt = increment;
return increment;
} else {
iPair = new IntPair[1];
numInts = 1;
iPair[0].idx = index;
return iPair[0].cnt = increment;
}
}

View File

@ -17,8 +17,19 @@ public:
int getCount(int pos);
int getIndex(int pos);
IntCount(const IntCount&old)
{
numInts = old.numInts;
if (numInts > 0) {
iPair = new IntPair[numInts];
for (int i = 0; i < numInts; i++) {
iPair[i] = old.iPair[i];
}
} else {
iPair = nullptr;
}
}
private:
IntCount(const IntCount&); // No copy constructor
int numInts;
struct IntPair{int idx; int cnt;} *iPair;

View File

@ -429,6 +429,8 @@ void leaky::open(char *logFile)
{
fprintf(outputfd," <a href=\"#thread_%d\">%d</a> ",
threadArray[i],threadArray[i]);
if ((i+1)%10 == 0)
fprintf(outputfd,"<br>\n");
}
fprintf(outputfd,"</pre>");
}
@ -453,10 +455,10 @@ void leaky::open(char *logFile)
static int symbolOrder(void const* a, void const* b)
{
Symbol const* ap = (Symbol const *)a;
Symbol const* bp = (Symbol const *)b;
return ap->address == bp->address ? 0 :
(ap->address > bp->address ? 1 : -1);
Symbol const** ap = (Symbol const **)a;
Symbol const** bp = (Symbol const **)b;
return (*ap)->address == (*bp)->address ? 0 :
((*ap)->address > (*bp)->address ? 1 : -1);
}
void leaky::ReadSharedLibrarySymbols()
@ -484,9 +486,9 @@ void leaky::setupSymbols(const char *fileName)
}
// Now sort them
qsort(externalSymbols, usefulSymbols, sizeof(Symbol), symbolOrder);
lowestSymbolAddr = externalSymbols[0].address;
highestSymbolAddr = externalSymbols[usefulSymbols-1].address;
qsort(externalSymbols, usefulSymbols, sizeof(Symbol *), symbolOrder);
lowestSymbolAddr = externalSymbols[0]->address;
highestSymbolAddr = externalSymbols[usefulSymbols-1]->address;
}
}
@ -496,18 +498,18 @@ int leaky::findSymbolIndex(u_long addr)
{
u_int base = 0;
u_int limit = usefulSymbols - 1;
Symbol* end = &externalSymbols[limit];
Symbol** end = &externalSymbols[limit];
while (base <= limit) {
u_int midPoint = (base + limit)>>1;
Symbol* sp = &externalSymbols[midPoint];
if (addr < sp->address) {
Symbol** sp = &externalSymbols[midPoint];
if (addr < (*sp)->address) {
if (midPoint == 0) {
return -1;
}
limit = midPoint - 1;
} else {
if (sp+1 < end) {
if (addr < (sp+1)->address) {
if (addr < (*(sp+1))->address) {
return midPoint;
}
} else {
@ -526,7 +528,7 @@ Symbol* leaky::findSymbol(u_long addr)
if(idx<0) {
return NULL;
} else {
return &externalSymbols[idx];
return externalSymbols[idx];
}
}
@ -644,22 +646,22 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
"index", "Count", "Hits", "Function Name");
for(i=0; i<usefulSymbols && countArray[rankingTable[i]]>0; i++) {
Symbol *sp=&externalSymbols[rankingTable[i]];
Symbol **sp=&externalSymbols[rankingTable[i]];
sp->cntP.printReport(fp, this, rankingTable[i], totalTimerHits);
(*sp)->cntP.printReport(fp, this, rankingTable[i], totalTimerHits);
char *symname = htmlify(sp->name);
char *symname = htmlify((*sp)->name);
fprintf(fp, "%6d %6d (%3.1f%%)%s <a name=%d>%8d (%3.1f%%)</a>%s <b>%s</b>\n",
rankingTable[i],
sp->timerHit, (sp->timerHit*1000/totalTimerHits)/10.0,
(sp->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
(*sp)->timerHit, ((*sp)->timerHit*1000/totalTimerHits)/10.0,
((*sp)->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
rankingTable[i], countArray[rankingTable[i]],
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0,
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
symname);
delete [] symname;
sp->cntC.printReport(fp, this, rankingTable[i], totalTimerHits);
(*sp)->cntC.printReport(fp, this, rankingTable[i], totalTimerHits);
fprintf(fp, "<hr>\n");
}
@ -673,9 +675,9 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
for(mx=usefulSymbols/9, h=581130733; h>0; h/=3) {
if(h<mx) {
for(i = h-1; i<usefulSymbols; i++) {
int j, tmp=rankingTable[i], val = externalSymbols[tmp].timerHit;
int j, tmp=rankingTable[i], val = externalSymbols[tmp]->timerHit;
for(j = i;
(j>=h) && (externalSymbols[rankingTable[j-h]].timerHit<val); j-=h) {
(j>=h) && (externalSymbols[rankingTable[j-h]]->timerHit<val); j-=h) {
rankingTable[j] = rankingTable[j-h];
}
rankingTable[j] = tmp;
@ -689,9 +691,9 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
// do single-pass and print this out after the loop finishes.
totalTimerHits = 0;
for(i=0;
i<usefulSymbols && externalSymbols[rankingTable[i]].timerHit>0; i++) {
Symbol *sp=&externalSymbols[rankingTable[i]];
totalTimerHits += sp->timerHit;
i<usefulSymbols && externalSymbols[rankingTable[i]]->timerHit>0; i++) {
Symbol **sp=&externalSymbols[rankingTable[i]];
totalTimerHits += (*sp)->timerHit;
}
if (totalTimerHits == 0)
totalTimerHits = 1;
@ -708,14 +710,14 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
fprintf(fp, "Count %%Total Function Name\n");
// Now loop for as long as we have timer hits
for(i=0;
i<usefulSymbols && externalSymbols[rankingTable[i]].timerHit>0; i++) {
i<usefulSymbols && externalSymbols[rankingTable[i]]->timerHit>0; i++) {
Symbol *sp=&externalSymbols[rankingTable[i]];
Symbol **sp=&externalSymbols[rankingTable[i]];
char *symname = htmlify(sp->name);
char *symname = htmlify((*sp)->name);
fprintf(fp, "<a href=\"#%d\">%3d %-2.1f %s</a>\n",
rankingTable[i], sp->timerHit,
((float)sp->timerHit/(float)totalTimerHits)*100.0, symname);
rankingTable[i], (*sp)->timerHit,
((float)(*sp)->timerHit/(float)totalTimerHits)*100.0, symname);
delete [] symname;
}
}
@ -730,8 +732,8 @@ void leaky::analyze(int thread)
// reset hit counts
for(int i=0; i<usefulSymbols; i++) {
externalSymbols[i].timerHit = 0;
externalSymbols[i].regClear();
externalSymbols[i]->timerHit = 0;
externalSymbols[i]->regClear();
}
// The flag array is used to prevent counting symbols multiple times
@ -773,7 +775,7 @@ void leaky::analyze(int thread)
if(idx>=0) {
// Skip over bogus __restore_rt frames that realtime profiling
// can introduce.
if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) {
if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) {
--pcp;
--i;
idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp));
@ -781,8 +783,8 @@ void leaky::analyze(int thread)
continue;
}
}
Symbol *sp=&externalSymbols[idx];
char *symname = htmlify(sp->name);
Symbol **sp=&externalSymbols[idx];
char *symname = htmlify((*sp)->name);
fprintf(outputfd,"%c-%s\n",type,symname);
delete [] symname;
}
@ -798,7 +800,7 @@ void leaky::analyze(int thread)
if(idx>=0) {
// Skip over bogus __restore_rt frames that realtime profiling
// can introduce.
if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) {
if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) {
--pcp;
--i;
idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp));
@ -814,8 +816,8 @@ void leaky::analyze(int thread)
// 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);
externalSymbols[parrentIdx]->regChild(idx);
externalSymbols[idx]->regParrent(parrentIdx);
}
// inside if() so an unknown in the middle of a stack won't break
// the link!
@ -825,7 +827,7 @@ void leaky::analyze(int thread)
// idx should be the function that we were in when we received the signal.
if(idx>=0) {
++externalSymbols[idx].timerHit;
++externalSymbols[idx]->timerHit;
}
}

View File

@ -75,7 +75,8 @@ struct leaky {
int stacks;
int sfd;
Symbol* externalSymbols;
Symbol** externalSymbols;
Symbol** lastSymbol;
int usefulSymbols;
int numExternalSymbols;
StrSet exclusions;
@ -104,13 +105,14 @@ struct leaky {
void displayStackTrace(FILE* out, malloc_log_entry* lep);
Symbol ** ExtendSymbols(int num);
void ReadSymbols(const char* fileName, u_long aBaseAddress);
void ReadSharedLibrarySymbols();
void setupSymbols(const char* fileName);
Symbol* findSymbol(u_long address);
bool excluded(malloc_log_entry* lep);
bool included(malloc_log_entry* lep);
const char* indexToName(int idx) {return externalSymbols[idx].name;}
const char* indexToName(int idx) {return externalSymbols[idx]->name;}
private:
void generateReportHTML(FILE *fp, int *countArray, int count, int thread);

View File

@ -447,7 +447,7 @@ static void startSignalCounter(unsigned long millisec)
}
}
static long timerMiliSec = 50;
static long timerMilliSec = 50;
#if defined(linux)
static int setupRTCSignals(int hz, struct sigaction *sap)
@ -569,7 +569,7 @@ void *ucontext)
#endif
if (!rtcHz)
startSignalCounter(timerMiliSec);
startSignalCounter(timerMilliSec);
}
NS_EXPORT_(void) setupProfilingStuff(void)
@ -621,12 +621,12 @@ NS_EXPORT_(void) setupProfilingStuff(void)
if(delay) {
double tmp = strtod(delay+strlen("JP_PERIOD="), NULL);
if (tmp>=1e-3) {
timerMiliSec = static_cast<unsigned long>(1000 * tmp);
timerMilliSec = static_cast<unsigned long>(1000 * tmp);
} else {
fprintf(stderr,
"JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n",
tmp);
timerMiliSec = 1;
timerMilliSec = 1;
}
}
@ -653,7 +653,7 @@ NS_EXPORT_(void) setupProfilingStuff(void)
if (rtc) {
#if defined(linux)
rtcHz = atol(rtc+strlen("JP_RTC_HZ="));
timerMiliSec = 0; /* This makes JP_FIRST work right. */
timerMilliSec = 0; /* This makes JP_FIRST work right. */
realTime = 1; /* It's the _R_TC and all. ;) */
#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
@ -754,7 +754,7 @@ NS_EXPORT_(void) setupProfilingStuff(void)
printf("Jprof: Initialized signal handler and set "
"timer for %lu %s, %d s "
"initial delay\n",
rtcHz ? rtcHz : timerMiliSec,
rtcHz ? rtcHz : timerMilliSec,
rtcHz ? "Hz" : "ms",
firstDelay);
@ -771,7 +771,7 @@ NS_EXPORT_(void) setupProfilingStuff(void)
#endif
{
puts("Jprof: started timer");
startSignalCounter(firstDelay*1000 + timerMiliSec);
startSignalCounter(firstDelay*1000 + timerMilliSec);
}
}
}