Annotation of researchv10no/cmd/prof.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.