Annotation of coherent/d/bin/cc/c/coh/profil.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * profil.c
                      3:  * 2/8/85
                      4:  * Usage:  profil [ -alnz ] [ infile [ profile [ outfile ] ] ]
                      5:  *
                      6:  * Reads Intel 8086 OMF SMALL model executable infile and profile, then
                      7:  * writes profile information on outfile; defaults are stdin, PFILE, stdout.
                      8:  * The profile information is normally a list of nonzero counts and names
                      9:  * (sorted by count), followed by a list of unmatched profile counts.
                     10:  * Options:    -a      print addresses in addition to counts and names
                     11:  *             -l      sort by location; implies -a
                     12:  *             -n      sort by name
                     13:  *             -z      include symbols with zero counts
                     14:  *
                     15:  * Reference:  "8086 Relocatable Object Module Formats,"
                     16:  * Intel 121748-001 (c) 1981 Intel Corp.
                     17:  */
                     18: 
                     19: #define        VERSION "1.0"           /* version number */
                     20: #ifdef UDI
                     21: #define        VFLAG   'v'             /* flags must be l.c. for UDI */
                     22: #else
                     23: #define        VFLAG   'V'
                     24: #endif
                     25: 
                     26: #define        NERRMSG 80              /* error message buffer length */
                     27: #define NAMELEN        41              /* max length of an lname + NUL */
                     28: 
                     29: #include <stdio.h>
                     30: #include <prof.h>
                     31: 
                     32: extern char *malloc();
                     33: extern addrcomp();
                     34: extern countcomp();
                     35: extern long getlong();
                     36: extern namecomp();
                     37: 
                     38: /*
                     39:  * OMF types.
                     40:  */
                     41: #define        RHEADR  0x6E            /* R-module header */
                     42: #define BLKDEF 0x7A            /* Block definition */
                     43: #define BLKEND 0x7C            /* Block end */
                     44: #define        THEADR  0x80            /* T-module header */
                     45: #define        LHEADR  0x82            /* L-module header */
                     46: #define        MODEND  0x8A            /* Module end */
                     47: #define        PUBDEF  0x90            /* Public definition */
                     48: #define        LNAMES  0x96            /* list of names */
                     49: #define        SEGDEF  0x98            /* Segment definition */
                     50: #define        GRPDEF  0x9A            /* Group definition */
                     51: 
                     52: /*
                     53:  * Symbols.
                     54:  */
                     55: struct sym {
                     56:        struct sym *s_link;     /* link */
                     57:        char *s_addr;           /* address */
                     58:        long s_count;           /* count */
                     59:        char s_name[];          /* name */
                     60: };
                     61: 
                     62: /*
                     63:  * Globals.
                     64:  */
                     65: int    aflag;                  /* print address info */
                     66: int    lflag;                  /* sort by location */
                     67: int    nflag;                  /* sort by name */
                     68: int    zflag;                  /* print zero counts */
                     69: int    lnamen;                 /* lname index */
                     70: int    segn;                   /* segment index */
                     71: int    groupn;                 /* group index */
                     72: int    len;                    /* record length excluding checksum */
                     73: int    csum;                   /* checksum */
                     74: int    codelname;              /* lname index of CODE */
                     75: int    cseg;                   /* segment index of CODE */
                     76: int    cgrouplname;            /* lname index of CGROUP */
                     77: int    cgroup;                 /* group index of CGROUP */
                     78: int    nsyms;                  /* number of symbols */
                     79: int    nnotfound;              /* profile entries not found in symbols */
                     80: struct sym *symlist;           /* linked list of symbols */
                     81: struct sym **sympp;            /* sorted table of symbols */
                     82: char   id[NAMELEN];            /* identifier */
                     83: char   *filename;              /* file name */
                     84: 
                     85: main(argc, argv)
                     86: int argc;
                     87: char **argv;
                     88: {
                     89:        register int c;
                     90:        ++argv;
                     91:        if ((argc > 1) && (**argv == '-')) {
                     92:                while (c = *++*argv) {
                     93:                        switch (c) {
                     94:                        case 'a':       ++aflag;
                     95:                                        break;
                     96:                        case 'l':       ++lflag;
                     97:                                        ++aflag;
                     98:                                        break;
                     99:                        case 'n':       ++nflag;
                    100:                                        break;
                    101:                        case 'z':       ++zflag;
                    102:                                        break;
                    103:                        case VFLAG:     fprintf(stderr, "profil:  V%s\n", VERSION);
                    104:                                        break;
                    105:                        default:        usage();
                    106:                                        break;
                    107:                        }
                    108:                }
                    109:                ++argv;
                    110:                --argc;
                    111:        }
                    112:        if (argc > 4)
                    113:                usage();
                    114:        if (argc >=2) {
                    115:                filename = *argv++;
                    116:                if (freopen(filename, "rb", stdin) == NULL)
                    117:                        fatalf("cannot open executable %s for input");
                    118:        }
                    119:        else
                    120:                filename = "stdin";     /* For error messages... */
                    121:        readsyms();                     /* Read symbols from the executable. */
                    122:        addrsort();                     /* Sort the symbols by address. */
                    123:        filename = (argc >= 3) ? *argv++ : PFILE;
                    124:        if (freopen(filename, "rb", stdin) == NULL)
                    125:                fatalf("cannot open profile %s for input");
                    126:        readprof();                     /* Read the profile information. */
                    127:        if (argc == 4) {
                    128:                filename = *argv;
                    129:                if (freopen(filename, "w", stdout) == NULL)
                    130:                        fatalf("cannot open %s for output");
                    131:        }
                    132:        dumpprof();                     /* Dump the profile. */
                    133:        exit(0);
                    134: }
                    135: 
                    136: /*
                    137:  * Compare the addresses of two symbols for qsort.
                    138:  */
                    139: addrcomp(p1, p2)
                    140: struct sym **p1, **p2;
                    141: {
                    142:        register char *a1, *a2;
                    143:        a1 = (*p1)->s_addr;
                    144:        a2 = (*p2)->s_addr;
                    145:        return((a1 < a2) ? -1 : ((a1 == a2) ? 0 : 1));
                    146: }
                    147: 
                    148: /*
                    149:  * Sort the symbols by address.
                    150:  */
                    151: addrsort()
                    152: {
                    153:        register struct sym **spp;
                    154:        /* Allocate a table for the sym pointers. */
                    155:        if ((sympp = (struct sym **)malloc((nsyms+1)*sizeof(struct sym *))) == NULL)
                    156:                fatal("out of memory for symbol sorting");
                    157:        /* Copy the sym pointers from the linked list into the table. */
                    158:        spp = sympp;
                    159:        while (symlist) {
                    160:                *spp++ = symlist;
                    161:                symlist = symlist->s_link;
                    162:        }
                    163:        *spp = NULL;                    /* Null terminate the table. */
                    164:        qsort(sympp, nsyms, sizeof(struct sym *), addrcomp);    /* Sort it. */
                    165: }
                    166: 
                    167: /*
                    168:  * Add a new symbol with name id to the symbol list.
                    169:  */
                    170: addsym(offset)
                    171: unsigned offset;
                    172: {
                    173:        register struct sym *sp;
                    174:        if ((sp = (struct sym *) malloc(sizeof(struct sym) + strlen(id) + 1)) == NULL)
                    175:                fatal("out of memory for symbols");
                    176:        sp->s_link = symlist;
                    177:        sp->s_addr = offset;
                    178:        sp->s_count = 0L;
                    179:        strcpy(sp->s_name, id);
                    180:        symlist = sp;
                    181: }
                    182: 
                    183: /*
                    184:  * Compare the counts of two symbols for qsort.
                    185:  */
                    186: countcomp(p1, p2)
                    187: struct sym **p1, **p2;
                    188: {
                    189:        register long l1, l2;
                    190:        l1 = (*p1)->s_count;
                    191:        l2 = (*p2)->s_count;
                    192:        return((l1 < l2) ? -1 : ((l1 == l2) ? 0 : 1));
                    193: }
                    194: 
                    195: /*
                    196:  * Dump the profile information.
                    197:  */
                    198: dumpprof()
                    199: {
                    200:        /* Sort symbol table (now sorted by address) by desired method. */
                    201:        if (nflag)
                    202:                qsort(sympp, nsyms, sizeof(struct sym *), namecomp);
                    203:        else if (!lflag)
                    204:                qsort(sympp, nsyms, sizeof(struct sym *), countcomp);
                    205:        dumpsyms();                     /* Dump the sorted list. */
                    206:        if (nnotfound == 0)
                    207:                return;                 /* No unmatched symbols. */
                    208:        printf("Not found:\n");
                    209:        nsyms = nnotfound;
                    210:        addrsort();                     /* Sort the not found list. */
                    211:        if (!lflag)
                    212:                qsort(sympp, nsyms, sizeof(struct sym *), countcomp);
                    213:        aflag = 1;                      /* Force address printing. */
                    214:        dumpsyms();                     /* Dump the not found list. */
                    215: }
                    216: 
                    217: /*
                    218:  * Dump the sorted symbol table.
                    219:  * Free the symbols and the table.
                    220:  */
                    221: dumpsyms()
                    222: {
                    223:        register struct sym **spp;
                    224:        register struct sym *sp;
                    225:        for (spp = sympp; *spp; spp++) {
                    226:                sp = *spp;
                    227:                if (!zflag && (sp->s_count == 0L))
                    228:                        continue;
                    229:                printf("%8ld ", sp->s_count);
                    230:                if (aflag)
                    231:                        printf("0x%04x ", sp->s_addr);
                    232:                printf("%s\n", sp->s_name);
                    233:                free(sp);
                    234:        }
                    235:        free(sympp);
                    236: }
                    237:  
                    238: /*
                    239:  * Print error message and exit.
                    240:  */
                    241: fatal(s)
                    242: register char *s;
                    243: {
                    244:        fprintf(stderr, "profil:  %s\n", s);
                    245:        exit(1);
                    246: }
                    247: 
                    248: /*
                    249:  * Print error message with current filename and exit.
                    250:  */
                    251: fatalf(s)
                    252: register char *s;
                    253: {
                    254:        char errmsg[NERRMSG];
                    255:        sprintf(errmsg, s, filename);
                    256:        fatal(errmsg);
                    257: }
                    258: 
                    259: /*
                    260:  * Read a byte from standard input, update checksum and len.
                    261:  */
                    262: getb()
                    263: {
                    264:        register int i;
                    265:        if ((i = getchar()) == EOF)
                    266:                fatalf("premature EOF on %s");
                    267:        csum += i;
                    268:        --len;
                    269:        return(i);
                    270: }
                    271: 
                    272: /*
                    273:  * Get BLKDEF procedure name info.
                    274:  * This is not done for nested BLKDEFs.
                    275:  */
                    276: getblkdef()
                    277: {
                    278:        if (getgsf()) {
                    279:                ++nsyms;
                    280:                getname();
                    281:                addsym(geti());
                    282:        }
                    283: }
                    284: 
                    285: /*
                    286:  * Get GRPDEF info.
                    287:  * Set cgroup if the LNAME is "CGROUP".
                    288:  */
                    289: getgrpdef()
                    290: {
                    291:        ++groupn;                       /* Bump group index. */
                    292:        if (getindex() == cgrouplname)
                    293:                cgroup = groupn;
                    294: }
                    295: 
                    296: /*
                    297:  * Get group, segment and optional frame number.
                    298:  * Returns TRUE if group is CGROUP and segment is CODE.
                    299:  */
                    300: getgsf()
                    301: {
                    302:        register int group, segm;
                    303:        group = getindex();
                    304:        segm = getindex();
                    305:        if ((group == 0) && (segm == 0))
                    306:                return(0);
                    307:        return((group==cgroup) && (segm==cseg));
                    308: }
                    309: 
                    310: /*
                    311:  * Read a word and return it.
                    312:  */
                    313: geti()
                    314: {
                    315:        register int i = getb();
                    316:        return(i | (getb() << 8));
                    317: }
                    318: 
                    319: /*
                    320:  * Read an index and return it.
                    321:  */
                    322: getindex()
                    323: {
                    324:        register int i = getb();
                    325:        if ((i&0x80) == 0)
                    326:                return(i);
                    327:        return(((i&0x7F)<<8) | getb());
                    328: }
                    329: 
                    330: /*
                    331:  * Get an LNAME record.
                    332:  * Set codelname if the LNAME is "CODE".
                    333:  * Set cgrouplname if the LNAME is "CGROUP".
                    334:  */
                    335: getlnames()
                    336: {
                    337:        while (len) {
                    338:                ++lnamen;               /* Bump LNAME index. */
                    339:                getname();
                    340:                if (strcmp(id, "CODE") == 0)
                    341:                        codelname = lnamen;
                    342:                else if (strcmp(id, "CGROUP") == 0)
                    343:                        cgrouplname = lnamen;
                    344:        }
                    345: }
                    346: 
                    347: /*
                    348:  * Read a long and return it.
                    349:  */
                    350: long
                    351: getlong()
                    352: {
                    353:        register long l = geti();
                    354:        return(l | (geti() << 16));
                    355: }
                    356: 
                    357: /*
                    358:  * Read a name into id.
                    359:  */
                    360: getname()
                    361: {
                    362:        register int len = getb();
                    363:        register char *cp = &id[0];
                    364:        while (len--)
                    365:                *cp++ = getb();
                    366:        *cp = '\0';
                    367: }
                    368: 
                    369: /*
                    370:  * Get PUBDEF info.
                    371:  * Add it to symbols if in CGROUP and CODE segment.
                    372:  */
                    373: getpubdef()
                    374: {
                    375:        if (getgsf()) {
                    376:                while (len) {
                    377:                        ++nsyms;
                    378:                        getname();
                    379:                        addsym(geti());
                    380:                        getindex();
                    381:                }
                    382:        }
                    383: }
                    384: 
                    385: /*
                    386:  * Get SEGDEF info.
                    387:  * Set cseg if the LNAME is "CODE".
                    388:  */
                    389: getsegdef()
                    390: {
                    391:        register int a;
                    392:        ++segn;                         /* Bump segment index. */
                    393:        a = (getb()&0xE0) >> 5;
                    394:        if (a == 5)
                    395:                return;
                    396:        else if (a == 0) {
                    397:                geti();
                    398:                getb();
                    399:        }
                    400:        else if (a == 6) {
                    401:                getb();
                    402:                geti();
                    403:                geti();
                    404:        }
                    405:        geti();                         /* Length. */
                    406:        if (getindex() == codelname)
                    407:                cseg = segn;            /* Set code segment index. */
                    408: }
                    409: 
                    410: /*
                    411:  * Ignore len bytes.
                    412:  */
                    413: ignore()
                    414: {
                    415:        while (len)
                    416:                getb();
                    417: }
                    418: 
                    419: /*
                    420:  * Compare the names of two symbols for qsort.
                    421:  */
                    422: namecomp(p1, p2)
                    423: struct sym **p1, **p2;
                    424: {
                    425:        return(strcmp((*p1)->s_name, (*p2)->s_name));
                    426: }
                    427: 
                    428: /*
                    429:  * Print warning message.
                    430:  */
                    431: nonfatal(s)
                    432: register char *s;
                    433: {
                    434:        fprintf(stderr, "profil:  warning:  %s\n", s);
                    435: }
                    436: 
                    437: /*
                    438:  * Read the profile file.
                    439:  */
                    440: readprof()
                    441: {
                    442:        register struct sym **spp;
                    443:        register unsigned int addr;
                    444:        register int i;
                    445:        register long count;
                    446:        if (geti() != PSMALL)
                    447:                fatalf("%s is not a profile file");
                    448:        id[0] = '\0';                           /* Nil id for nonfounds. */
                    449:        while ((i=getchar()) != EOF) {          /* Look ahead for EOF. */
                    450:                ungetc(i, stdin);               /* Put it back. */
                    451:                count = getlong();              /* Get count. */
                    452:                geti();                         /* Ignore link. */
                    453:                addr = geti() -  PSBACK;        /* Get loc and adjust. */
                    454:                for (spp = sympp; *spp ; spp++) {
                    455:                        if ((*spp)->s_addr == addr) {   /* Matched. */
                    456:                                (*spp)->s_count = count;
                    457:                                break;
                    458:                        }
                    459:                        else if ((*spp)->s_addr > addr) {
                    460:                                ++nnotfound;    /* Not found. */
                    461:                                addsym(addr);   /* Add to not found list. */
                    462:                                symlist->s_count = count;
                    463:                                break;
                    464:                        }
                    465:                }
                    466:        }
                    467: }
                    468: 
                    469: /*
                    470:  * Read symbols from the OMF executable file and build symbol table.
                    471:  */
                    472: readsyms()
                    473: {
                    474:        register int type, blevel, xflag;
                    475:        type = getb();
                    476:        if ((type != THEADR) && (type != LHEADR) && (type != RHEADR))
                    477:                fatalf("%s is not an object file");
                    478:        ungetc(type, stdin);
                    479:        csum = blevel = xflag = 0;
                    480:        while (!xflag) {
                    481:                type = getb();                  /* Record type. */
                    482:                len = geti() - 1;               /* Record length without csum. */
                    483:                switch (type) {
                    484:                        case BLKDEF:
                    485:                                if (blevel++ == 0)
                    486:                                        getblkdef();
                    487:                                break;
                    488:                        case BLKEND:
                    489:                                --blevel;
                    490:                                break;
                    491:                        case GRPDEF:
                    492:                                getgrpdef();
                    493:                                break;
                    494:                        case LNAMES:
                    495:                                getlnames();
                    496:                                break;
                    497:                        case MODEND:
                    498:                                xflag = 1;
                    499:                                break;
                    500:                        case PUBDEF:
                    501:                                getpubdef();
                    502:                                break;
                    503:                        case SEGDEF:
                    504:                                getsegdef();
                    505:                                break;
                    506:                        default:
                    507:                                break;
                    508:                }
                    509:                ignore();                       /* Skip to csum. */
                    510:                getb();                         /* Read the csum. */
                    511:                if ((csum&0xFF) != 0)
                    512:                        fatalf("checksum error on executable %s");
                    513:        }
                    514:        if (getchar() != EOF)
                    515:                fatalf("data after MODEND on executable %s");
                    516:        if (cseg == 0)
                    517:                nonfatal("cannot find CODE segment");
                    518:        if (cgroup == 0)
                    519:                nonfatal("cannot find CGROUP");
                    520: }
                    521: 
                    522: /*
                    523:  * Print usage message and exit.
                    524:  */
                    525: usage()
                    526: {
                    527:        fatal("Usage:  profil [ -alnz ] [ infile [ profile [ outfile ] ] ]");
                    528: }

unix.superglobalmegacorp.com

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