Annotation of coherent/b/bin/c/coh/profil.c, revision 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.