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*52650Smckusick static char sccsid[] = "@(#)gprof.c 5.9 (Berkeley) 02/24/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 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; 47*52650Smckusick case 'C': 48*52650Smckusick Cflag = TRUE; 49*52650Smckusick cyclethreshold = atoi( *++argv ); 50*52650Smckusick break; 517173Speter case 'c': 5248700Sdonn #if defined(vax) || defined(tahoe) 537173Speter cflag = TRUE; 5448700Sdonn #else 5548700Sdonn fprintf(stderr, "gprof: -c isn't supported on this architecture yet\n"); 5648700Sdonn exit(1); 5748700Sdonn #endif 587173Speter break; 594866Smckusic case 'd': 607173Speter dflag = TRUE; 61*52650Smckusick debug |= atoi( *++argv ); 624510Speter debug |= ANYDEBUG; 634510Speter # ifdef DEBUG 6411807Smckusick printf("[main] debug = %d\n", debug); 6511807Smckusick # else not DEBUG 6611807Smckusick printf("%s: -d ignored\n", whoami); 674510Speter # endif DEBUG 684866Smckusic break; 697223Speter case 'E': 707223Speter ++argv; 717223Speter addlist( Elist , *argv ); 727223Speter Eflag = TRUE; 737223Speter addlist( elist , *argv ); 747223Speter eflag = TRUE; 757223Speter break; 767173Speter case 'e': 777223Speter addlist( elist , *++argv ); 787173Speter eflag = TRUE; 794866Smckusic break; 807223Speter case 'F': 817223Speter ++argv; 827223Speter addlist( Flist , *argv ); 837223Speter Fflag = TRUE; 847223Speter addlist( flist , *argv ); 857223Speter fflag = TRUE; 867223Speter break; 877173Speter case 'f': 887223Speter addlist( flist , *++argv ); 897173Speter fflag = TRUE; 904866Smckusic break; 9130963Smckusick case 'k': 9230963Smckusick addlist( kfromlist , *++argv ); 9330963Smckusick addlist( ktolist , *++argv ); 9430963Smckusick kflag = TRUE; 9530963Smckusick break; 964866Smckusic case 's': 977173Speter sflag = TRUE; 984866Smckusic break; 994866Smckusic case 'z': 1007173Speter zflag = TRUE; 1014866Smckusic break; 1024510Speter } 1034510Speter argv++; 1044510Speter } 1054510Speter if ( *argv != 0 ) { 1064510Speter a_outname = *argv; 1074510Speter argv++; 1084510Speter } else { 1094510Speter a_outname = A_OUTNAME; 1104510Speter } 1114510Speter if ( *argv != 0 ) { 1124563Speter gmonname = *argv; 1134510Speter argv++; 1144510Speter } else { 1154563Speter gmonname = GMONNAME; 1164510Speter } 1174510Speter /* 1187173Speter * turn off default functions 1197173Speter */ 1207223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 1217223Speter Eflag = TRUE; 1227223Speter addlist( Elist , *sp ); 1237173Speter eflag = TRUE; 1247223Speter addlist( elist , *sp ); 1257173Speter } 1267173Speter /* 12715910Speter * how many ticks per second? 12815910Speter * if we can't tell, report time in ticks. 12910249Speter */ 13010249Speter hz = hertz(); 13115910Speter if (hz == 0) { 13215910Speter hz = 1; 13315910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 13415910Speter } 13510249Speter /* 1364510Speter * get information about a.out file. 1374510Speter */ 1384510Speter getnfile(); 1394510Speter /* 1404510Speter * get information about mon.out file(s). 1414510Speter */ 1424866Smckusic do { 1434866Smckusic getpfile( gmonname ); 1444866Smckusic if ( *argv != 0 ) { 1454866Smckusic gmonname = *argv; 1464866Smckusic } 1477128Speter } while ( *argv++ != 0 ); 1484510Speter /* 1494866Smckusic * dump out a gmon.sum file if requested 1504866Smckusic */ 1517128Speter if ( sflag ) { 1527128Speter dumpsum( GMONSUM ); 1537128Speter } 1544866Smckusic /* 1554510Speter * assign samples to procedures 1564510Speter */ 1574510Speter asgnsamples(); 1584510Speter /* 15916852Smckusick * assemble the dynamic profile 1604510Speter */ 16116852Smckusick timesortnlp = doarcs(); 16216852Smckusick /* 16316852Smckusick * print the dynamic profile 16416852Smckusick */ 16516852Smckusick printgprof( timesortnlp ); 16616852Smckusick /* 16716852Smckusick * print the flat profile 16816852Smckusick */ 1694510Speter printprof(); 1704510Speter /* 17116852Smckusick * print the index 1724510Speter */ 17316852Smckusick printindex(); 1744510Speter done(); 1754510Speter } 1764510Speter 1777128Speter /* 1787128Speter * Set up string and symbol tables from a.out. 1797128Speter * and optionally the text space. 1807128Speter * On return symbol table is sorted by value. 1817128Speter */ 1824510Speter getnfile() 1834510Speter { 1844510Speter FILE *nfile; 18533226Sbostic int valcmp(); 1864510Speter 1874510Speter nfile = fopen( a_outname ,"r"); 1884510Speter if (nfile == NULL) { 1894510Speter perror( a_outname ); 1904510Speter done(); 1914510Speter } 1924510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1934510Speter if (N_BADMAG(xbuf)) { 1947128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1954510Speter done(); 1964510Speter } 1974510Speter getstrtab(nfile); 1984510Speter getsymtab(nfile); 1994720Speter gettextspace( nfile ); 2004510Speter qsort(nl, nname, sizeof(nltype), valcmp); 2014510Speter fclose(nfile); 2024510Speter # ifdef DEBUG 2034510Speter if ( debug & AOUTDEBUG ) { 2044510Speter register int j; 2054510Speter 2064510Speter for (j = 0; j < nname; j++){ 2074510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 2084510Speter } 2094510Speter } 2104510Speter # endif DEBUG 2114510Speter } 2124510Speter 2134510Speter getstrtab(nfile) 2144510Speter FILE *nfile; 2154510Speter { 2164510Speter 2174510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 2184510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 2197128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 2207128Speter whoami , a_outname ); 2214510Speter done(); 2224510Speter } 2234510Speter strtab = (char *)calloc(ssiz, 1); 2244510Speter if (strtab == NULL) { 2257128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 2267128Speter whoami , a_outname , ssiz); 2274510Speter done(); 2284510Speter } 2294510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2307128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2317128Speter whoami , a_outname ); 2324510Speter done(); 2334510Speter } 2344510Speter } 2354510Speter 2364510Speter /* 2374510Speter * Read in symbol table 2384510Speter */ 2394510Speter getsymtab(nfile) 2404510Speter FILE *nfile; 2414510Speter { 2424510Speter register long i; 2434510Speter int askfor; 2444510Speter struct nlist nbuf; 2454510Speter 2464510Speter /* pass1 - count symbols */ 2474510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2484510Speter nname = 0; 2494510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2504510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2514845Speter if ( ! funcsymbol( &nbuf ) ) { 2524510Speter continue; 2534510Speter } 2544510Speter nname++; 2554510Speter } 2564510Speter if (nname == 0) { 2577128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2584510Speter done(); 2594510Speter } 2607128Speter askfor = nname + 1; 2614510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2624510Speter if (nl == 0) { 2637128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2647128Speter whoami, askfor * sizeof(nltype) ); 2654510Speter done(); 2664510Speter } 2674510Speter 2684510Speter /* pass2 - read symbols */ 2694510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2704510Speter npe = nl; 2714510Speter nname = 0; 2724510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2734510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2744845Speter if ( ! funcsymbol( &nbuf ) ) { 2754845Speter # ifdef DEBUG 2764845Speter if ( debug & AOUTDEBUG ) { 2774845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2784845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2794845Speter } 2804845Speter # endif DEBUG 2814510Speter continue; 2824510Speter } 2834510Speter npe->value = nbuf.n_value; 2844510Speter npe->name = strtab+nbuf.n_un.n_strx; 2854510Speter # ifdef DEBUG 2864510Speter if ( debug & AOUTDEBUG ) { 2874510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2884510Speter nname , npe -> name , npe -> value ); 2894510Speter } 2904510Speter # endif DEBUG 2914510Speter npe++; 2924510Speter nname++; 2934510Speter } 2944510Speter npe->value = -1; 2954510Speter } 2964510Speter 2974510Speter /* 2984720Speter * read in the text space of an a.out file 2994720Speter */ 3004720Speter gettextspace( nfile ) 3014720Speter FILE *nfile; 3024720Speter { 30333226Sbostic char *malloc(); 3044720Speter 3054720Speter if ( cflag == 0 ) { 3064720Speter return; 3074720Speter } 30833226Sbostic textspace = (u_char *) malloc( xbuf.a_text ); 3094720Speter if ( textspace == 0 ) { 3107128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 3117128Speter whoami , xbuf.a_text ); 3127128Speter fprintf( stderr , "can't do -c\n" ); 3134720Speter return; 3144720Speter } 3154720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 3164720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 3177128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 3187128Speter fprintf( stderr , "can't do -c\n" ); 3194720Speter free( textspace ); 3204720Speter textspace = 0; 3214720Speter return; 3224720Speter } 3234720Speter } 3244720Speter /* 3254563Speter * information from a gmon.out file is in two parts: 3264510Speter * an array of sampling hits within pc ranges, 3274510Speter * and the arcs. 3284510Speter */ 3294510Speter getpfile(filename) 3304510Speter char *filename; 3314510Speter { 3324510Speter FILE *pfile; 3334510Speter FILE *openpfile(); 3344510Speter struct rawarc arc; 3354510Speter 3364510Speter pfile = openpfile(filename); 3374510Speter readsamples(pfile); 3384510Speter /* 3394510Speter * the rest of the file consists of 3404510Speter * a bunch of <from,self,count> tuples. 3414510Speter */ 3424510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3434510Speter # ifdef DEBUG 3444510Speter if ( debug & SAMPLEDEBUG ) { 3454752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3464510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3474510Speter } 3484510Speter # endif DEBUG 3494510Speter /* 3504510Speter * add this arc 3514510Speter */ 3524510Speter tally( &arc ); 3534510Speter } 3544510Speter fclose(pfile); 3554510Speter } 3564510Speter 3574841Speter FILE * 3584841Speter openpfile(filename) 3594510Speter char *filename; 3604510Speter { 3614866Smckusic struct hdr tmp; 3624510Speter FILE *pfile; 3634510Speter 3644510Speter if((pfile = fopen(filename, "r")) == NULL) { 3654510Speter perror(filename); 3664510Speter done(); 3674510Speter } 3684866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3694866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3704866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3714866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3724866Smckusic done(); 3734866Smckusic } 3744866Smckusic h = tmp; 3754752Speter s_lowpc = (unsigned long) h.lowpc; 3764752Speter s_highpc = (unsigned long) h.highpc; 3777227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3787227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3794510Speter sampbytes = h.ncnt - sizeof(struct hdr); 38033226Sbostic nsamples = sampbytes / sizeof (UNIT); 3817226Speter # ifdef DEBUG 3827226Speter if ( debug & SAMPLEDEBUG ) { 3837226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3847226Speter h.lowpc , h.highpc , h.ncnt ); 3857226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3867226Speter s_lowpc , s_highpc ); 3877226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3887226Speter lowpc , highpc ); 3897226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3907226Speter sampbytes , nsamples ); 3917226Speter } 3927226Speter # endif DEBUG 3934510Speter return(pfile); 3944510Speter } 3954510Speter 3964510Speter tally( rawp ) 3974510Speter struct rawarc *rawp; 3984510Speter { 3994510Speter nltype *parentp; 4004510Speter nltype *childp; 4014510Speter 4024510Speter parentp = nllookup( rawp -> raw_frompc ); 4034510Speter childp = nllookup( rawp -> raw_selfpc ); 40452581Smckusick if ( parentp == 0 || childp == 0 ) 40552581Smckusick return; 40630963Smckusick if ( kflag 40730963Smckusick && onlist( kfromlist , parentp -> name ) 40830963Smckusick && onlist( ktolist , childp -> name ) ) { 40930963Smckusick return; 41030963Smckusick } 4114510Speter childp -> ncall += rawp -> raw_count; 4124510Speter # ifdef DEBUG 4134510Speter if ( debug & TALLYDEBUG ) { 4144510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 4154510Speter parentp -> name , childp -> name , rawp -> raw_count ); 4164510Speter } 4174510Speter # endif DEBUG 4184720Speter addarc( parentp , childp , rawp -> raw_count ); 4194510Speter } 4204510Speter 4214866Smckusic /* 4224866Smckusic * dump out the gmon.sum file 4234866Smckusic */ 4244866Smckusic dumpsum( sumfile ) 4254866Smckusic char *sumfile; 4264866Smckusic { 4274866Smckusic register nltype *nlp; 4284866Smckusic register arctype *arcp; 4294866Smckusic struct rawarc arc; 4304866Smckusic FILE *sfile; 4314866Smckusic 4324866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 4334866Smckusic perror( sumfile ); 4344866Smckusic done(); 4354866Smckusic } 4364866Smckusic /* 4374866Smckusic * dump the header; use the last header read in 4384866Smckusic */ 4394866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4404866Smckusic perror( sumfile ); 4414866Smckusic done(); 4424866Smckusic } 4434866Smckusic /* 4444866Smckusic * dump the samples 4454866Smckusic */ 44633226Sbostic if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 4474866Smckusic perror( sumfile ); 4484866Smckusic done(); 4494866Smckusic } 4504866Smckusic /* 4514866Smckusic * dump the normalized raw arc information 4524866Smckusic */ 45311807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4544866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4554866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4564866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4574866Smckusic arc.raw_count = arcp -> arc_count; 4584866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4594866Smckusic perror( sumfile ); 4604866Smckusic done(); 4614866Smckusic } 4624866Smckusic # ifdef DEBUG 4634866Smckusic if ( debug & SAMPLEDEBUG ) { 4644866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4654866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4664866Smckusic } 4674866Smckusic # endif DEBUG 4684866Smckusic } 4694866Smckusic } 4704866Smckusic fclose( sfile ); 4714866Smckusic } 4724866Smckusic 4734510Speter valcmp(p1, p2) 4744510Speter nltype *p1, *p2; 4754510Speter { 4764510Speter if ( p1 -> value < p2 -> value ) { 4774510Speter return LESSTHAN; 4784510Speter } 4794510Speter if ( p1 -> value > p2 -> value ) { 4804510Speter return GREATERTHAN; 4814510Speter } 4824510Speter return EQUALTO; 4834510Speter } 4844510Speter 4854510Speter readsamples(pfile) 4864510Speter FILE *pfile; 4874510Speter { 4884510Speter register i; 48933226Sbostic UNIT sample; 4904510Speter 4914510Speter if (samples == 0) { 49233226Sbostic samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 4934510Speter if (samples == 0) { 4947128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 49533226Sbostic whoami , sampbytes / sizeof (UNIT)); 4964510Speter done(); 4974510Speter } 4984510Speter } 4994510Speter for (i = 0; i < nsamples; i++) { 50033226Sbostic fread(&sample, sizeof (UNIT), 1, pfile); 5014510Speter if (feof(pfile)) 5024510Speter break; 5034510Speter samples[i] += sample; 5044510Speter } 5054510Speter if (i != nsamples) { 5064510Speter fprintf(stderr, 5077128Speter "%s: unexpected EOF after reading %d/%d samples\n", 5087128Speter whoami , --i , nsamples ); 5094510Speter done(); 5104510Speter } 5114510Speter } 5124510Speter 5134510Speter /* 51411523Smckusick * Assign samples to the procedures to which they belong. 51511523Smckusick * 51611523Smckusick * There are three cases as to where pcl and pch can be 51711523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 51811523Smckusick * as shown in the following diagram. overlap computes the 51911523Smckusick * distance between the arrows, the fraction of the sample 52011523Smckusick * that is to be credited to the routine which starts at svalue0. 52111523Smckusick * 52211523Smckusick * svalue0 svalue1 52311523Smckusick * | | 52411523Smckusick * v v 52511523Smckusick * 52611523Smckusick * +-----------------------------------------------+ 52711523Smckusick * | | 52811523Smckusick * | ->| |<- ->| |<- ->| |<- | 52911523Smckusick * | | | | | | 53011523Smckusick * +---------+ +---------+ +---------+ 53111523Smckusick * 53211523Smckusick * ^ ^ ^ ^ ^ ^ 53311523Smckusick * | | | | | | 53411523Smckusick * pcl pch pcl pch pcl pch 53511523Smckusick * 53611523Smckusick * For the vax we assert that samples will never fall in the first 53711807Smckusick * two bytes of any routine, since that is the entry mask, 53811807Smckusick * thus we give call alignentries() to adjust the entry points if 53911807Smckusick * the entry mask falls in one bucket but the code for the routine 54011807Smckusick * doesn't start until the next bucket. In conjunction with the 54111807Smckusick * alignment of routine addresses, this should allow us to have 54211807Smckusick * only one sample for every four bytes of text space and never 54311807Smckusick * have any overlap (the two end cases, above). 5444510Speter */ 5454510Speter asgnsamples() 5464510Speter { 5474510Speter register int j; 54833226Sbostic UNIT ccnt; 5494510Speter double time; 5504510Speter unsigned long pcl, pch; 5514510Speter register int i; 5524841Speter unsigned long overlap; 5534510Speter unsigned long svalue0, svalue1; 5544510Speter 5554510Speter /* read samples and assign to namelist symbols */ 5564510Speter scale = highpc - lowpc; 5574510Speter scale /= nsamples; 55811807Smckusick alignentries(); 5597257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5604510Speter ccnt = samples[i]; 5614510Speter if (ccnt == 0) 5624510Speter continue; 56311523Smckusick pcl = lowpc + scale * i; 56411523Smckusick pch = lowpc + scale * (i + 1); 5654510Speter time = ccnt; 5664510Speter # ifdef DEBUG 5674510Speter if ( debug & SAMPLEDEBUG ) { 5685072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5695072Smckusic pcl , pch , ccnt ); 5704510Speter } 5714510Speter # endif DEBUG 5724510Speter totime += time; 5737252Smckusick for (j = j - 1; j < nname; j++) { 57411807Smckusick svalue0 = nl[j].svalue; 57511807Smckusick svalue1 = nl[j+1].svalue; 57611807Smckusick /* 57711807Smckusick * if high end of tick is below entry address, 57811807Smckusick * go for next tick. 57911807Smckusick */ 5804510Speter if (pch < svalue0) 5814510Speter break; 58211807Smckusick /* 58311807Smckusick * if low end of tick into next routine, 58411807Smckusick * go for next routine. 58511807Smckusick */ 5864510Speter if (pcl >= svalue1) 5874510Speter continue; 58811807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 58911523Smckusick if (overlap > 0) { 5904510Speter # ifdef DEBUG 59111523Smckusick if (debug & SAMPLEDEBUG) { 59211807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 59311807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 59411807Smckusick nl[j].name, 59511807Smckusick overlap * time / scale, overlap); 5964510Speter } 5974510Speter # endif DEBUG 59811523Smckusick nl[j].time += overlap * time / scale; 5994510Speter } 6004510Speter } 6014510Speter } 6024510Speter # ifdef DEBUG 60311523Smckusick if (debug & SAMPLEDEBUG) { 60411523Smckusick printf("[asgnsamples] totime %f\n", totime); 6054510Speter } 6064510Speter # endif DEBUG 6074510Speter } 6084510Speter 6094510Speter 6104841Speter unsigned long 6114510Speter min(a, b) 6124841Speter unsigned long a,b; 6134510Speter { 6144510Speter if (a<b) 6154510Speter return(a); 6164510Speter return(b); 6174510Speter } 6184510Speter 6194841Speter unsigned long 6204510Speter max(a, b) 6214841Speter unsigned long a,b; 6224510Speter { 6234510Speter if (a>b) 6244510Speter return(a); 6254510Speter return(b); 6264510Speter } 6274510Speter 62811807Smckusick /* 62911807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 63011807Smckusick * and possibly push the scaled entry points over the entry mask, 63111807Smckusick * if it turns out that the entry point is in one bucket and the code 63211807Smckusick * for a routine is in the next bucket. 63311807Smckusick */ 63411807Smckusick alignentries() 63511807Smckusick { 63611807Smckusick register struct nl *nlp; 63711807Smckusick unsigned long bucket_of_entry; 63811807Smckusick unsigned long bucket_of_code; 63911807Smckusick 64011807Smckusick for (nlp = nl; nlp < npe; nlp++) { 64111807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 64211807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 64311807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 64411807Smckusick if (bucket_of_entry < bucket_of_code) { 64511807Smckusick # ifdef DEBUG 64611807Smckusick if (debug & SAMPLEDEBUG) { 64711807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 64811807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 64911807Smckusick } 65011807Smckusick # endif DEBUG 65111807Smckusick nlp->svalue += UNITS_TO_CODE; 65211807Smckusick } 65311807Smckusick } 65411807Smckusick } 65511807Smckusick 6564845Speter bool 6574845Speter funcsymbol( nlistp ) 6584845Speter struct nlist *nlistp; 6594845Speter { 6604845Speter extern char *strtab; /* string table from a.out */ 6614851Speter extern int aflag; /* if static functions aren't desired */ 6624845Speter char *name; 6634845Speter 6644845Speter /* 6654845Speter * must be a text symbol, 6664851Speter * and static text symbols don't qualify if aflag set. 6674845Speter */ 6684845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6694851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6704845Speter return FALSE; 6714845Speter } 6724845Speter /* 6737128Speter * can't have any `funny' characters in name, 6744845Speter * where `funny' includes `.', .o file names 6754845Speter * and `$', pascal labels. 6764845Speter */ 6774845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6784845Speter if ( *name == '.' || *name == '$' ) { 6794845Speter return FALSE; 6804845Speter } 6814845Speter } 6824845Speter return TRUE; 6834845Speter } 6844845Speter 6854510Speter done() 6864510Speter { 6874510Speter 6884510Speter exit(0); 6894510Speter } 690