X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/06ac0fb1b79423d128f012c3a6f2cc2963e35d48..1f096eb2af98e1c908d9a84ed3e9c95b81d4751d:/usr/src/usr.bin/gprof/gprof.c diff --git a/usr/src/usr.bin/gprof/gprof.c b/usr/src/usr.bin/gprof/gprof.c index adceb86df9..3868583d0a 100644 --- a/usr/src/usr.bin/gprof/gprof.c +++ b/usr/src/usr.bin/gprof/gprof.c @@ -1,30 +1,74 @@ #ifndef lint - static char *sccsid = "@(#)gprof.c 1.4 (Berkeley) %G%"; + static char *sccsid = "@(#)gprof.c 1.18 (Berkeley) %G%"; #endif lint #include "gprof.h" +char *whoami = "gprof"; + + /* + * things which get -E excluded by default. + */ +char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; + main(argc, argv) - int argc; - char **argv; + int argc; + char **argv; { + char **sp; --argc; argv++; debug = 0; while ( *argv != 0 && **argv == '-' ) { (*argv)++; - if ( **argv == 'd' ) { + switch ( **argv ) { + case 'a': + aflag = TRUE; + break; + case 'b': + bflag = TRUE; + break; + case 'c': + cflag = TRUE; + break; + case 'd': + dflag = TRUE; (*argv)++; debug |= atoi( *argv ); debug |= ANYDEBUG; # ifdef DEBUG printf( "[main] debug = %d\n" , debug ); # endif DEBUG - } else if ( **argv == 'z' ) { - zflg++; - } else if ( **argv == 'c' ) { - cflag++; + break; + case 'E': + ++argv; + addlist( Elist , *argv ); + Eflag = TRUE; + addlist( elist , *argv ); + eflag = TRUE; + break; + case 'e': + addlist( elist , *++argv ); + eflag = TRUE; + break; + case 'F': + ++argv; + addlist( Flist , *argv ); + Fflag = TRUE; + addlist( flist , *argv ); + fflag = TRUE; + break; + case 'f': + addlist( flist , *++argv ); + fflag = TRUE; + break; + case 's': + sflag = TRUE; + break; + case 'z': + zflag = TRUE; + break; } argv++; } @@ -39,6 +83,15 @@ main(argc, argv) argv++; } else { gmonname = GMONNAME; + } + /* + * turn off default functions + */ + for ( sp = &defaultEs[0] ; *sp ; sp++ ) { + Eflag = TRUE; + addlist( Elist , *sp ); + eflag = TRUE; + addlist( elist , *sp ); } /* * get information about a.out file. @@ -47,7 +100,18 @@ main(argc, argv) /* * get information about mon.out file(s). */ - getpfile( gmonname ); + do { + getpfile( gmonname ); + if ( *argv != 0 ) { + gmonname = *argv; + } + } while ( *argv++ != 0 ); + /* + * dump out a gmon.sum file if requested + */ + if ( sflag ) { + dumpsum( GMONSUM ); + } /* * assign samples to procedures */ @@ -63,11 +127,11 @@ main(argc, argv) done(); } -/* - * Set up string and symbol tables from a.out. - * and optionally the text space. - * On return symbol table is sorted by value. - */ + /* + * Set up string and symbol tables from a.out. + * and optionally the text space. + * On return symbol table is sorted by value. + */ getnfile() { FILE *nfile; @@ -79,7 +143,7 @@ getnfile() } fread(&xbuf, 1, sizeof(xbuf), nfile); if (N_BADMAG(xbuf)) { - fprintf(stderr, "%s: bad format\n", a_outname ); + fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); done(); } getstrtab(nfile); @@ -104,17 +168,19 @@ getstrtab(nfile) fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { - fprintf(stderr, "%s: no string table (old format?)\n", a_outname ); + fprintf(stderr, "%s: %s: no string table (old format?)\n" , + whoami , a_outname ); done(); } strtab = (char *)calloc(ssiz, 1); if (strtab == NULL) { - fprintf(stderr, "%s: no room for %d bytes of string table", - a_outname , ssiz); + fprintf(stderr, "%s: %s: no room for %d bytes of string table", + whoami , a_outname , ssiz); done(); } if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { - fprintf(stderr, "%s: error reading string table\n", a_outname ); + fprintf(stderr, "%s: %s: error reading string table\n", + whoami , a_outname ); done(); } } @@ -134,27 +200,20 @@ getsymtab(nfile) nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); - if ( nbuf.n_type != N_TEXT+N_EXT ) { + if ( ! funcsymbol( &nbuf ) ) { continue; } nname++; } if (nname == 0) { - fprintf(stderr, "%s: no symbols\n", a_outname ); + fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); done(); } - /* - * ask also for CYCLEFRACTION extra namelist entries for - * cycle entries. these hide out at the end of the namelist - * and aren't accessed unless the whole namelist (nname+ncycles) - * is sorted and searched. - */ - ncycles = nname * CYCLEFRACTION; - askfor = nname + 1 + ncycles; + askfor = nname + 1; nl = (nltype *) calloc( askfor , sizeof(nltype) ); if (nl == 0) { - fprintf(stderr, "prof: No room for %d bytes of symbol table\n", - askfor * sizeof(nltype) ); + fprintf(stderr, "%s: No room for %d bytes of symbol table\n", + whoami, askfor * sizeof(nltype) ); done(); } @@ -164,7 +223,13 @@ getsymtab(nfile) nname = 0; for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { fread(&nbuf, sizeof(nbuf), 1, nfile); - if ( nbuf.n_type != N_TEXT+N_EXT ) { + if ( ! funcsymbol( &nbuf ) ) { +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + printf( "[getsymtab] rejecting: 0x%x %s\n" , + nbuf.n_type , strtab + nbuf.n_un.n_strx ); + } +# endif DEBUG continue; } npe->value = nbuf.n_value; @@ -195,14 +260,15 @@ gettextspace( nfile ) } textspace = malloc( xbuf.a_text ); if ( textspace == 0 ) { - fprintf( stderr , "gprof: ran out room for %d bytes of text space: " ); - fprintf( stderr , "can't do -c\n" , xbuf.a_text ); + fprintf( stderr , "%s: ran out room for %d bytes of text space: " , + whoami , xbuf.a_text ); + fprintf( stderr , "can't do -c\n" ); return; } (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { - fprintf( stderr , "couldn't read text space: " ); - fprintf( stderr , "can't do -c\n" , xbuf.a_text ); + fprintf( stderr , "%s: couldn't read text space: " , whoami ); + fprintf( stderr , "can't do -c\n" ); free( textspace ); textspace = 0; return; @@ -241,22 +307,42 @@ getpfile(filename) fclose(pfile); } -FILE *openpfile(filename) +FILE * +openpfile(filename) char *filename; { + struct hdr tmp; FILE *pfile; if((pfile = fopen(filename, "r")) == NULL) { perror(filename); done(); } - fread(&h, sizeof(struct hdr), 1, pfile); + fread(&tmp, sizeof(struct hdr), 1, pfile); + if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || + tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { + fprintf(stderr, "%s: incompatible with first gmon file\n", filename); + done(); + } + h = tmp; s_lowpc = (unsigned long) h.lowpc; s_highpc = (unsigned long) h.highpc; - lowpc = h.lowpc - (UNIT *)0; - highpc = h.highpc - (UNIT *)0; + lowpc = (unsigned long)h.lowpc / sizeof(UNIT); + highpc = (unsigned long)h.highpc / sizeof(UNIT); sampbytes = h.ncnt - sizeof(struct hdr); nsamples = sampbytes / sizeof (unsigned UNIT); +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", + h.lowpc , h.highpc , h.ncnt ); + printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , + s_lowpc , s_highpc ); + printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , + lowpc , highpc ); + printf( "[openpfile] sampbytes %d nsamples %d\n" , + sampbytes , nsamples ); + } +# endif DEBUG return(pfile); } @@ -278,6 +364,58 @@ tally( rawp ) addarc( parentp , childp , rawp -> raw_count ); } +/* + * dump out the gmon.sum file + */ +dumpsum( sumfile ) + char *sumfile; +{ + register nltype *nlp; + register arctype *arcp; + struct rawarc arc; + FILE *sfile; + + if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { + perror( sumfile ); + done(); + } + /* + * dump the header; use the last header read in + */ + if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { + perror( sumfile ); + done(); + } + /* + * dump the samples + */ + if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) { + perror( sumfile ); + done(); + } + /* + * dump the normalized raw arc information + */ + for ( nlp = nl ; nlp < npe - 1 ; nlp++ ) { + for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + arc.raw_frompc = arcp -> arc_parentp -> value; + arc.raw_selfpc = arcp -> arc_childp -> value; + arc.raw_count = arcp -> arc_count; + if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { + perror( sumfile ); + done(); + } +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , + arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); + } +# endif DEBUG + } + } + fclose( sfile ); +} + valcmp(p1, p2) nltype *p1, *p2; { @@ -299,8 +437,8 @@ readsamples(pfile) if (samples == 0) { samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT)); if (samples == 0) { - fprintf( stderr , "prof: No room for %d sample pc's\n", - sampbytes / sizeof (unsigned UNIT)); + fprintf( stderr , "%s: No room for %d sample pc's\n", + whoami , sampbytes / sizeof (unsigned UNIT)); done(); } } @@ -312,8 +450,8 @@ readsamples(pfile) } if (i != nsamples) { fprintf(stderr, - "prof: unexpected EOF after reading %d/%d samples\n", - --i, nsamples); + "%s: unexpected EOF after reading %d/%d samples\n", + whoami , --i , nsamples ); done(); } } @@ -328,13 +466,13 @@ asgnsamples() double time; unsigned long pcl, pch; register int i; - int overlap; + unsigned long overlap; unsigned long svalue0, svalue1; /* read samples and assign to namelist symbols */ scale = highpc - lowpc; scale /= nsamples; - for (i=0; i < nsamples; i++) { + for (i = 0, j = 1; i < nsamples; i++) { ccnt = samples[i]; if (ccnt == 0) continue; @@ -343,12 +481,12 @@ asgnsamples() time = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { - printf( "[asgnsamples] ccnt %d time %f totime %f\n" , - ccnt , time , totime ); + printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , + pcl , pch , ccnt ); } # endif DEBUG totime += time; - for (j=0; j0) { # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { - printf( "[asgnsamples] %s gets %f ticks\n" , - nl[j].name , overlap*time/scale ); + printf( "[asgnsamples] (0x%x-0x%x) %s gets %f ticks\n" , + svalue0 , svalue1 , nl[j].name , + overlap*time/scale ); } # endif DEBUG nl[j].time += overlap*time/scale; @@ -372,29 +511,56 @@ asgnsamples() printf( "[asgnsamples] totime %f\n" , totime ); } # endif DEBUG - if (totime==0.0) { - fprintf( stderr , "No time accumulated\n" ); - totime=1.0; - } } +unsigned long min(a, b) - unsigned a,b; + unsigned long a,b; { if (ab) return(a); return(b); } +bool +funcsymbol( nlistp ) + struct nlist *nlistp; +{ + extern char *strtab; /* string table from a.out */ + extern int aflag; /* if static functions aren't desired */ + char *name; + + /* + * must be a text symbol, + * and static text symbols don't qualify if aflag set. + */ + if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) + || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { + return FALSE; + } + /* + * can't have any `funny' characters in name, + * where `funny' includes `.', .o file names + * and `$', pascal labels. + */ + for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { + if ( *name == '.' || *name == '$' ) { + return FALSE; + } + } + return TRUE; +} + done() {