|
|
1.1 ! root 1: #include "sys/types.h" ! 2: #include "sys/stat.h" ! 3: #include "a.out.h" ! 4: /* it wouldn't be better to get this out of sys/param.h */ ! 5: #define HZ 60 ! 6: ! 7: typedef unsigned short Prof; /* what the counts are stored in! */ ! 8: /* a mon.out consists of a phdr, cnt structs pcnt, and the rest are ! 9: Profs of pc clicks */ ! 10: struct phdr { ! 11: char *lopc, *hipc; /* void *? */ ! 12: int cnt; ! 13: }; ! 14: struct phdr hsv; ! 15: struct pcnt { ! 16: char * value; ! 17: long calls; ! 18: }; ! 19: char flags[128]; ! 20: char *xfile, *file; ! 21: struct nlist *names; ! 22: char *strings, *pbuf; ! 23: Prof *accum; ! 24: int accumsz; ! 25: typedef struct { ! 26: char *loc; ! 27: char *name; ! 28: long calls; ! 29: long clicks; ! 30: unsigned char type; ! 31: } sym; ! 32: int nsym; ! 33: sym *syms, nilsym; ! 34: long lopct, hipct; /* plot stuff */ ! 35: double rscale, roffset; ! 36: ! 37: main(argc, argv) ! 38: char **argv; ! 39: { int c; ! 40: extern int optind; ! 41: extern char **optarg; ! 42: char *p; ! 43: ! 44: while((c = getopt(argc, argv, "alnsvz")) != -1) ! 45: switch(c) { ! 46: case 'l': case 'n': case 's': case 'z': ! 47: flags[c] = 1; ! 48: continue; ! 49: case 'v': ! 50: flags['v'] = 1; ! 51: p = argv[optind]; ! 52: if(*p != '-' || p[1] > '9' || p[1] < '0') ! 53: continue; ! 54: lopct = atoi(p+1); ! 55: p = argv[++optind]; ! 56: if(*p != '-' || p[1] > '9' || p[1] < '0') ! 57: continue; ! 58: hipct = atoi(p+1); ! 59: optind++; ! 60: continue; ! 61: case '?': ! 62: fatal("usage: %s -[alnsz] files\n", argv[0]); ! 63: } ! 64: if(optind < argc) ! 65: xfile = argv[optind++]; ! 66: else ! 67: xfile = "a.out"; ! 68: readsyms(); ! 69: if(optind >= argc) ! 70: doit("mon.out"); ! 71: else ! 72: for(; optind < argc; optind++) ! 73: doit(argv[optind]); ! 74: output(); ! 75: exit(0); ! 76: } ! 77: ! 78: doit(s) ! 79: char *s; ! 80: { struct stat stb; ! 81: int fd; ! 82: ! 83: file = s; ! 84: fd = open(s, 0); ! 85: if(fd < 0) ! 86: fatal("couldn't open %s\n", s); ! 87: fstat(fd, &stb); ! 88: pbuf = (char *) malloc(stb.st_size); ! 89: if(pbuf == 0) ! 90: fatal("couldn't alloc %d bytes for %s\n", stb.st_size, s); ! 91: if(read(fd, pbuf, stb.st_size) != stb.st_size) ! 92: fatal("read of %s failed\n", s); ! 93: if(stb.st_size <= sizeof(struct phdr)) ! 94: fatal("%s not a mon.out\n"); ! 95: close(fd); ! 96: addcalls(); ! 97: addclicks(stb.st_size); ! 98: free(pbuf); ! 99: } ! 100: ! 101: addclicks(top) ! 102: { int i, n, cnt, j; ! 103: char *x; ! 104: Prof *p; ! 105: struct phdr *h; ! 106: double scale; /* the kernel uses 16 bit fractions */ ! 107: ! 108: h = (struct phdr *)pbuf; ! 109: n = ((struct phdr *)pbuf)->cnt; ! 110: p = (Prof *) (pbuf + sizeof(struct phdr) + n * sizeof(struct pcnt)); ! 111: top -= sizeof(struct phdr) + n * sizeof(struct pcnt); ! 112: cnt = top/sizeof(Prof); /* number of counters */ ! 113: if(flags['s'] && !accumsz) { ! 114: accum = (Prof *) malloc(cnt*sizeof(Prof)); ! 115: (void) memset(accum, 0, cnt*sizeof(Prof)); ! 116: accumsz = cnt; ! 117: hsv = *h; ! 118: } /* we assume h is fixed across the files */ ! 119: scale = (h->hipc-h->lopc)/(double)cnt; ! 120: /* in mcrt0.s it's 8 */ ! 121: for(j = i = 0; i < cnt; i++) { ! 122: x = (char *)(h->lopc + (int)(scale*i)); ! 123: while(j < nsym && syms[j+1].loc < x) ! 124: j++; ! 125: if(j > nsym) ! 126: fatal("cnts out of range %s\n", file); ! 127: syms[j].clicks += p[i]; ! 128: } ! 129: if(flags['s']) ! 130: for(i = 0; i < accumsz; i++) { ! 131: n = accum[i] + p[i]; ! 132: accum[i] = n; ! 133: if(n != accum[i]) { ! 134: mesg("overflow in accumulating counts, -s ignored\n"); ! 135: flags['s'] = 0; ! 136: return; ! 137: } ! 138: } ! 139: } ! 140: ! 141: addcalls() ! 142: { int n, i; ! 143: struct pcnt *p; ! 144: ! 145: p = (struct pcnt *)(pbuf + sizeof(struct phdr)); ! 146: n = ((struct phdr *)pbuf)->cnt; ! 147: for(i = 0; i < n; i++, p++) ! 148: addcall(p->value, p->calls); ! 149: } ! 150: ! 151: addcall(x, n) ! 152: char *x; ! 153: { int i; ! 154: for(i = 0; i < nsym && syms[i+1].loc < x; i++) ! 155: ; ! 156: if(i >= nsym) { ! 157: mesg("cntr out of range (%s), ignored\n", file); ! 158: return; ! 159: } ! 160: if(syms[i+1].loc == x) ! 161: syms[i+1].calls += n; ! 162: else ! 163: syms[i].calls += n; ! 164: } ! 165: ! 166: symnum(a, b) ! 167: register sym *a, *b; ! 168: { ! 169: return(a->loc - b->loc); ! 170: } ! 171: ! 172: readsyms() ! 173: { int fd, n, i, j; ! 174: struct exec x; ! 175: struct stat stb; ! 176: struct nlist *np; ! 177: ! 178: fd = open(xfile, 0); ! 179: if(fd < 0) ! 180: fatal("couldn't read %s\n", xfile); ! 181: if(read(fd, (char *)&x, sizeof(x)) != sizeof(x)) ! 182: fatal("can't read header of %s\n", xfile); ! 183: if(!x.a_syms) ! 184: fatal("%s has no symbol table\n", xfile); ! 185: ! 186: /* read the symbol table in */ ! 187: lseek(fd, N_SYMOFF(x), 0); ! 188: names = (struct nlist *) malloc(x.a_syms); ! 189: read(fd, (char *)names, x.a_syms); ! 190: nsym = N_STROFF(x) - N_SYMOFF(x); ! 191: nsym /= sizeof(struct nlist); /* over estimated */ ! 192: ! 193: /* read the wretched strings in */ ! 194: lseek(fd, N_STROFF(x), 0); ! 195: fstat(fd, &stb); ! 196: n = stb.st_size - N_STROFF(x); ! 197: strings = (char *) malloc(n); ! 198: if(read(fd, strings, n) != n) ! 199: fatal("couldn't read string table from %s (%d)\n", xfile, n); ! 200: ! 201: /* copy the text symbols into the symbol table */ ! 202: syms = (sym *) malloc(nsym * sizeof(sym)); ! 203: for(i = 0, np = names; np < names + nsym; np++) { ! 204: if((np->n_type & N_TYPE) != N_TEXT) ! 205: continue; ! 206: if(np->n_type & N_STAB) ! 207: continue; ! 208: syms[i] = nilsym; ! 209: syms[i].type = np->n_type; ! 210: syms[i].loc = (char *)np->n_value; ! 211: syms[i].name = strings + np->n_un.n_strx; ! 212: i++; ! 213: } ! 214: nsym = i; ! 215: qsort((char *)syms, nsym, sizeof(sym), symnum); ! 216: ! 217: /* now decide which of the ones with the same loc we like */ ! 218: for(i = 0; i < nsym; i = j) { ! 219: for(j = i+1; j < nsym; j++) ! 220: if(syms[i].loc != syms[j].loc) ! 221: break; ! 222: choose(i, j); ! 223: } ! 224: /* and squash it down */ ! 225: for(i = j = 0; i < nsym; i++) ! 226: if(syms[i].type) ! 227: syms[j++] = syms[i]; ! 228: nsym = j; ! 229: syms[nsym].loc = (char *)0x8fffffff; /* a very big end */ ! 230: close(fd); ! 231: } ! 232: ! 233: /* the expert system */ ! 234: choose(i, j) ! 235: { int n; ! 236: if(j-i <= 1) ! 237: return; ! 238: /* if there is an external text one, take it */ ! 239: for(n = i; n < j; n++) ! 240: if(syms[n].type & N_EXT) ! 241: goto found; ! 242: /* if there is one that starts with _, take it */ ! 243: for(n = i; n < j; n++) ! 244: if(syms[n].name[0] == '_') ! 245: goto found; ! 246: /* if there is one without a . in it, take it */ ! 247: for(n = i; n < j; n++) ! 248: if(!strchr(syms[n].name, '.')) ! 249: goto found; ! 250: /* first must be right, or at least ok */ ! 251: n = i; ! 252: found: ! 253: for(; i < j; i++) ! 254: if(i != n) ! 255: syms[i].type = 0; ! 256: } ! 257: ! 258: char ebuf[256]; ! 259: mesg(s, a, b, c, d, e, f) ! 260: char *s; ! 261: { ! 262: sprintf(ebuf, s, a, b, c, d, e, f); ! 263: write(2, ebuf, strlen(ebuf)); ! 264: } ! 265: ! 266: fatal(s, a, b, c, d, e, f) ! 267: char *s; ! 268: { ! 269: mesg(s, a, b, c, d, e, f); ! 270: exit(1); ! 271: } ! 272: ! 273: symcalls(a, b) ! 274: register sym *a, *b; ! 275: { ! 276: return(b->calls - a->calls); ! 277: } ! 278: ! 279: symcnt(a, b) ! 280: register sym *a, *b; ! 281: { ! 282: return(b->clicks - a->clicks); /* largest first */ ! 283: } ! 284: ! 285: output() ! 286: { int i, tot, fd; ! 287: double x, y; ! 288: ! 289: if(flags['v']) { ! 290: plotout(); ! 291: return; ! 292: } ! 293: for(tot = i = 0; i < nsym; i++) ! 294: tot += syms[i].clicks; ! 295: if(tot == 0) ! 296: tot = 1; ! 297: if(flags['n']) ! 298: qsort((char *)syms, nsym, sizeof(sym), symcalls); ! 299: else if(!flags['l']) ! 300: qsort((char *)syms, nsym, sizeof(sym), symcnt); ! 301: printf(" %% Time\tCalls\tName\n"); ! 302: for(i = 0; i < nsym; i++) { ! 303: if(!syms[i].calls && !syms[i].clicks && !flags['z']) ! 304: continue; ! 305: x = syms[i].clicks; ! 306: x /= HZ; ! 307: y = syms[i].clicks/(double)tot; ! 308: printf("%4.1f%8.3f %8d\t%s\n", (y*100), x, syms[i].calls, ! 309: syms[i].name); ! 310: } ! 311: if(!flags['s']) ! 312: return; ! 313: fd = creat("mon.sum", 0666); ! 314: if(fd < 0) ! 315: fatal("can't create mon.sum\n"); ! 316: hsv.cnt = nsym; ! 317: if(write(fd, (char *)&hsv, sizeof(hsv)) != sizeof(hsv)) ! 318: fatal("write failed\n"); ! 319: for(i = 0; i < nsym; i++) { /* this is very inefficient */ ! 320: write(fd, (char *)&syms[i].loc, 4); /* 4! */ ! 321: write(fd, (char *)&syms[i].calls, 4); ! 322: } ! 323: if(write(fd, (char *)accum, accumsz*sizeof(Prof)) != accumsz*sizeof(Prof)) ! 324: fatal("write failed\n"); ! 325: close(fd); ! 326: } ! 327: ! 328: /* most of this is witchcraft */ ! 329: plotout() ! 330: { int i; ! 331: /* double lastx, lasty; ! 332: if(lopct >= 100 || lopct < 0) ! 333: lopct = 0; ! 334: if(hipct > 100 || hipct <= 0) ! 335: hipct = 100; ! 336: rscale = 100./(hipct-lopct); ! 337: roffset = 2040.+40.8*lopct*rscale; ! 338: openpl(); ! 339: erase(); ! 340: range(-2048, -2048, 2048, 2048); ! 341: line(-2040, -2040, -2040, 2040); ! 342: for(i = 0; i < 11; i++) ! 343: line(-2040, 2040-i*408, 0, 2040-i*408); ! 344: */ ! 345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.