121960Sdist /* 221960Sdist * Copyright (c) 1983 Regents of the University of California. 334199Sbostic * All rights reserved. 434199Sbostic * 542683Sbostic * %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*52812Smckusick static char sccsid[] = "@(#)gprof.c 5.10 (Berkeley) 03/02/92"; 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 27*52812Smckusick static struct phdr h; 28*52812Smckusick 294510Speter main(argc, argv) 307173Speter int argc; 317173Speter char **argv; 324510Speter { 337173Speter char **sp; 3416852Smckusick nltype **timesortnlp; 354510Speter 364510Speter --argc; 374510Speter argv++; 384510Speter debug = 0; 3912385Smckusick bflag = TRUE; 404510Speter while ( *argv != 0 && **argv == '-' ) { 414510Speter (*argv)++; 424866Smckusic switch ( **argv ) { 437173Speter case 'a': 447173Speter aflag = TRUE; 457173Speter break; 467173Speter case 'b': 4712385Smckusick bflag = FALSE; 487173Speter break; 4952650Smckusick case 'C': 5052650Smckusick Cflag = TRUE; 5152650Smckusick cyclethreshold = atoi( *++argv ); 5252650Smckusick break; 537173Speter case 'c': 5448700Sdonn #if defined(vax) || defined(tahoe) 557173Speter cflag = TRUE; 5648700Sdonn #else 5748700Sdonn fprintf(stderr, "gprof: -c isn't supported on this architecture yet\n"); 5848700Sdonn exit(1); 5948700Sdonn #endif 607173Speter break; 614866Smckusic case 'd': 627173Speter dflag = TRUE; 6352650Smckusick debug |= atoi( *++argv ); 644510Speter debug |= ANYDEBUG; 654510Speter # ifdef DEBUG 6611807Smckusick printf("[main] debug = %d\n", debug); 6711807Smckusick # else not DEBUG 6811807Smckusick printf("%s: -d ignored\n", whoami); 694510Speter # endif DEBUG 704866Smckusic break; 717223Speter case 'E': 727223Speter ++argv; 737223Speter addlist( Elist , *argv ); 747223Speter Eflag = TRUE; 757223Speter addlist( elist , *argv ); 767223Speter eflag = TRUE; 777223Speter break; 787173Speter case 'e': 797223Speter addlist( elist , *++argv ); 807173Speter eflag = TRUE; 814866Smckusic break; 827223Speter case 'F': 837223Speter ++argv; 847223Speter addlist( Flist , *argv ); 857223Speter Fflag = TRUE; 867223Speter addlist( flist , *argv ); 877223Speter fflag = TRUE; 887223Speter break; 897173Speter case 'f': 907223Speter addlist( flist , *++argv ); 917173Speter fflag = TRUE; 924866Smckusic break; 9330963Smckusick case 'k': 9430963Smckusick addlist( kfromlist , *++argv ); 9530963Smckusick addlist( ktolist , *++argv ); 9630963Smckusick kflag = TRUE; 9730963Smckusick break; 984866Smckusic case 's': 997173Speter sflag = TRUE; 1004866Smckusic break; 1014866Smckusic case 'z': 1027173Speter zflag = TRUE; 1034866Smckusic break; 1044510Speter } 1054510Speter argv++; 1064510Speter } 1074510Speter if ( *argv != 0 ) { 1084510Speter a_outname = *argv; 1094510Speter argv++; 1104510Speter } else { 1114510Speter a_outname = A_OUTNAME; 1124510Speter } 1134510Speter if ( *argv != 0 ) { 1144563Speter gmonname = *argv; 1154510Speter argv++; 1164510Speter } else { 1174563Speter gmonname = GMONNAME; 1184510Speter } 1194510Speter /* 1207173Speter * turn off default functions 1217173Speter */ 1227223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 1237223Speter Eflag = TRUE; 1247223Speter addlist( Elist , *sp ); 1257173Speter eflag = TRUE; 1267223Speter addlist( elist , *sp ); 1277173Speter } 1287173Speter /* 1294510Speter * get information about a.out file. 1304510Speter */ 1314510Speter getnfile(); 1324510Speter /* 1334510Speter * get information about mon.out file(s). 1344510Speter */ 1354866Smckusic do { 1364866Smckusic getpfile( gmonname ); 1374866Smckusic if ( *argv != 0 ) { 1384866Smckusic gmonname = *argv; 1394866Smckusic } 1407128Speter } while ( *argv++ != 0 ); 1414510Speter /* 142*52812Smckusick * how many ticks per second? 143*52812Smckusick * if we can't tell, report time in ticks. 144*52812Smckusick */ 145*52812Smckusick if (hz == 0) { 146*52812Smckusick hz = 1; 147*52812Smckusick fprintf(stderr, "time is in ticks, not seconds\n"); 148*52812Smckusick } 149*52812Smckusick /* 1504866Smckusic * dump out a gmon.sum file if requested 1514866Smckusic */ 1527128Speter if ( sflag ) { 1537128Speter dumpsum( GMONSUM ); 1547128Speter } 1554866Smckusic /* 1564510Speter * assign samples to procedures 1574510Speter */ 1584510Speter asgnsamples(); 1594510Speter /* 16016852Smckusick * assemble the dynamic profile 1614510Speter */ 16216852Smckusick timesortnlp = doarcs(); 16316852Smckusick /* 16416852Smckusick * print the dynamic profile 16516852Smckusick */ 16616852Smckusick printgprof( timesortnlp ); 16716852Smckusick /* 16816852Smckusick * print the flat profile 16916852Smckusick */ 1704510Speter printprof(); 1714510Speter /* 17216852Smckusick * print the index 1734510Speter */ 17416852Smckusick printindex(); 1754510Speter done(); 1764510Speter } 1774510Speter 1787128Speter /* 1797128Speter * Set up string and symbol tables from a.out. 1807128Speter * and optionally the text space. 1817128Speter * On return symbol table is sorted by value. 1827128Speter */ 1834510Speter getnfile() 1844510Speter { 1854510Speter FILE *nfile; 18633226Sbostic int valcmp(); 1874510Speter 1884510Speter nfile = fopen( a_outname ,"r"); 1894510Speter if (nfile == NULL) { 1904510Speter perror( a_outname ); 1914510Speter done(); 1924510Speter } 1934510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1944510Speter if (N_BADMAG(xbuf)) { 1957128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1964510Speter done(); 1974510Speter } 1984510Speter getstrtab(nfile); 1994510Speter getsymtab(nfile); 2004720Speter gettextspace( nfile ); 2014510Speter qsort(nl, nname, sizeof(nltype), valcmp); 2024510Speter fclose(nfile); 2034510Speter # ifdef DEBUG 2044510Speter if ( debug & AOUTDEBUG ) { 2054510Speter register int j; 2064510Speter 2074510Speter for (j = 0; j < nname; j++){ 2084510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 2094510Speter } 2104510Speter } 2114510Speter # endif DEBUG 2124510Speter } 2134510Speter 2144510Speter getstrtab(nfile) 2154510Speter FILE *nfile; 2164510Speter { 2174510Speter 2184510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 2194510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 2207128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 2217128Speter whoami , a_outname ); 2224510Speter done(); 2234510Speter } 2244510Speter strtab = (char *)calloc(ssiz, 1); 2254510Speter if (strtab == NULL) { 2267128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 2277128Speter whoami , a_outname , ssiz); 2284510Speter done(); 2294510Speter } 2304510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2317128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2327128Speter whoami , a_outname ); 2334510Speter done(); 2344510Speter } 2354510Speter } 2364510Speter 2374510Speter /* 2384510Speter * Read in symbol table 2394510Speter */ 2404510Speter getsymtab(nfile) 2414510Speter FILE *nfile; 2424510Speter { 2434510Speter register long i; 2444510Speter int askfor; 2454510Speter struct nlist nbuf; 2464510Speter 2474510Speter /* pass1 - count symbols */ 2484510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2494510Speter nname = 0; 2504510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2514510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2524845Speter if ( ! funcsymbol( &nbuf ) ) { 2534510Speter continue; 2544510Speter } 2554510Speter nname++; 2564510Speter } 2574510Speter if (nname == 0) { 2587128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2594510Speter done(); 2604510Speter } 2617128Speter askfor = nname + 1; 2624510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2634510Speter if (nl == 0) { 2647128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2657128Speter whoami, askfor * sizeof(nltype) ); 2664510Speter done(); 2674510Speter } 2684510Speter 2694510Speter /* pass2 - read symbols */ 2704510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2714510Speter npe = nl; 2724510Speter nname = 0; 2734510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2744510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2754845Speter if ( ! funcsymbol( &nbuf ) ) { 2764845Speter # ifdef DEBUG 2774845Speter if ( debug & AOUTDEBUG ) { 2784845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2794845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2804845Speter } 2814845Speter # endif DEBUG 2824510Speter continue; 2834510Speter } 2844510Speter npe->value = nbuf.n_value; 2854510Speter npe->name = strtab+nbuf.n_un.n_strx; 2864510Speter # ifdef DEBUG 2874510Speter if ( debug & AOUTDEBUG ) { 2884510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2894510Speter nname , npe -> name , npe -> value ); 2904510Speter } 2914510Speter # endif DEBUG 2924510Speter npe++; 2934510Speter nname++; 2944510Speter } 2954510Speter npe->value = -1; 2964510Speter } 2974510Speter 2984510Speter /* 2994720Speter * read in the text space of an a.out file 3004720Speter */ 3014720Speter gettextspace( nfile ) 3024720Speter FILE *nfile; 3034720Speter { 30433226Sbostic char *malloc(); 3054720Speter 3064720Speter if ( cflag == 0 ) { 3074720Speter return; 3084720Speter } 30933226Sbostic textspace = (u_char *) malloc( xbuf.a_text ); 3104720Speter if ( textspace == 0 ) { 3117128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 3127128Speter whoami , xbuf.a_text ); 3137128Speter fprintf( stderr , "can't do -c\n" ); 3144720Speter return; 3154720Speter } 3164720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 3174720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 3187128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 3197128Speter fprintf( stderr , "can't do -c\n" ); 3204720Speter free( textspace ); 3214720Speter textspace = 0; 3224720Speter return; 3234720Speter } 3244720Speter } 3254720Speter /* 3264563Speter * information from a gmon.out file is in two parts: 3274510Speter * an array of sampling hits within pc ranges, 3284510Speter * and the arcs. 3294510Speter */ 3304510Speter getpfile(filename) 3314510Speter char *filename; 3324510Speter { 3334510Speter FILE *pfile; 3344510Speter FILE *openpfile(); 3354510Speter struct rawarc arc; 3364510Speter 3374510Speter pfile = openpfile(filename); 3384510Speter readsamples(pfile); 3394510Speter /* 3404510Speter * the rest of the file consists of 3414510Speter * a bunch of <from,self,count> tuples. 3424510Speter */ 3434510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3444510Speter # ifdef DEBUG 3454510Speter if ( debug & SAMPLEDEBUG ) { 3464752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3474510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3484510Speter } 3494510Speter # endif DEBUG 3504510Speter /* 3514510Speter * add this arc 3524510Speter */ 3534510Speter tally( &arc ); 3544510Speter } 3554510Speter fclose(pfile); 3564510Speter } 3574510Speter 3584841Speter FILE * 3594841Speter openpfile(filename) 3604510Speter char *filename; 3614510Speter { 362*52812Smckusick struct phdr tmp; 363*52812Smckusick FILE *pfile; 364*52812Smckusick int size; 365*52812Smckusick int rate; 3664510Speter 3674510Speter if((pfile = fopen(filename, "r")) == NULL) { 3684510Speter perror(filename); 3694510Speter done(); 3704510Speter } 371*52812Smckusick fread(&tmp, sizeof(struct phdr), 1, pfile); 372*52812Smckusick if ( s_highpc != 0 && ( tmp.lpc != h.lpc || 373*52812Smckusick tmp.hpc != h.hpc || tmp.ncnt != h.ncnt ) ) { 3744866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3754866Smckusic done(); 3764866Smckusic } 3774866Smckusic h = tmp; 378*52812Smckusick if ( h.version == GMONVERSION ) { 379*52812Smckusick size = sizeof(struct phdr); 380*52812Smckusick rate = h.profrate; 381*52812Smckusick 382*52812Smckusick } else { 383*52812Smckusick size = sizeof(struct ophdr); 384*52812Smckusick fseek(pfile, size, SEEK_SET); 385*52812Smckusick h.profrate = rate = hertz(); 386*52812Smckusick h.version = GMONVERSION; 387*52812Smckusick } 388*52812Smckusick if (hz == 0) { 389*52812Smckusick hz = rate; 390*52812Smckusick } else if (hz != rate) { 391*52812Smckusick fprintf(stderr, 392*52812Smckusick "%s: profile clock rate (%d) %s (%d) in first gmon file\n", 393*52812Smckusick filename, rate, "incompatible with clock rate", hz); 394*52812Smckusick done(); 395*52812Smckusick } 396*52812Smckusick s_lowpc = (unsigned long) h.lpc; 397*52812Smckusick s_highpc = (unsigned long) h.hpc; 398*52812Smckusick lowpc = (unsigned long)h.lpc / sizeof(UNIT); 399*52812Smckusick highpc = (unsigned long)h.hpc / sizeof(UNIT); 400*52812Smckusick sampbytes = h.ncnt - size; 40133226Sbostic nsamples = sampbytes / sizeof (UNIT); 4027226Speter # ifdef DEBUG 4037226Speter if ( debug & SAMPLEDEBUG ) { 404*52812Smckusick printf( "[openpfile] hdr.lpc 0x%x hdr.hpc 0x%x hdr.ncnt %d\n", 405*52812Smckusick h.lpc , h.hpc , h.ncnt ); 4067226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 4077226Speter s_lowpc , s_highpc ); 4087226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 4097226Speter lowpc , highpc ); 4107226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 4117226Speter sampbytes , nsamples ); 412*52812Smckusick printf( "[openpfile] sample rate %d\n" , hz ); 4137226Speter } 4147226Speter # endif DEBUG 4154510Speter return(pfile); 4164510Speter } 4174510Speter 4184510Speter tally( rawp ) 4194510Speter struct rawarc *rawp; 4204510Speter { 4214510Speter nltype *parentp; 4224510Speter nltype *childp; 4234510Speter 4244510Speter parentp = nllookup( rawp -> raw_frompc ); 4254510Speter childp = nllookup( rawp -> raw_selfpc ); 42652581Smckusick if ( parentp == 0 || childp == 0 ) 42752581Smckusick return; 42830963Smckusick if ( kflag 42930963Smckusick && onlist( kfromlist , parentp -> name ) 43030963Smckusick && onlist( ktolist , childp -> name ) ) { 43130963Smckusick return; 43230963Smckusick } 4334510Speter childp -> ncall += rawp -> raw_count; 4344510Speter # ifdef DEBUG 4354510Speter if ( debug & TALLYDEBUG ) { 4364510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 4374510Speter parentp -> name , childp -> name , rawp -> raw_count ); 4384510Speter } 4394510Speter # endif DEBUG 4404720Speter addarc( parentp , childp , rawp -> raw_count ); 4414510Speter } 4424510Speter 4434866Smckusic /* 4444866Smckusic * dump out the gmon.sum file 4454866Smckusic */ 4464866Smckusic dumpsum( sumfile ) 4474866Smckusic char *sumfile; 4484866Smckusic { 4494866Smckusic register nltype *nlp; 4504866Smckusic register arctype *arcp; 4514866Smckusic struct rawarc arc; 4524866Smckusic FILE *sfile; 4534866Smckusic 4544866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 4554866Smckusic perror( sumfile ); 4564866Smckusic done(); 4574866Smckusic } 4584866Smckusic /* 4594866Smckusic * dump the header; use the last header read in 4604866Smckusic */ 4614866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4624866Smckusic perror( sumfile ); 4634866Smckusic done(); 4644866Smckusic } 4654866Smckusic /* 4664866Smckusic * dump the samples 4674866Smckusic */ 46833226Sbostic if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 4694866Smckusic perror( sumfile ); 4704866Smckusic done(); 4714866Smckusic } 4724866Smckusic /* 4734866Smckusic * dump the normalized raw arc information 4744866Smckusic */ 47511807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4764866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4774866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4784866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4794866Smckusic arc.raw_count = arcp -> arc_count; 4804866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4814866Smckusic perror( sumfile ); 4824866Smckusic done(); 4834866Smckusic } 4844866Smckusic # ifdef DEBUG 4854866Smckusic if ( debug & SAMPLEDEBUG ) { 4864866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4874866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4884866Smckusic } 4894866Smckusic # endif DEBUG 4904866Smckusic } 4914866Smckusic } 4924866Smckusic fclose( sfile ); 4934866Smckusic } 4944866Smckusic 4954510Speter valcmp(p1, p2) 4964510Speter nltype *p1, *p2; 4974510Speter { 4984510Speter if ( p1 -> value < p2 -> value ) { 4994510Speter return LESSTHAN; 5004510Speter } 5014510Speter if ( p1 -> value > p2 -> value ) { 5024510Speter return GREATERTHAN; 5034510Speter } 5044510Speter return EQUALTO; 5054510Speter } 5064510Speter 5074510Speter readsamples(pfile) 5084510Speter FILE *pfile; 5094510Speter { 5104510Speter register i; 51133226Sbostic UNIT sample; 5124510Speter 5134510Speter if (samples == 0) { 51433226Sbostic samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 5154510Speter if (samples == 0) { 5167128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 51733226Sbostic whoami , sampbytes / sizeof (UNIT)); 5184510Speter done(); 5194510Speter } 5204510Speter } 5214510Speter for (i = 0; i < nsamples; i++) { 52233226Sbostic fread(&sample, sizeof (UNIT), 1, pfile); 5234510Speter if (feof(pfile)) 5244510Speter break; 5254510Speter samples[i] += sample; 5264510Speter } 5274510Speter if (i != nsamples) { 5284510Speter fprintf(stderr, 5297128Speter "%s: unexpected EOF after reading %d/%d samples\n", 5307128Speter whoami , --i , nsamples ); 5314510Speter done(); 5324510Speter } 5334510Speter } 5344510Speter 5354510Speter /* 53611523Smckusick * Assign samples to the procedures to which they belong. 53711523Smckusick * 53811523Smckusick * There are three cases as to where pcl and pch can be 53911523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 54011523Smckusick * as shown in the following diagram. overlap computes the 54111523Smckusick * distance between the arrows, the fraction of the sample 54211523Smckusick * that is to be credited to the routine which starts at svalue0. 54311523Smckusick * 54411523Smckusick * svalue0 svalue1 54511523Smckusick * | | 54611523Smckusick * v v 54711523Smckusick * 54811523Smckusick * +-----------------------------------------------+ 54911523Smckusick * | | 55011523Smckusick * | ->| |<- ->| |<- ->| |<- | 55111523Smckusick * | | | | | | 55211523Smckusick * +---------+ +---------+ +---------+ 55311523Smckusick * 55411523Smckusick * ^ ^ ^ ^ ^ ^ 55511523Smckusick * | | | | | | 55611523Smckusick * pcl pch pcl pch pcl pch 55711523Smckusick * 55811523Smckusick * For the vax we assert that samples will never fall in the first 55911807Smckusick * two bytes of any routine, since that is the entry mask, 56011807Smckusick * thus we give call alignentries() to adjust the entry points if 56111807Smckusick * the entry mask falls in one bucket but the code for the routine 56211807Smckusick * doesn't start until the next bucket. In conjunction with the 56311807Smckusick * alignment of routine addresses, this should allow us to have 56411807Smckusick * only one sample for every four bytes of text space and never 56511807Smckusick * have any overlap (the two end cases, above). 5664510Speter */ 5674510Speter asgnsamples() 5684510Speter { 5694510Speter register int j; 57033226Sbostic UNIT ccnt; 5714510Speter double time; 5724510Speter unsigned long pcl, pch; 5734510Speter register int i; 5744841Speter unsigned long overlap; 5754510Speter unsigned long svalue0, svalue1; 5764510Speter 5774510Speter /* read samples and assign to namelist symbols */ 5784510Speter scale = highpc - lowpc; 5794510Speter scale /= nsamples; 58011807Smckusick alignentries(); 5817257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5824510Speter ccnt = samples[i]; 5834510Speter if (ccnt == 0) 5844510Speter continue; 58511523Smckusick pcl = lowpc + scale * i; 58611523Smckusick pch = lowpc + scale * (i + 1); 5874510Speter time = ccnt; 5884510Speter # ifdef DEBUG 5894510Speter if ( debug & SAMPLEDEBUG ) { 5905072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5915072Smckusic pcl , pch , ccnt ); 5924510Speter } 5934510Speter # endif DEBUG 5944510Speter totime += time; 5957252Smckusick for (j = j - 1; j < nname; j++) { 59611807Smckusick svalue0 = nl[j].svalue; 59711807Smckusick svalue1 = nl[j+1].svalue; 59811807Smckusick /* 59911807Smckusick * if high end of tick is below entry address, 60011807Smckusick * go for next tick. 60111807Smckusick */ 6024510Speter if (pch < svalue0) 6034510Speter break; 60411807Smckusick /* 60511807Smckusick * if low end of tick into next routine, 60611807Smckusick * go for next routine. 60711807Smckusick */ 6084510Speter if (pcl >= svalue1) 6094510Speter continue; 61011807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 61111523Smckusick if (overlap > 0) { 6124510Speter # ifdef DEBUG 61311523Smckusick if (debug & SAMPLEDEBUG) { 61411807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 61511807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 61611807Smckusick nl[j].name, 61711807Smckusick overlap * time / scale, overlap); 6184510Speter } 6194510Speter # endif DEBUG 62011523Smckusick nl[j].time += overlap * time / scale; 6214510Speter } 6224510Speter } 6234510Speter } 6244510Speter # ifdef DEBUG 62511523Smckusick if (debug & SAMPLEDEBUG) { 62611523Smckusick printf("[asgnsamples] totime %f\n", totime); 6274510Speter } 6284510Speter # endif DEBUG 6294510Speter } 6304510Speter 6314510Speter 6324841Speter unsigned long 6334510Speter min(a, b) 6344841Speter unsigned long a,b; 6354510Speter { 6364510Speter if (a<b) 6374510Speter return(a); 6384510Speter return(b); 6394510Speter } 6404510Speter 6414841Speter unsigned long 6424510Speter max(a, b) 6434841Speter unsigned long a,b; 6444510Speter { 6454510Speter if (a>b) 6464510Speter return(a); 6474510Speter return(b); 6484510Speter } 6494510Speter 65011807Smckusick /* 65111807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 65211807Smckusick * and possibly push the scaled entry points over the entry mask, 65311807Smckusick * if it turns out that the entry point is in one bucket and the code 65411807Smckusick * for a routine is in the next bucket. 65511807Smckusick */ 65611807Smckusick alignentries() 65711807Smckusick { 65811807Smckusick register struct nl *nlp; 65911807Smckusick unsigned long bucket_of_entry; 66011807Smckusick unsigned long bucket_of_code; 66111807Smckusick 66211807Smckusick for (nlp = nl; nlp < npe; nlp++) { 66311807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 66411807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 66511807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 66611807Smckusick if (bucket_of_entry < bucket_of_code) { 66711807Smckusick # ifdef DEBUG 66811807Smckusick if (debug & SAMPLEDEBUG) { 66911807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 67011807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 67111807Smckusick } 67211807Smckusick # endif DEBUG 67311807Smckusick nlp->svalue += UNITS_TO_CODE; 67411807Smckusick } 67511807Smckusick } 67611807Smckusick } 67711807Smckusick 6784845Speter bool 6794845Speter funcsymbol( nlistp ) 6804845Speter struct nlist *nlistp; 6814845Speter { 6824845Speter extern char *strtab; /* string table from a.out */ 6834851Speter extern int aflag; /* if static functions aren't desired */ 6844845Speter char *name; 6854845Speter 6864845Speter /* 6874845Speter * must be a text symbol, 6884851Speter * and static text symbols don't qualify if aflag set. 6894845Speter */ 6904845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6914851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6924845Speter return FALSE; 6934845Speter } 6944845Speter /* 6957128Speter * can't have any `funny' characters in name, 6964845Speter * where `funny' includes `.', .o file names 6974845Speter * and `$', pascal labels. 6984845Speter */ 6994845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 7004845Speter if ( *name == '.' || *name == '$' ) { 7014845Speter return FALSE; 7024845Speter } 7034845Speter } 7044845Speter return TRUE; 7054845Speter } 7064845Speter 7074510Speter done() 7084510Speter { 7094510Speter 7104510Speter exit(0); 7114510Speter } 712