121960Sdist /* 221960Sdist * Copyright (c) 1983 Regents of the University of California. 334199Sbostic * All rights reserved. 434199Sbostic * 5*42683Sbostic * %sccs.include.redist.c% 621960Sdist */ 721960Sdist 84510Speter #ifndef lint 921960Sdist char copyright[] = 1021960Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1121960Sdist All rights reserved.\n"; 1234199Sbostic #endif /* not lint */ 134510Speter 1421960Sdist #ifndef lint 15*42683Sbostic static char sccsid[] = "@(#)gprof.c 5.6 (Berkeley) 06/01/90"; 1634199Sbostic #endif /* not lint */ 1721960Sdist 184563Speter #include "gprof.h" 194510Speter 207128Speter char *whoami = "gprof"; 217128Speter 227223Speter /* 237223Speter * things which get -E excluded by default. 247223Speter */ 257223Speter char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; 267173Speter 274510Speter main(argc, argv) 287173Speter int argc; 297173Speter char **argv; 304510Speter { 317173Speter char **sp; 3216852Smckusick nltype **timesortnlp; 334510Speter 344510Speter --argc; 354510Speter argv++; 364510Speter debug = 0; 3712385Smckusick bflag = TRUE; 384510Speter while ( *argv != 0 && **argv == '-' ) { 394510Speter (*argv)++; 404866Smckusic switch ( **argv ) { 417173Speter case 'a': 427173Speter aflag = TRUE; 437173Speter break; 447173Speter case 'b': 4512385Smckusick bflag = FALSE; 467173Speter break; 477173Speter case 'c': 487173Speter cflag = TRUE; 497173Speter break; 504866Smckusic case 'd': 517173Speter dflag = TRUE; 524510Speter (*argv)++; 534510Speter debug |= atoi( *argv ); 544510Speter debug |= ANYDEBUG; 554510Speter # ifdef DEBUG 5611807Smckusick printf("[main] debug = %d\n", debug); 5711807Smckusick # else not DEBUG 5811807Smckusick printf("%s: -d ignored\n", whoami); 594510Speter # endif DEBUG 604866Smckusic break; 617223Speter case 'E': 627223Speter ++argv; 637223Speter addlist( Elist , *argv ); 647223Speter Eflag = TRUE; 657223Speter addlist( elist , *argv ); 667223Speter eflag = TRUE; 677223Speter break; 687173Speter case 'e': 697223Speter addlist( elist , *++argv ); 707173Speter eflag = TRUE; 714866Smckusic break; 727223Speter case 'F': 737223Speter ++argv; 747223Speter addlist( Flist , *argv ); 757223Speter Fflag = TRUE; 767223Speter addlist( flist , *argv ); 777223Speter fflag = TRUE; 787223Speter break; 797173Speter case 'f': 807223Speter addlist( flist , *++argv ); 817173Speter fflag = TRUE; 824866Smckusic break; 8330963Smckusick case 'k': 8430963Smckusick addlist( kfromlist , *++argv ); 8530963Smckusick addlist( ktolist , *++argv ); 8630963Smckusick kflag = TRUE; 8730963Smckusick break; 884866Smckusic case 's': 897173Speter sflag = TRUE; 904866Smckusic break; 914866Smckusic case 'z': 927173Speter zflag = TRUE; 934866Smckusic break; 944510Speter } 954510Speter argv++; 964510Speter } 974510Speter if ( *argv != 0 ) { 984510Speter a_outname = *argv; 994510Speter argv++; 1004510Speter } else { 1014510Speter a_outname = A_OUTNAME; 1024510Speter } 1034510Speter if ( *argv != 0 ) { 1044563Speter gmonname = *argv; 1054510Speter argv++; 1064510Speter } else { 1074563Speter gmonname = GMONNAME; 1084510Speter } 1094510Speter /* 1107173Speter * turn off default functions 1117173Speter */ 1127223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 1137223Speter Eflag = TRUE; 1147223Speter addlist( Elist , *sp ); 1157173Speter eflag = TRUE; 1167223Speter addlist( elist , *sp ); 1177173Speter } 1187173Speter /* 11915910Speter * how many ticks per second? 12015910Speter * if we can't tell, report time in ticks. 12110249Speter */ 12210249Speter hz = hertz(); 12315910Speter if (hz == 0) { 12415910Speter hz = 1; 12515910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 12615910Speter } 12710249Speter /* 1284510Speter * get information about a.out file. 1294510Speter */ 1304510Speter getnfile(); 1314510Speter /* 1324510Speter * get information about mon.out file(s). 1334510Speter */ 1344866Smckusic do { 1354866Smckusic getpfile( gmonname ); 1364866Smckusic if ( *argv != 0 ) { 1374866Smckusic gmonname = *argv; 1384866Smckusic } 1397128Speter } while ( *argv++ != 0 ); 1404510Speter /* 1414866Smckusic * dump out a gmon.sum file if requested 1424866Smckusic */ 1437128Speter if ( sflag ) { 1447128Speter dumpsum( GMONSUM ); 1457128Speter } 1464866Smckusic /* 1474510Speter * assign samples to procedures 1484510Speter */ 1494510Speter asgnsamples(); 1504510Speter /* 15116852Smckusick * assemble the dynamic profile 1524510Speter */ 15316852Smckusick timesortnlp = doarcs(); 15416852Smckusick /* 15516852Smckusick * print the dynamic profile 15616852Smckusick */ 15716852Smckusick printgprof( timesortnlp ); 15816852Smckusick /* 15916852Smckusick * print the flat profile 16016852Smckusick */ 1614510Speter printprof(); 1624510Speter /* 16316852Smckusick * print the index 1644510Speter */ 16516852Smckusick printindex(); 1664510Speter done(); 1674510Speter } 1684510Speter 1697128Speter /* 1707128Speter * Set up string and symbol tables from a.out. 1717128Speter * and optionally the text space. 1727128Speter * On return symbol table is sorted by value. 1737128Speter */ 1744510Speter getnfile() 1754510Speter { 1764510Speter FILE *nfile; 17733226Sbostic int valcmp(); 1784510Speter 1794510Speter nfile = fopen( a_outname ,"r"); 1804510Speter if (nfile == NULL) { 1814510Speter perror( a_outname ); 1824510Speter done(); 1834510Speter } 1844510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1854510Speter if (N_BADMAG(xbuf)) { 1867128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1874510Speter done(); 1884510Speter } 1894510Speter getstrtab(nfile); 1904510Speter getsymtab(nfile); 1914720Speter gettextspace( nfile ); 1924510Speter qsort(nl, nname, sizeof(nltype), valcmp); 1934510Speter fclose(nfile); 1944510Speter # ifdef DEBUG 1954510Speter if ( debug & AOUTDEBUG ) { 1964510Speter register int j; 1974510Speter 1984510Speter for (j = 0; j < nname; j++){ 1994510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 2004510Speter } 2014510Speter } 2024510Speter # endif DEBUG 2034510Speter } 2044510Speter 2054510Speter getstrtab(nfile) 2064510Speter FILE *nfile; 2074510Speter { 2084510Speter 2094510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 2104510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 2117128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 2127128Speter whoami , a_outname ); 2134510Speter done(); 2144510Speter } 2154510Speter strtab = (char *)calloc(ssiz, 1); 2164510Speter if (strtab == NULL) { 2177128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 2187128Speter whoami , a_outname , ssiz); 2194510Speter done(); 2204510Speter } 2214510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2227128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2237128Speter whoami , a_outname ); 2244510Speter done(); 2254510Speter } 2264510Speter } 2274510Speter 2284510Speter /* 2294510Speter * Read in symbol table 2304510Speter */ 2314510Speter getsymtab(nfile) 2324510Speter FILE *nfile; 2334510Speter { 2344510Speter register long i; 2354510Speter int askfor; 2364510Speter struct nlist nbuf; 2374510Speter 2384510Speter /* pass1 - count symbols */ 2394510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2404510Speter nname = 0; 2414510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2424510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2434845Speter if ( ! funcsymbol( &nbuf ) ) { 2444510Speter continue; 2454510Speter } 2464510Speter nname++; 2474510Speter } 2484510Speter if (nname == 0) { 2497128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2504510Speter done(); 2514510Speter } 2527128Speter askfor = nname + 1; 2534510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2544510Speter if (nl == 0) { 2557128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2567128Speter whoami, askfor * sizeof(nltype) ); 2574510Speter done(); 2584510Speter } 2594510Speter 2604510Speter /* pass2 - read symbols */ 2614510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2624510Speter npe = nl; 2634510Speter nname = 0; 2644510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2654510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2664845Speter if ( ! funcsymbol( &nbuf ) ) { 2674845Speter # ifdef DEBUG 2684845Speter if ( debug & AOUTDEBUG ) { 2694845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2704845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2714845Speter } 2724845Speter # endif DEBUG 2734510Speter continue; 2744510Speter } 2754510Speter npe->value = nbuf.n_value; 2764510Speter npe->name = strtab+nbuf.n_un.n_strx; 2774510Speter # ifdef DEBUG 2784510Speter if ( debug & AOUTDEBUG ) { 2794510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2804510Speter nname , npe -> name , npe -> value ); 2814510Speter } 2824510Speter # endif DEBUG 2834510Speter npe++; 2844510Speter nname++; 2854510Speter } 2864510Speter npe->value = -1; 2874510Speter } 2884510Speter 2894510Speter /* 2904720Speter * read in the text space of an a.out file 2914720Speter */ 2924720Speter gettextspace( nfile ) 2934720Speter FILE *nfile; 2944720Speter { 29533226Sbostic char *malloc(); 2964720Speter 2974720Speter if ( cflag == 0 ) { 2984720Speter return; 2994720Speter } 30033226Sbostic textspace = (u_char *) malloc( xbuf.a_text ); 3014720Speter if ( textspace == 0 ) { 3027128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 3037128Speter whoami , xbuf.a_text ); 3047128Speter fprintf( stderr , "can't do -c\n" ); 3054720Speter return; 3064720Speter } 3074720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 3084720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 3097128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 3107128Speter fprintf( stderr , "can't do -c\n" ); 3114720Speter free( textspace ); 3124720Speter textspace = 0; 3134720Speter return; 3144720Speter } 3154720Speter } 3164720Speter /* 3174563Speter * information from a gmon.out file is in two parts: 3184510Speter * an array of sampling hits within pc ranges, 3194510Speter * and the arcs. 3204510Speter */ 3214510Speter getpfile(filename) 3224510Speter char *filename; 3234510Speter { 3244510Speter FILE *pfile; 3254510Speter FILE *openpfile(); 3264510Speter struct rawarc arc; 3274510Speter 3284510Speter pfile = openpfile(filename); 3294510Speter readsamples(pfile); 3304510Speter /* 3314510Speter * the rest of the file consists of 3324510Speter * a bunch of <from,self,count> tuples. 3334510Speter */ 3344510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3354510Speter # ifdef DEBUG 3364510Speter if ( debug & SAMPLEDEBUG ) { 3374752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3384510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3394510Speter } 3404510Speter # endif DEBUG 3414510Speter /* 3424510Speter * add this arc 3434510Speter */ 3444510Speter tally( &arc ); 3454510Speter } 3464510Speter fclose(pfile); 3474510Speter } 3484510Speter 3494841Speter FILE * 3504841Speter openpfile(filename) 3514510Speter char *filename; 3524510Speter { 3534866Smckusic struct hdr tmp; 3544510Speter FILE *pfile; 3554510Speter 3564510Speter if((pfile = fopen(filename, "r")) == NULL) { 3574510Speter perror(filename); 3584510Speter done(); 3594510Speter } 3604866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3614866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3624866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3634866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3644866Smckusic done(); 3654866Smckusic } 3664866Smckusic h = tmp; 3674752Speter s_lowpc = (unsigned long) h.lowpc; 3684752Speter s_highpc = (unsigned long) h.highpc; 3697227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3707227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3714510Speter sampbytes = h.ncnt - sizeof(struct hdr); 37233226Sbostic nsamples = sampbytes / sizeof (UNIT); 3737226Speter # ifdef DEBUG 3747226Speter if ( debug & SAMPLEDEBUG ) { 3757226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3767226Speter h.lowpc , h.highpc , h.ncnt ); 3777226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3787226Speter s_lowpc , s_highpc ); 3797226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3807226Speter lowpc , highpc ); 3817226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3827226Speter sampbytes , nsamples ); 3837226Speter } 3847226Speter # endif DEBUG 3854510Speter return(pfile); 3864510Speter } 3874510Speter 3884510Speter tally( rawp ) 3894510Speter struct rawarc *rawp; 3904510Speter { 3914510Speter nltype *parentp; 3924510Speter nltype *childp; 3934510Speter 3944510Speter parentp = nllookup( rawp -> raw_frompc ); 3954510Speter childp = nllookup( rawp -> raw_selfpc ); 39630963Smckusick if ( kflag 39730963Smckusick && onlist( kfromlist , parentp -> name ) 39830963Smckusick && onlist( ktolist , childp -> name ) ) { 39930963Smckusick return; 40030963Smckusick } 4014510Speter childp -> ncall += rawp -> raw_count; 4024510Speter # ifdef DEBUG 4034510Speter if ( debug & TALLYDEBUG ) { 4044510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 4054510Speter parentp -> name , childp -> name , rawp -> raw_count ); 4064510Speter } 4074510Speter # endif DEBUG 4084720Speter addarc( parentp , childp , rawp -> raw_count ); 4094510Speter } 4104510Speter 4114866Smckusic /* 4124866Smckusic * dump out the gmon.sum file 4134866Smckusic */ 4144866Smckusic dumpsum( sumfile ) 4154866Smckusic char *sumfile; 4164866Smckusic { 4174866Smckusic register nltype *nlp; 4184866Smckusic register arctype *arcp; 4194866Smckusic struct rawarc arc; 4204866Smckusic FILE *sfile; 4214866Smckusic 4224866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 4234866Smckusic perror( sumfile ); 4244866Smckusic done(); 4254866Smckusic } 4264866Smckusic /* 4274866Smckusic * dump the header; use the last header read in 4284866Smckusic */ 4294866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4304866Smckusic perror( sumfile ); 4314866Smckusic done(); 4324866Smckusic } 4334866Smckusic /* 4344866Smckusic * dump the samples 4354866Smckusic */ 43633226Sbostic if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 4374866Smckusic perror( sumfile ); 4384866Smckusic done(); 4394866Smckusic } 4404866Smckusic /* 4414866Smckusic * dump the normalized raw arc information 4424866Smckusic */ 44311807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4444866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4454866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4464866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4474866Smckusic arc.raw_count = arcp -> arc_count; 4484866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4494866Smckusic perror( sumfile ); 4504866Smckusic done(); 4514866Smckusic } 4524866Smckusic # ifdef DEBUG 4534866Smckusic if ( debug & SAMPLEDEBUG ) { 4544866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4554866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4564866Smckusic } 4574866Smckusic # endif DEBUG 4584866Smckusic } 4594866Smckusic } 4604866Smckusic fclose( sfile ); 4614866Smckusic } 4624866Smckusic 4634510Speter valcmp(p1, p2) 4644510Speter nltype *p1, *p2; 4654510Speter { 4664510Speter if ( p1 -> value < p2 -> value ) { 4674510Speter return LESSTHAN; 4684510Speter } 4694510Speter if ( p1 -> value > p2 -> value ) { 4704510Speter return GREATERTHAN; 4714510Speter } 4724510Speter return EQUALTO; 4734510Speter } 4744510Speter 4754510Speter readsamples(pfile) 4764510Speter FILE *pfile; 4774510Speter { 4784510Speter register i; 47933226Sbostic UNIT sample; 4804510Speter 4814510Speter if (samples == 0) { 48233226Sbostic samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 4834510Speter if (samples == 0) { 4847128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 48533226Sbostic whoami , sampbytes / sizeof (UNIT)); 4864510Speter done(); 4874510Speter } 4884510Speter } 4894510Speter for (i = 0; i < nsamples; i++) { 49033226Sbostic fread(&sample, sizeof (UNIT), 1, pfile); 4914510Speter if (feof(pfile)) 4924510Speter break; 4934510Speter samples[i] += sample; 4944510Speter } 4954510Speter if (i != nsamples) { 4964510Speter fprintf(stderr, 4977128Speter "%s: unexpected EOF after reading %d/%d samples\n", 4987128Speter whoami , --i , nsamples ); 4994510Speter done(); 5004510Speter } 5014510Speter } 5024510Speter 5034510Speter /* 50411523Smckusick * Assign samples to the procedures to which they belong. 50511523Smckusick * 50611523Smckusick * There are three cases as to where pcl and pch can be 50711523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 50811523Smckusick * as shown in the following diagram. overlap computes the 50911523Smckusick * distance between the arrows, the fraction of the sample 51011523Smckusick * that is to be credited to the routine which starts at svalue0. 51111523Smckusick * 51211523Smckusick * svalue0 svalue1 51311523Smckusick * | | 51411523Smckusick * v v 51511523Smckusick * 51611523Smckusick * +-----------------------------------------------+ 51711523Smckusick * | | 51811523Smckusick * | ->| |<- ->| |<- ->| |<- | 51911523Smckusick * | | | | | | 52011523Smckusick * +---------+ +---------+ +---------+ 52111523Smckusick * 52211523Smckusick * ^ ^ ^ ^ ^ ^ 52311523Smckusick * | | | | | | 52411523Smckusick * pcl pch pcl pch pcl pch 52511523Smckusick * 52611523Smckusick * For the vax we assert that samples will never fall in the first 52711807Smckusick * two bytes of any routine, since that is the entry mask, 52811807Smckusick * thus we give call alignentries() to adjust the entry points if 52911807Smckusick * the entry mask falls in one bucket but the code for the routine 53011807Smckusick * doesn't start until the next bucket. In conjunction with the 53111807Smckusick * alignment of routine addresses, this should allow us to have 53211807Smckusick * only one sample for every four bytes of text space and never 53311807Smckusick * have any overlap (the two end cases, above). 5344510Speter */ 5354510Speter asgnsamples() 5364510Speter { 5374510Speter register int j; 53833226Sbostic UNIT ccnt; 5394510Speter double time; 5404510Speter unsigned long pcl, pch; 5414510Speter register int i; 5424841Speter unsigned long overlap; 5434510Speter unsigned long svalue0, svalue1; 5444510Speter 5454510Speter /* read samples and assign to namelist symbols */ 5464510Speter scale = highpc - lowpc; 5474510Speter scale /= nsamples; 54811807Smckusick alignentries(); 5497257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5504510Speter ccnt = samples[i]; 5514510Speter if (ccnt == 0) 5524510Speter continue; 55311523Smckusick pcl = lowpc + scale * i; 55411523Smckusick pch = lowpc + scale * (i + 1); 5554510Speter time = ccnt; 5564510Speter # ifdef DEBUG 5574510Speter if ( debug & SAMPLEDEBUG ) { 5585072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5595072Smckusic pcl , pch , ccnt ); 5604510Speter } 5614510Speter # endif DEBUG 5624510Speter totime += time; 5637252Smckusick for (j = j - 1; j < nname; j++) { 56411807Smckusick svalue0 = nl[j].svalue; 56511807Smckusick svalue1 = nl[j+1].svalue; 56611807Smckusick /* 56711807Smckusick * if high end of tick is below entry address, 56811807Smckusick * go for next tick. 56911807Smckusick */ 5704510Speter if (pch < svalue0) 5714510Speter break; 57211807Smckusick /* 57311807Smckusick * if low end of tick into next routine, 57411807Smckusick * go for next routine. 57511807Smckusick */ 5764510Speter if (pcl >= svalue1) 5774510Speter continue; 57811807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 57911523Smckusick if (overlap > 0) { 5804510Speter # ifdef DEBUG 58111523Smckusick if (debug & SAMPLEDEBUG) { 58211807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 58311807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 58411807Smckusick nl[j].name, 58511807Smckusick overlap * time / scale, overlap); 5864510Speter } 5874510Speter # endif DEBUG 58811523Smckusick nl[j].time += overlap * time / scale; 5894510Speter } 5904510Speter } 5914510Speter } 5924510Speter # ifdef DEBUG 59311523Smckusick if (debug & SAMPLEDEBUG) { 59411523Smckusick printf("[asgnsamples] totime %f\n", totime); 5954510Speter } 5964510Speter # endif DEBUG 5974510Speter } 5984510Speter 5994510Speter 6004841Speter unsigned long 6014510Speter min(a, b) 6024841Speter unsigned long a,b; 6034510Speter { 6044510Speter if (a<b) 6054510Speter return(a); 6064510Speter return(b); 6074510Speter } 6084510Speter 6094841Speter unsigned long 6104510Speter max(a, b) 6114841Speter unsigned long a,b; 6124510Speter { 6134510Speter if (a>b) 6144510Speter return(a); 6154510Speter return(b); 6164510Speter } 6174510Speter 61811807Smckusick /* 61911807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 62011807Smckusick * and possibly push the scaled entry points over the entry mask, 62111807Smckusick * if it turns out that the entry point is in one bucket and the code 62211807Smckusick * for a routine is in the next bucket. 62311807Smckusick */ 62411807Smckusick alignentries() 62511807Smckusick { 62611807Smckusick register struct nl *nlp; 62711807Smckusick unsigned long bucket_of_entry; 62811807Smckusick unsigned long bucket_of_code; 62911807Smckusick 63011807Smckusick for (nlp = nl; nlp < npe; nlp++) { 63111807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 63211807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 63311807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 63411807Smckusick if (bucket_of_entry < bucket_of_code) { 63511807Smckusick # ifdef DEBUG 63611807Smckusick if (debug & SAMPLEDEBUG) { 63711807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 63811807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 63911807Smckusick } 64011807Smckusick # endif DEBUG 64111807Smckusick nlp->svalue += UNITS_TO_CODE; 64211807Smckusick } 64311807Smckusick } 64411807Smckusick } 64511807Smckusick 6464845Speter bool 6474845Speter funcsymbol( nlistp ) 6484845Speter struct nlist *nlistp; 6494845Speter { 6504845Speter extern char *strtab; /* string table from a.out */ 6514851Speter extern int aflag; /* if static functions aren't desired */ 6524845Speter char *name; 6534845Speter 6544845Speter /* 6554845Speter * must be a text symbol, 6564851Speter * and static text symbols don't qualify if aflag set. 6574845Speter */ 6584845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6594851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6604845Speter return FALSE; 6614845Speter } 6624845Speter /* 6637128Speter * can't have any `funny' characters in name, 6644845Speter * where `funny' includes `.', .o file names 6654845Speter * and `$', pascal labels. 6664845Speter */ 6674845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6684845Speter if ( *name == '.' || *name == '$' ) { 6694845Speter return FALSE; 6704845Speter } 6714845Speter } 6724845Speter return TRUE; 6734845Speter } 6744845Speter 6754510Speter done() 6764510Speter { 6774510Speter 6784510Speter exit(0); 6794510Speter } 680