[BACK]Return to gprof.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / gprof

Annotation of src/usr.bin/gprof/gprof.c, Revision 1.6

1.6     ! aaron       1: /*     $OpenBSD: gprof.c,v 1.5 1999/06/16 15:23:53 deraadt Exp $       */
1.1       deraadt     2: /*     $NetBSD: gprof.c,v 1.8 1995/04/19 07:15:59 cgd Exp $    */
                      3:
                      4: /*
                      5:  * Copyright (c) 1983, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
                     38: static char copyright[] =
                     39: "@(#) Copyright (c) 1983, 1993\n\
                     40:        The Regents of the University of California.  All rights reserved.\n";
                     41: #endif /* not lint */
                     42:
                     43: #ifndef lint
                     44: #if 0
                     45: static char sccsid[] = "@(#)gprof.c    8.1 (Berkeley) 6/6/93";
                     46: #else
1.6     ! aaron      47: static char rcsid[] = "$OpenBSD: gprof.c,v 1.5 1999/06/16 15:23:53 deraadt Exp $";
1.1       deraadt    48: #endif
                     49: #endif /* not lint */
                     50:
                     51: #include "gprof.h"
                     52:
                     53: char   *whoami = "gprof";
                     54:
                     55:     /*
                     56:      * things which get -E excluded by default.
                     57:      */
                     58: char   *defaultEs[] = { "mcount" , "__mcleanup" , 0 };
                     59:
                     60: static struct gmonhdr  gmonhdr;
                     61:
                     62: main(argc, argv)
                     63:     int argc;
                     64:     char **argv;
                     65: {
                     66:     char       **sp;
                     67:     nltype     **timesortnlp;
                     68:
                     69:     --argc;
                     70:     argv++;
                     71:     debug = 0;
                     72:     bflag = TRUE;
                     73:     while ( *argv != 0 && **argv == '-' ) {
                     74:        (*argv)++;
                     75:        switch ( **argv ) {
                     76:        case 'a':
                     77:            aflag = TRUE;
                     78:            break;
                     79:        case 'b':
                     80:            bflag = FALSE;
                     81:            break;
                     82:        case 'C':
                     83:            Cflag = TRUE;
                     84:            cyclethreshold = atoi( *++argv );
                     85:            break;
                     86:        case 'c':
1.5       deraadt    87: #if defined(__i386__) || defined(__vax__) || defined(__tahoe__) || defined(__sparc__)
1.1       deraadt    88:            cflag = TRUE;
                     89: #else
                     90:            fprintf(stderr, "gprof: -c isn't supported on this architecture yet\n");
                     91:            exit(1);
                     92: #endif
                     93:            break;
                     94:        case 'd':
                     95:            dflag = TRUE;
                     96:            setlinebuf(stdout);
                     97:            debug |= atoi( *++argv );
                     98:            debug |= ANYDEBUG;
                     99: #          ifdef DEBUG
                    100:                printf("[main] debug = %d\n", debug);
                    101: #          else not DEBUG
                    102:                printf("%s: -d ignored\n", whoami);
                    103: #          endif DEBUG
                    104:            break;
                    105:        case 'E':
                    106:            ++argv;
                    107:            addlist( Elist , *argv );
                    108:            Eflag = TRUE;
                    109:            addlist( elist , *argv );
                    110:            eflag = TRUE;
                    111:            break;
                    112:        case 'e':
                    113:            addlist( elist , *++argv );
                    114:            eflag = TRUE;
                    115:            break;
                    116:        case 'F':
                    117:            ++argv;
                    118:            addlist( Flist , *argv );
                    119:            Fflag = TRUE;
                    120:            addlist( flist , *argv );
                    121:            fflag = TRUE;
                    122:            break;
                    123:        case 'f':
                    124:            addlist( flist , *++argv );
                    125:            fflag = TRUE;
                    126:            break;
                    127:        case 'k':
                    128:            addlist( kfromlist , *++argv );
                    129:            addlist( ktolist , *++argv );
                    130:            kflag = TRUE;
                    131:            break;
                    132:        case 's':
                    133:            sflag = TRUE;
                    134:            break;
                    135:        case 'z':
                    136:            zflag = TRUE;
                    137:            break;
                    138:        }
                    139:        argv++;
                    140:     }
                    141:     if ( *argv != 0 ) {
                    142:        a_outname  = *argv;
                    143:        argv++;
                    144:     } else {
                    145:        a_outname  = A_OUTNAME;
                    146:     }
                    147:     if ( *argv != 0 ) {
                    148:        gmonname = *argv;
                    149:        argv++;
                    150:     } else {
                    151:        gmonname = GMONNAME;
                    152:     }
                    153:        /*
                    154:         *      turn off default functions
                    155:         */
                    156:     for ( sp = &defaultEs[0] ; *sp ; sp++ ) {
                    157:        Eflag = TRUE;
                    158:        addlist( Elist , *sp );
                    159:        eflag = TRUE;
                    160:        addlist( elist , *sp );
                    161:     }
                    162:        /*
                    163:         *      get information about a.out file.
                    164:         */
                    165:     getnfile();
                    166:        /*
                    167:         *      get information about mon.out file(s).
                    168:         */
                    169:     do {
                    170:        getpfile( gmonname );
                    171:        if ( *argv != 0 ) {
                    172:            gmonname = *argv;
                    173:        }
                    174:     } while ( *argv++ != 0 );
                    175:        /*
                    176:         *      how many ticks per second?
                    177:         *      if we can't tell, report time in ticks.
                    178:         */
                    179:     if (hz == 0) {
                    180:        hz = 1;
                    181:        fprintf(stderr, "time is in ticks, not seconds\n");
                    182:     }
                    183:        /*
                    184:         *      dump out a gmon.sum file if requested
                    185:         */
                    186:     if ( sflag ) {
                    187:        dumpsum( GMONSUM );
                    188:     }
                    189:        /*
                    190:         *      assign samples to procedures
                    191:         */
                    192:     asgnsamples();
                    193:        /*
                    194:         *      assemble the dynamic profile
                    195:         */
                    196:     timesortnlp = doarcs();
                    197:        /*
                    198:         *      print the dynamic profile
                    199:         */
                    200:     printgprof( timesortnlp );
                    201:        /*
                    202:         *      print the flat profile
                    203:         */
                    204:     printprof();
                    205:        /*
                    206:         *      print the index
                    207:         */
                    208:     printindex();
                    209:     done();
                    210: }
                    211:
                    212:     /*
                    213:      * Set up string and symbol tables from a.out.
                    214:      * and optionally the text space.
                    215:      * On return symbol table is sorted by value.
                    216:      */
                    217: getnfile()
                    218: {
                    219:     FILE       *nfile;
                    220:     int                valcmp();
                    221:
                    222:     nfile = fopen( a_outname ,"r");
                    223:     if (nfile == NULL) {
                    224:        perror( a_outname );
                    225:        done();
                    226:     }
                    227:     fread(&xbuf, 1, sizeof(xbuf), nfile);
                    228:     if (N_BADMAG(xbuf)) {
                    229:        fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname );
                    230:        done();
                    231:     }
                    232:     getstrtab(nfile);
                    233:     getsymtab(nfile);
                    234:     gettextspace( nfile );
                    235:     qsort(nl, nname, sizeof(nltype), valcmp);
                    236:     fclose(nfile);
                    237: #   ifdef DEBUG
                    238:        if ( debug & AOUTDEBUG ) {
                    239:            register int j;
                    240:
                    241:            for (j = 0; j < nname; j++){
                    242:                printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name);
                    243:            }
                    244:        }
                    245: #   endif DEBUG
                    246: }
                    247:
                    248: getstrtab(nfile)
                    249:     FILE       *nfile;
                    250: {
                    251:
                    252:     fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0);
                    253:     if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) {
                    254:        fprintf(stderr, "%s: %s: no string table (old format?)\n" ,
                    255:                whoami , a_outname );
                    256:        done();
                    257:     }
                    258:     strtab = calloc(ssiz, 1);
                    259:     if (strtab == NULL) {
                    260:        fprintf(stderr, "%s: %s: no room for %d bytes of string table\n",
                    261:                whoami , a_outname , ssiz);
                    262:        done();
                    263:     }
                    264:     if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) {
                    265:        fprintf(stderr, "%s: %s: error reading string table\n",
                    266:                whoami , a_outname );
                    267:        done();
                    268:     }
                    269: }
                    270:
                    271:     /*
                    272:      * Read in symbol table
                    273:      */
                    274: getsymtab(nfile)
                    275:     FILE       *nfile;
                    276: {
                    277:     register long      i;
                    278:     int                        askfor;
                    279:     struct nlist       nbuf;
                    280:
                    281:     /* pass1 - count symbols */
                    282:     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
                    283:     nname = 0;
                    284:     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
                    285:        fread(&nbuf, sizeof(nbuf), 1, nfile);
                    286:        if ( ! funcsymbol( &nbuf ) ) {
                    287:            continue;
                    288:        }
                    289:        nname++;
                    290:     }
                    291:     if (nname == 0) {
                    292:        fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname );
                    293:        done();
                    294:     }
                    295:     askfor = nname + 1;
                    296:     nl = (nltype *) calloc( askfor , sizeof(nltype) );
                    297:     if (nl == 0) {
                    298:        fprintf(stderr, "%s: No room for %d bytes of symbol table\n",
                    299:                whoami, askfor * sizeof(nltype) );
                    300:        done();
                    301:     }
                    302:
                    303:     /* pass2 - read symbols */
                    304:     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
                    305:     npe = nl;
                    306:     nname = 0;
                    307:     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
                    308:        fread(&nbuf, sizeof(nbuf), 1, nfile);
                    309:        if ( ! funcsymbol( &nbuf ) ) {
                    310: #          ifdef DEBUG
                    311:                if ( debug & AOUTDEBUG ) {
                    312:                    printf( "[getsymtab] rejecting: 0x%x %s\n" ,
                    313:                            nbuf.n_type , strtab + nbuf.n_un.n_strx );
                    314:                }
                    315: #          endif DEBUG
                    316:            continue;
                    317:        }
                    318:        npe->value = nbuf.n_value;
                    319:        npe->name = strtab+nbuf.n_un.n_strx;
                    320: #      ifdef DEBUG
                    321:            if ( debug & AOUTDEBUG ) {
                    322:                printf( "[getsymtab] %d %s 0x%08x\n" ,
                    323:                        nname , npe -> name , npe -> value );
                    324:            }
                    325: #      endif DEBUG
                    326:        npe++;
                    327:        nname++;
                    328:     }
                    329:     npe->value = -1;
                    330: }
                    331:
                    332:     /*
                    333:      * read in the text space of an a.out file
                    334:      */
                    335: gettextspace( nfile )
                    336:     FILE       *nfile;
                    337: {
                    338:
                    339:     if ( cflag == 0 ) {
                    340:        return;
                    341:     }
                    342:     textspace = (u_char *) malloc( xbuf.a_text );
                    343:     if ( textspace == 0 ) {
                    344:        fprintf( stderr , "%s: ran out room for %d bytes of text space:  " ,
                    345:                        whoami , xbuf.a_text );
                    346:        fprintf( stderr , "can't do -c\n" );
                    347:        return;
                    348:     }
                    349:     (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 );
                    350:     if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) {
                    351:        fprintf( stderr , "%s: couldn't read text space:  " , whoami );
                    352:        fprintf( stderr , "can't do -c\n" );
                    353:        free( textspace );
                    354:        textspace = 0;
                    355:        return;
                    356:     }
                    357: }
                    358:     /*
                    359:      * information from a gmon.out file is in two parts:
                    360:      * an array of sampling hits within pc ranges,
                    361:      * and the arcs.
                    362:      */
                    363: getpfile(filename)
                    364:     char *filename;
                    365: {
                    366:     FILE               *pfile;
                    367:     FILE               *openpfile();
                    368:     struct rawarc      arc;
                    369:
                    370:     pfile = openpfile(filename);
                    371:     readsamples(pfile);
                    372:        /*
                    373:         *      the rest of the file consists of
                    374:         *      a bunch of <from,self,count> tuples.
                    375:         */
                    376:     while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) {
                    377: #      ifdef DEBUG
                    378:            if ( debug & SAMPLEDEBUG ) {
                    379:                printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" ,
                    380:                        arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
                    381:            }
                    382: #      endif DEBUG
                    383:            /*
                    384:             *  add this arc
                    385:             */
                    386:        tally( &arc );
                    387:     }
                    388:     fclose(pfile);
                    389: }
                    390:
                    391: FILE *
                    392: openpfile(filename)
                    393:     char *filename;
                    394: {
                    395:     struct gmonhdr     tmp;
                    396:     FILE               *pfile;
                    397:     int                        size;
                    398:     int                        rate;
                    399:
                    400:     if((pfile = fopen(filename, "r")) == NULL) {
                    401:        perror(filename);
                    402:        done();
                    403:     }
                    404:     fread(&tmp, sizeof(struct gmonhdr), 1, pfile);
                    405:     if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc ||
                    406:         tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) {
                    407:        fprintf(stderr, "%s: incompatible with first gmon file\n", filename);
                    408:        done();
                    409:     }
                    410:     gmonhdr = tmp;
                    411:     if ( gmonhdr.version == GMONVERSION ) {
                    412:        rate = gmonhdr.profrate;
                    413:        size = sizeof(struct gmonhdr);
                    414:     } else {
                    415:        fseek(pfile, sizeof(struct ophdr), SEEK_SET);
                    416:        size = sizeof(struct ophdr);
                    417:        gmonhdr.profrate = rate = hertz();
                    418:        gmonhdr.version = GMONVERSION;
                    419:     }
                    420:     if (hz == 0) {
                    421:        hz = rate;
                    422:     } else if (hz != rate) {
                    423:        fprintf(stderr,
                    424:            "%s: profile clock rate (%d) %s (%d) in first gmon file\n",
                    425:            filename, rate, "incompatible with clock rate", hz);
                    426:        done();
                    427:     }
                    428:     s_lowpc = (unsigned long) gmonhdr.lpc;
                    429:     s_highpc = (unsigned long) gmonhdr.hpc;
                    430:     lowpc = (unsigned long)gmonhdr.lpc / sizeof(UNIT);
                    431:     highpc = (unsigned long)gmonhdr.hpc / sizeof(UNIT);
                    432:     sampbytes = gmonhdr.ncnt - size;
                    433:     nsamples = sampbytes / sizeof (UNIT);
                    434: #   ifdef DEBUG
                    435:        if ( debug & SAMPLEDEBUG ) {
                    436:            printf( "[openpfile] hdr.lpc 0x%x hdr.hpc 0x%x hdr.ncnt %d\n",
                    437:                gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt );
                    438:            printf( "[openpfile]   s_lowpc 0x%x   s_highpc 0x%x\n" ,
                    439:                s_lowpc , s_highpc );
                    440:            printf( "[openpfile]     lowpc 0x%x     highpc 0x%x\n" ,
                    441:                lowpc , highpc );
                    442:            printf( "[openpfile] sampbytes %d nsamples %d\n" ,
                    443:                sampbytes , nsamples );
                    444:            printf( "[openpfile] sample rate %d\n" , hz );
                    445:        }
                    446: #   endif DEBUG
                    447:     return(pfile);
                    448: }
                    449:
                    450: tally( rawp )
                    451:     struct rawarc      *rawp;
                    452: {
                    453:     nltype             *parentp;
                    454:     nltype             *childp;
                    455:
                    456:     parentp = nllookup( rawp -> raw_frompc );
                    457:     childp = nllookup( rawp -> raw_selfpc );
                    458:     if ( parentp == 0 || childp == 0 )
                    459:        return;
                    460:     if ( kflag
                    461:         && onlist( kfromlist , parentp -> name )
                    462:         && onlist( ktolist , childp -> name ) ) {
                    463:        return;
                    464:     }
                    465:     childp -> ncall += rawp -> raw_count;
                    466: #   ifdef DEBUG
                    467:        if ( debug & TALLYDEBUG ) {
                    468:            printf( "[tally] arc from %s to %s traversed %d times\n" ,
                    469:                    parentp -> name , childp -> name , rawp -> raw_count );
                    470:        }
                    471: #   endif DEBUG
                    472:     addarc( parentp , childp , rawp -> raw_count );
                    473: }
                    474:
                    475: /*
                    476:  * dump out the gmon.sum file
                    477:  */
                    478: dumpsum( sumfile )
                    479:     char *sumfile;
                    480: {
                    481:     register nltype *nlp;
                    482:     register arctype *arcp;
                    483:     struct rawarc arc;
                    484:     FILE *sfile;
                    485:
                    486:     if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) {
                    487:        perror( sumfile );
                    488:        done();
                    489:     }
                    490:     /*
                    491:      * dump the header; use the last header read in
                    492:      */
                    493:     if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) {
                    494:        perror( sumfile );
                    495:        done();
                    496:     }
                    497:     /*
                    498:      * dump the samples
                    499:      */
                    500:     if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) {
                    501:        perror( sumfile );
                    502:        done();
                    503:     }
                    504:     /*
                    505:      * dump the normalized raw arc information
                    506:      */
                    507:     for ( nlp = nl ; nlp < npe ; nlp++ ) {
                    508:        for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
                    509:            arc.raw_frompc = arcp -> arc_parentp -> value;
                    510:            arc.raw_selfpc = arcp -> arc_childp -> value;
                    511:            arc.raw_count = arcp -> arc_count;
                    512:            if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) {
                    513:                perror( sumfile );
                    514:                done();
                    515:            }
                    516: #          ifdef DEBUG
                    517:                if ( debug & SAMPLEDEBUG ) {
                    518:                    printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" ,
                    519:                            arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
                    520:                }
                    521: #          endif DEBUG
                    522:        }
                    523:     }
                    524:     fclose( sfile );
                    525: }
                    526:
                    527: valcmp(p1, p2)
                    528:     nltype *p1, *p2;
                    529: {
                    530:     if ( p1 -> value < p2 -> value ) {
                    531:        return LESSTHAN;
                    532:     }
                    533:     if ( p1 -> value > p2 -> value ) {
                    534:        return GREATERTHAN;
                    535:     }
                    536:     return EQUALTO;
                    537: }
                    538:
                    539: readsamples(pfile)
                    540:     FILE       *pfile;
                    541: {
                    542:     register i;
                    543:     UNIT       sample;
                    544:
                    545:     if (samples == 0) {
                    546:        samples = (UNIT *) calloc(sampbytes, sizeof (UNIT));
                    547:        if (samples == 0) {
                    548:            fprintf( stderr , "%s: No room for %d sample pc's\n",
                    549:                whoami , sampbytes / sizeof (UNIT));
                    550:            done();
                    551:        }
                    552:     }
                    553:     for (i = 0; i < nsamples; i++) {
                    554:        fread(&sample, sizeof (UNIT), 1, pfile);
                    555:        if (feof(pfile))
                    556:                break;
                    557:        samples[i] += sample;
                    558:     }
                    559:     if (i != nsamples) {
                    560:        fprintf(stderr,
                    561:            "%s: unexpected EOF after reading %d/%d samples\n",
1.6     ! aaron     562:                whoami , i , nsamples );
1.1       deraadt   563:        done();
                    564:     }
                    565: }
                    566:
                    567: /*
                    568:  *     Assign samples to the procedures to which they belong.
                    569:  *
                    570:  *     There are three cases as to where pcl and pch can be
                    571:  *     with respect to the routine entry addresses svalue0 and svalue1
                    572:  *     as shown in the following diagram.  overlap computes the
                    573:  *     distance between the arrows, the fraction of the sample
                    574:  *     that is to be credited to the routine which starts at svalue0.
                    575:  *
                    576:  *         svalue0                                         svalue1
                    577:  *            |                                               |
                    578:  *            v                                               v
                    579:  *
                    580:  *            +-----------------------------------------------+
                    581:  *            |                                               |
                    582:  *       |  ->|    |<-         ->|         |<-         ->|    |<-  |
                    583:  *       |         |             |         |             |         |
                    584:  *       +---------+             +---------+             +---------+
                    585:  *
                    586:  *       ^         ^             ^         ^             ^         ^
                    587:  *       |         |             |         |             |         |
                    588:  *      pcl       pch           pcl       pch           pcl       pch
                    589:  *
                    590:  *     For the vax we assert that samples will never fall in the first
                    591:  *     two bytes of any routine, since that is the entry mask,
                    592:  *     thus we give call alignentries() to adjust the entry points if
                    593:  *     the entry mask falls in one bucket but the code for the routine
                    594:  *     doesn't start until the next bucket.  In conjunction with the
                    595:  *     alignment of routine addresses, this should allow us to have
                    596:  *     only one sample for every four bytes of text space and never
                    597:  *     have any overlap (the two end cases, above).
                    598:  */
                    599: asgnsamples()
                    600: {
                    601:     register int       j;
                    602:     UNIT               ccnt;
                    603:     double             time;
                    604:     unsigned long      pcl, pch;
                    605:     register int       i;
                    606:     unsigned long      overlap;
                    607:     unsigned long      svalue0, svalue1;
                    608:
                    609:     /* read samples and assign to namelist symbols */
                    610:     scale = highpc - lowpc;
                    611:     scale /= nsamples;
                    612:     alignentries();
                    613:     for (i = 0, j = 1; i < nsamples; i++) {
                    614:        ccnt = samples[i];
                    615:        if (ccnt == 0)
                    616:                continue;
                    617:        pcl = lowpc + scale * i;
                    618:        pch = lowpc + scale * (i + 1);
                    619:        time = ccnt;
                    620: #      ifdef DEBUG
                    621:            if ( debug & SAMPLEDEBUG ) {
                    622:                printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" ,
                    623:                        pcl , pch , ccnt );
                    624:            }
                    625: #      endif DEBUG
                    626:        totime += time;
                    627:        for (j = j - 1; j < nname; j++) {
                    628:            svalue0 = nl[j].svalue;
                    629:            svalue1 = nl[j+1].svalue;
                    630:                /*
                    631:                 *      if high end of tick is below entry address,
                    632:                 *      go for next tick.
                    633:                 */
                    634:            if (pch < svalue0)
                    635:                    break;
                    636:                /*
                    637:                 *      if low end of tick into next routine,
                    638:                 *      go for next routine.
                    639:                 */
                    640:            if (pcl >= svalue1)
                    641:                    continue;
                    642:            overlap = min(pch, svalue1) - max(pcl, svalue0);
                    643:            if (overlap > 0) {
                    644: #              ifdef DEBUG
                    645:                    if (debug & SAMPLEDEBUG) {
                    646:                        printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n",
                    647:                                nl[j].value/sizeof(UNIT), svalue0, svalue1,
                    648:                                nl[j].name,
                    649:                                overlap * time / scale, overlap);
                    650:                    }
                    651: #              endif DEBUG
                    652:                nl[j].time += overlap * time / scale;
                    653:            }
                    654:        }
                    655:     }
                    656: #   ifdef DEBUG
                    657:        if (debug & SAMPLEDEBUG) {
                    658:            printf("[asgnsamples] totime %f\n", totime);
                    659:        }
                    660: #   endif DEBUG
                    661: }
                    662:
                    663:
                    664: unsigned long
                    665: min(a, b)
                    666:     unsigned long a,b;
                    667: {
                    668:     if (a<b)
                    669:        return(a);
                    670:     return(b);
                    671: }
                    672:
                    673: unsigned long
                    674: max(a, b)
                    675:     unsigned long a,b;
                    676: {
                    677:     if (a>b)
                    678:        return(a);
                    679:     return(b);
                    680: }
                    681:
                    682:     /*
                    683:      * calculate scaled entry point addresses (to save time in asgnsamples),
                    684:      * and possibly push the scaled entry points over the entry mask,
                    685:      * if it turns out that the entry point is in one bucket and the code
                    686:      * for a routine is in the next bucket.
                    687:      */
                    688: alignentries()
                    689: {
                    690:     register struct nl *nlp;
                    691:     unsigned long      bucket_of_entry;
                    692:     unsigned long      bucket_of_code;
                    693:
                    694:     for (nlp = nl; nlp < npe; nlp++) {
                    695:        nlp -> svalue = nlp -> value / sizeof(UNIT);
                    696:        bucket_of_entry = (nlp->svalue - lowpc) / scale;
                    697:        bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale;
                    698:        if (bucket_of_entry < bucket_of_code) {
                    699: #          ifdef DEBUG
                    700:                if (debug & SAMPLEDEBUG) {
                    701:                    printf("[alignentries] pushing svalue 0x%x to 0x%x\n",
                    702:                            nlp->svalue, nlp->svalue + UNITS_TO_CODE);
                    703:                }
                    704: #          endif DEBUG
                    705:            nlp->svalue += UNITS_TO_CODE;
                    706:        }
                    707:     }
                    708: }
                    709:
                    710: bool
                    711: funcsymbol( nlistp )
                    712:     struct nlist       *nlistp;
                    713: {
                    714:     extern char        *strtab;        /* string table from a.out */
                    715:     extern int aflag;          /* if static functions aren't desired */
                    716:     char       *name, c;
                    717:
                    718:        /*
                    719:         *      must be a text symbol,
                    720:         *      and static text symbols don't qualify if aflag set.
                    721:         */
                    722:     if ( ! (  ( nlistp -> n_type == ( N_TEXT | N_EXT ) )
                    723:           || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) {
                    724:        return FALSE;
                    725:     }
                    726:        /*
                    727:         *      can't have any `funny' characters in name,
1.4       deraadt   728:         *      where `funny' means `.', .o file names
1.1       deraadt   729:         *      need to make an exception for sparc .mul & co.
                    730:         *      perhaps we should just drop this code entirely...
                    731:         */
                    732:     name = strtab + nlistp -> n_un.n_strx;
1.5       deraadt   733: #ifdef __sparc__
1.1       deraadt   734:     if (nlistp -> n_value & 3)
                    735:        return FALSE;
                    736:     if ( *name == '.' ) {
                    737:        char *p = name + 1;
                    738:        if ( *p == 'u' )
                    739:            p++;
                    740:        if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 ||
                    741:             strcmp ( p, "rem" ) == 0 )
                    742:                return TRUE;
                    743:     }
                    744: #endif
                    745:     while ( c = *name++ ) {
1.4       deraadt   746:        if ( c == '.' ) {
1.1       deraadt   747:            return FALSE;
                    748:        }
                    749:     }
                    750:     return TRUE;
                    751: }
                    752:
                    753: done()
                    754: {
                    755:
                    756:     exit(0);
                    757: }