13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <mach.h>
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier typedef struct Data Data;
73e12c5d1SDavid du Colombier typedef struct Pc Pc;
83e12c5d1SDavid du Colombier typedef struct Acc Acc;
93e12c5d1SDavid du Colombier
103e12c5d1SDavid du Colombier struct Data
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier ushort down;
133e12c5d1SDavid du Colombier ushort right;
143e12c5d1SDavid du Colombier ulong pc;
153e12c5d1SDavid du Colombier ulong count;
163e12c5d1SDavid du Colombier ulong time;
173e12c5d1SDavid du Colombier };
183e12c5d1SDavid du Colombier
193e12c5d1SDavid du Colombier struct Pc
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier Pc *next;
223e12c5d1SDavid du Colombier ulong pc;
233e12c5d1SDavid du Colombier };
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier struct Acc
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier char *name;
283e12c5d1SDavid du Colombier ulong pc;
293e12c5d1SDavid du Colombier ulong ms;
303e12c5d1SDavid du Colombier ulong calls;
313e12c5d1SDavid du Colombier };
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier Data* data;
343e12c5d1SDavid du Colombier Acc* acc;
353e12c5d1SDavid du Colombier ulong ms;
363e12c5d1SDavid du Colombier long nsym;
373e12c5d1SDavid du Colombier long ndata;
383e12c5d1SDavid du Colombier int dflag;
393e12c5d1SDavid du Colombier int rflag;
403e12c5d1SDavid du Colombier Biobuf bout;
4159cc4ca5SDavid du Colombier int tabstop = 4;
42e288d156SDavid du Colombier int verbose;
433e12c5d1SDavid du Colombier
443e12c5d1SDavid du Colombier void syms(char*);
453e12c5d1SDavid du Colombier void datas(char*);
463e12c5d1SDavid du Colombier void graph(int, ulong, Pc*);
473e12c5d1SDavid du Colombier void plot(void);
483e12c5d1SDavid du Colombier char* name(ulong);
493e12c5d1SDavid du Colombier void indent(int);
503e12c5d1SDavid du Colombier char* defaout(void);
513e12c5d1SDavid du Colombier
523e12c5d1SDavid du Colombier void
main(int argc,char * argv[])533e12c5d1SDavid du Colombier main(int argc, char *argv[])
543e12c5d1SDavid du Colombier {
5559cc4ca5SDavid du Colombier char *s;
563e12c5d1SDavid du Colombier
5759cc4ca5SDavid du Colombier s = getenv("tabstop");
5816941224SDavid du Colombier if(s!=nil && strtol(s,0,0)>0)
5916941224SDavid du Colombier tabstop = strtol(s,0,0);
603e12c5d1SDavid du Colombier ARGBEGIN{
61e288d156SDavid du Colombier case 'v':
62e288d156SDavid du Colombier verbose = 1;
63e288d156SDavid du Colombier break;
643e12c5d1SDavid du Colombier case 'd':
653e12c5d1SDavid du Colombier dflag = 1;
663e12c5d1SDavid du Colombier break;
673e12c5d1SDavid du Colombier case 'r':
683e12c5d1SDavid du Colombier rflag = 1;
693e12c5d1SDavid du Colombier break;
703e12c5d1SDavid du Colombier default:
717dd7cddfSDavid du Colombier fprint(2, "usage: prof [-dr] [8.out] [prof.out]\n");
723e12c5d1SDavid du Colombier exits("usage");
733e12c5d1SDavid du Colombier }ARGEND
743e12c5d1SDavid du Colombier Binit(&bout, 1, OWRITE);
753e12c5d1SDavid du Colombier if(argc > 0)
763e12c5d1SDavid du Colombier syms(argv[0]);
773e12c5d1SDavid du Colombier else
783e12c5d1SDavid du Colombier syms(defaout());
793e12c5d1SDavid du Colombier if(argc > 1)
803e12c5d1SDavid du Colombier datas(argv[1]);
813e12c5d1SDavid du Colombier else
823e12c5d1SDavid du Colombier datas("prof.out");
833e12c5d1SDavid du Colombier if(ndata){
843e12c5d1SDavid du Colombier if(dflag)
853e12c5d1SDavid du Colombier graph(0, data[0].down, 0);
863e12c5d1SDavid du Colombier else
873e12c5d1SDavid du Colombier plot();
883e12c5d1SDavid du Colombier }
893e12c5d1SDavid du Colombier exits(0);
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier
923e12c5d1SDavid du Colombier void
swapdata(Data * dp)933e12c5d1SDavid du Colombier swapdata(Data *dp)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier dp->down = beswab(dp->down);
963e12c5d1SDavid du Colombier dp->right = beswab(dp->right);
973e12c5d1SDavid du Colombier dp->pc = beswal(dp->pc);
983e12c5d1SDavid du Colombier dp->count = beswal(dp->count);
993e12c5d1SDavid du Colombier dp->time = beswal(dp->time);
1003e12c5d1SDavid du Colombier }
1013e12c5d1SDavid du Colombier
1023e12c5d1SDavid du Colombier int
acmp(void * va,void * vb)1037dd7cddfSDavid du Colombier acmp(void *va, void *vb)
1043e12c5d1SDavid du Colombier {
1057dd7cddfSDavid du Colombier Acc *a, *b;
1067dd7cddfSDavid du Colombier ulong ua, ub;
1073e12c5d1SDavid du Colombier
1087dd7cddfSDavid du Colombier a = va;
1097dd7cddfSDavid du Colombier b = vb;
1107dd7cddfSDavid du Colombier ua = a->ms;
1117dd7cddfSDavid du Colombier ub = b->ms;
1123e12c5d1SDavid du Colombier
1137dd7cddfSDavid du Colombier if(ua > ub)
1143e12c5d1SDavid du Colombier return 1;
1157dd7cddfSDavid du Colombier if(ua < ub)
1163e12c5d1SDavid du Colombier return -1;
1173e12c5d1SDavid du Colombier return 0;
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier
1203e12c5d1SDavid du Colombier void
syms(char * cout)1213e12c5d1SDavid du Colombier syms(char *cout)
1223e12c5d1SDavid du Colombier {
1233e12c5d1SDavid du Colombier Fhdr f;
1243e12c5d1SDavid du Colombier int fd;
1253e12c5d1SDavid du Colombier
1263e12c5d1SDavid du Colombier if((fd = open(cout, 0)) < 0){
1273e12c5d1SDavid du Colombier perror(cout);
1283e12c5d1SDavid du Colombier exits("open");
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier if (!crackhdr(fd, &f)) {
1313e12c5d1SDavid du Colombier fprint(2, "can't read text file header\n");
1323e12c5d1SDavid du Colombier exits("read");
1333e12c5d1SDavid du Colombier }
1343e12c5d1SDavid du Colombier if (f.type == FNONE) {
1353e12c5d1SDavid du Colombier fprint(2, "text file not an a.out\n");
1363e12c5d1SDavid du Colombier exits("file type");
1373e12c5d1SDavid du Colombier }
1383e12c5d1SDavid du Colombier if (syminit(fd, &f) < 0) {
139219b2ee8SDavid du Colombier fprint(2, "syminit: %r\n");
1403e12c5d1SDavid du Colombier exits("syms");
1413e12c5d1SDavid du Colombier }
1423e12c5d1SDavid du Colombier close(fd);
1433e12c5d1SDavid du Colombier }
1443e12c5d1SDavid du Colombier
1453e12c5d1SDavid du Colombier void
datas(char * dout)1463e12c5d1SDavid du Colombier datas(char *dout)
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier int fd;
1499a747e4fSDavid du Colombier Dir *d;
1503e12c5d1SDavid du Colombier int i;
1513e12c5d1SDavid du Colombier
1523e12c5d1SDavid du Colombier if((fd = open(dout, 0)) < 0){
1533e12c5d1SDavid du Colombier perror(dout);
1543e12c5d1SDavid du Colombier exits("open");
1553e12c5d1SDavid du Colombier }
1569a747e4fSDavid du Colombier d = dirfstat(fd);
1579a747e4fSDavid du Colombier if(d == nil){
1589a747e4fSDavid du Colombier perror(dout);
1599a747e4fSDavid du Colombier exits("stat");
1609a747e4fSDavid du Colombier }
1619a747e4fSDavid du Colombier ndata = d->length/sizeof(data[0]);
1623e12c5d1SDavid du Colombier data = malloc(ndata*sizeof(Data));
1633e12c5d1SDavid du Colombier if(data == 0){
1643e12c5d1SDavid du Colombier fprint(2, "prof: can't malloc data\n");
1653e12c5d1SDavid du Colombier exits("data malloc");
1663e12c5d1SDavid du Colombier }
1679a747e4fSDavid du Colombier if(read(fd, data, d->length) != d->length){
1683e12c5d1SDavid du Colombier fprint(2, "prof: can't read data file\n");
1693e12c5d1SDavid du Colombier exits("data read");
1703e12c5d1SDavid du Colombier }
1719a747e4fSDavid du Colombier free(d);
1723e12c5d1SDavid du Colombier close(fd);
1733e12c5d1SDavid du Colombier for (i = 0; i < ndata; i++)
1743e12c5d1SDavid du Colombier swapdata(data+i);
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier
1773e12c5d1SDavid du Colombier char*
name(ulong pc)1783e12c5d1SDavid du Colombier name(ulong pc)
1793e12c5d1SDavid du Colombier {
1803e12c5d1SDavid du Colombier Symbol s;
1813e12c5d1SDavid du Colombier static char buf[16];
1823e12c5d1SDavid du Colombier
1833e12c5d1SDavid du Colombier if (findsym(pc, CTEXT, &s))
1843e12c5d1SDavid du Colombier return(s.name);
18516941224SDavid du Colombier snprint(buf, sizeof(buf), "#%lux", pc);
1863e12c5d1SDavid du Colombier return buf;
1873e12c5d1SDavid du Colombier }
1883e12c5d1SDavid du Colombier
1893e12c5d1SDavid du Colombier void
graph(int ind,ulong i,Pc * pc)1903e12c5d1SDavid du Colombier graph(int ind, ulong i, Pc *pc)
1913e12c5d1SDavid du Colombier {
1923e12c5d1SDavid du Colombier long time, count, prgm;
1933e12c5d1SDavid du Colombier Pc lpc;
1943e12c5d1SDavid du Colombier
1953e12c5d1SDavid du Colombier if(i >= ndata){
1967dd7cddfSDavid du Colombier fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
1973e12c5d1SDavid du Colombier return;
1983e12c5d1SDavid du Colombier }
1993e12c5d1SDavid du Colombier count = data[i].count;
2003e12c5d1SDavid du Colombier time = data[i].time;
2013e12c5d1SDavid du Colombier prgm = data[i].pc;
2023e12c5d1SDavid du Colombier if(time < 0)
2033e12c5d1SDavid du Colombier time += data[0].time;
2043e12c5d1SDavid du Colombier if(data[i].right != 0xFFFF)
2053e12c5d1SDavid du Colombier graph(ind, data[i].right, pc);
2063e12c5d1SDavid du Colombier indent(ind);
2073e12c5d1SDavid du Colombier if(count == 1)
2083e12c5d1SDavid du Colombier Bprint(&bout, "%s:%lud\n", name(prgm), time);
2093e12c5d1SDavid du Colombier else
2103e12c5d1SDavid du Colombier Bprint(&bout, "%s:%lud/%lud\n", name(prgm), time, count);
2113e12c5d1SDavid du Colombier if(data[i].down == 0xFFFF)
2123e12c5d1SDavid du Colombier return;
2133e12c5d1SDavid du Colombier lpc.next = pc;
2143e12c5d1SDavid du Colombier lpc.pc = prgm;
2153e12c5d1SDavid du Colombier if(!rflag){
2163e12c5d1SDavid du Colombier while(pc){
2173e12c5d1SDavid du Colombier if(pc->pc == prgm){
2183e12c5d1SDavid du Colombier indent(ind+1);
2193e12c5d1SDavid du Colombier Bprint(&bout, "...\n");
2203e12c5d1SDavid du Colombier return;
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier pc = pc->next;
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier }
2253e12c5d1SDavid du Colombier graph(ind+1, data[i].down, &lpc);
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier /*
2283e12c5d1SDavid du Colombier * assume acc is ordered by increasing text address.
2293e12c5d1SDavid du Colombier */
2303e12c5d1SDavid du Colombier long
symind(ulong pc)2313e12c5d1SDavid du Colombier symind(ulong pc)
2323e12c5d1SDavid du Colombier {
2333e12c5d1SDavid du Colombier int top, bot, mid;
2343e12c5d1SDavid du Colombier
2353e12c5d1SDavid du Colombier bot = 0;
2363e12c5d1SDavid du Colombier top = nsym;
2373e12c5d1SDavid du Colombier for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
2383e12c5d1SDavid du Colombier if (pc < acc[mid].pc)
2393e12c5d1SDavid du Colombier top = mid;
2403e12c5d1SDavid du Colombier else
2413e12c5d1SDavid du Colombier if (mid != nsym-1 && pc >= acc[mid+1].pc)
2423e12c5d1SDavid du Colombier bot = mid;
2433e12c5d1SDavid du Colombier else
2443e12c5d1SDavid du Colombier return mid;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier return -1;
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier
2493e12c5d1SDavid du Colombier ulong
sum(ulong i)2503e12c5d1SDavid du Colombier sum(ulong i)
2513e12c5d1SDavid du Colombier {
2523e12c5d1SDavid du Colombier long j, dtime, time;
253e288d156SDavid du Colombier int k;
254e288d156SDavid du Colombier static indent;
2553e12c5d1SDavid du Colombier
2563e12c5d1SDavid du Colombier if(i >= ndata){
2577dd7cddfSDavid du Colombier fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
2583e12c5d1SDavid du Colombier return 0;
2593e12c5d1SDavid du Colombier }
260e288d156SDavid du Colombier j = symind(data[i].pc);
2613e12c5d1SDavid du Colombier time = data[i].time;
2623e12c5d1SDavid du Colombier if(time < 0)
2633e12c5d1SDavid du Colombier time += data[0].time;
264e288d156SDavid du Colombier if (verbose){
265e288d156SDavid du Colombier for(k = 0; k < indent; k++)
266e288d156SDavid du Colombier print(" ");
267e288d156SDavid du Colombier print("%lud: %ld/%lud", i, data[i].time, data[i].count);
268e288d156SDavid du Colombier if (j >= 0)
269e288d156SDavid du Colombier print(" %s\n", acc[j].name);
270e288d156SDavid du Colombier else
271e288d156SDavid du Colombier print(" 0x%lux\n", data[i].pc);
272e288d156SDavid du Colombier }
2733e12c5d1SDavid du Colombier dtime = 0;
274e288d156SDavid du Colombier if(data[i].down != 0xFFFF){
275e288d156SDavid du Colombier indent++;
2763e12c5d1SDavid du Colombier dtime = sum(data[i].down);
277e288d156SDavid du Colombier indent--;
278e288d156SDavid du Colombier }
2793e12c5d1SDavid du Colombier j = symind(data[i].pc);
2803e12c5d1SDavid du Colombier if (j >= 0) {
2813e12c5d1SDavid du Colombier acc[j].ms += time - dtime;
2823e12c5d1SDavid du Colombier ms += time - dtime;
2833e12c5d1SDavid du Colombier acc[j].calls += data[i].count;
2843e12c5d1SDavid du Colombier }
2853e12c5d1SDavid du Colombier if(data[i].right == 0xFFFF)
2863e12c5d1SDavid du Colombier return time;
2873e12c5d1SDavid du Colombier return time + sum(data[i].right);
2883e12c5d1SDavid du Colombier }
2893e12c5d1SDavid du Colombier
2903e12c5d1SDavid du Colombier void
plot(void)2913e12c5d1SDavid du Colombier plot(void)
2923e12c5d1SDavid du Colombier {
2933e12c5d1SDavid du Colombier Symbol s;
2943e12c5d1SDavid du Colombier
2953e12c5d1SDavid du Colombier for (nsym = 0; textsym(&s, nsym); nsym++) {
2963e12c5d1SDavid du Colombier acc = realloc(acc, (nsym+1)*sizeof(Acc));
2973e12c5d1SDavid du Colombier if(acc == 0){
2983e12c5d1SDavid du Colombier fprint(2, "prof: malloc fail\n");
2993e12c5d1SDavid du Colombier exits("acc malloc");
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier acc[nsym].name = s.name;
3023e12c5d1SDavid du Colombier acc[nsym].pc = s.value;
3033e12c5d1SDavid du Colombier acc[nsym].calls = acc[nsym].ms = 0;
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier sum(data[0].down);
3063e12c5d1SDavid du Colombier qsort(acc, nsym, sizeof(Acc), acmp);
3073801c5d3SDavid du Colombier Bprint(&bout, " %% Time Calls Name\n");
3083e12c5d1SDavid du Colombier if(ms == 0)
3093e12c5d1SDavid du Colombier ms = 1;
3103e12c5d1SDavid du Colombier while (--nsym >= 0) {
3113e12c5d1SDavid du Colombier if(acc[nsym].calls)
3127dd7cddfSDavid du Colombier Bprint(&bout, "%4.1f %8.3f %8lud\t%s\n",
3133e12c5d1SDavid du Colombier (100.0*acc[nsym].ms)/ms,
3143e12c5d1SDavid du Colombier acc[nsym].ms/1000.0,
3153e12c5d1SDavid du Colombier acc[nsym].calls,
3163e12c5d1SDavid du Colombier acc[nsym].name);
3173e12c5d1SDavid du Colombier }
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier
3203e12c5d1SDavid du Colombier void
indent(int ind)3213e12c5d1SDavid du Colombier indent(int ind)
3223e12c5d1SDavid du Colombier {
3233e12c5d1SDavid du Colombier int j;
3243e12c5d1SDavid du Colombier
3253e12c5d1SDavid du Colombier j = 2*ind;
32659cc4ca5SDavid du Colombier while(j >= tabstop){
3273e12c5d1SDavid du Colombier Bwrite(&bout, ".\t", 2);
32859cc4ca5SDavid du Colombier j -= tabstop;
3293e12c5d1SDavid du Colombier }
3303e12c5d1SDavid du Colombier if(j)
3313e12c5d1SDavid du Colombier Bwrite(&bout, ". ", j);
3323e12c5d1SDavid du Colombier }
3333e12c5d1SDavid du Colombier
3343e12c5d1SDavid du Colombier char* trans[] =
3353e12c5d1SDavid du Colombier {
3363e12c5d1SDavid du Colombier "386", "8.out",
3377dd7cddfSDavid du Colombier "68020", "2.out",
3387dd7cddfSDavid du Colombier "alpha", "7.out",
339*4e47a2baSDavid du Colombier "amd64", "6.out",
3407dd7cddfSDavid du Colombier "arm", "5.out",
3417dd7cddfSDavid du Colombier "mips", "v.out",
3427dd7cddfSDavid du Colombier "power", "q.out",
3437dd7cddfSDavid du Colombier "sparc", "k.out",
3447dd7cddfSDavid du Colombier "spim", "0.out",
3453e12c5d1SDavid du Colombier 0,0
3463e12c5d1SDavid du Colombier };
3473e12c5d1SDavid du Colombier
3483e12c5d1SDavid du Colombier char*
defaout(void)3493e12c5d1SDavid du Colombier defaout(void)
3503e12c5d1SDavid du Colombier {
3513e12c5d1SDavid du Colombier char *p;
3523e12c5d1SDavid du Colombier int i;
3533e12c5d1SDavid du Colombier
3543e12c5d1SDavid du Colombier p = getenv("objtype");
3553e12c5d1SDavid du Colombier if(p)
3563e12c5d1SDavid du Colombier for(i=0; trans[i]; i+=2)
3573e12c5d1SDavid du Colombier if(strcmp(p, trans[i]) == 0)
3583e12c5d1SDavid du Colombier return trans[i+1];
3593e12c5d1SDavid du Colombier return trans[1];
3603e12c5d1SDavid du Colombier }
361