gprof.c revision 91735
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527313Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4127313Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 4327313Scharnier#endif 4427313Scharnierstatic const char rcsid[] = 4550477Speter "$FreeBSD: head/usr.bin/gprof/gprof.c 91735 2002-03-06 09:47:36Z bde $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 4827313Scharnier#include <err.h> 491590Srgrimes#include "gprof.h" 501590Srgrimes 5138928Sjdpstatic int valcmp(const void *, const void *); 521590Srgrimes 5338928Sjdp 541590Srgrimesstatic struct gmonhdr gmonhdr; 555190Swollmanstatic int lflag; 565190Swollmanstatic int Lflag; 571590Srgrimes 581590Srgrimesmain(argc, argv) 591590Srgrimes int argc; 601590Srgrimes char **argv; 611590Srgrimes{ 621590Srgrimes char **sp; 631590Srgrimes nltype **timesortnlp; 6438928Sjdp char **defaultEs; 651590Srgrimes 661590Srgrimes --argc; 671590Srgrimes argv++; 681590Srgrimes debug = 0; 691590Srgrimes bflag = TRUE; 701590Srgrimes while ( *argv != 0 && **argv == '-' ) { 711590Srgrimes (*argv)++; 721590Srgrimes switch ( **argv ) { 731590Srgrimes case 'a': 741590Srgrimes aflag = TRUE; 751590Srgrimes break; 761590Srgrimes case 'b': 771590Srgrimes bflag = FALSE; 781590Srgrimes break; 791590Srgrimes case 'C': 801590Srgrimes Cflag = TRUE; 811590Srgrimes cyclethreshold = atoi( *++argv ); 821590Srgrimes break; 831590Srgrimes case 'c': 841590Srgrimes#if defined(vax) || defined(tahoe) 851590Srgrimes cflag = TRUE; 861590Srgrimes#else 8727313Scharnier errx(1, "-c isn't supported on this architecture yet"); 881590Srgrimes#endif 891590Srgrimes break; 901590Srgrimes case 'd': 911590Srgrimes dflag = TRUE; 921590Srgrimes setlinebuf(stdout); 931590Srgrimes debug |= atoi( *++argv ); 941590Srgrimes debug |= ANYDEBUG; 951590Srgrimes# ifdef DEBUG 961590Srgrimes printf("[main] debug = %d\n", debug); 971590Srgrimes# else not DEBUG 9827313Scharnier printf("gprof: -d ignored\n"); 991590Srgrimes# endif DEBUG 1001590Srgrimes break; 1011590Srgrimes case 'E': 1021590Srgrimes ++argv; 1031590Srgrimes addlist( Elist , *argv ); 1041590Srgrimes Eflag = TRUE; 1051590Srgrimes addlist( elist , *argv ); 1061590Srgrimes eflag = TRUE; 1071590Srgrimes break; 1081590Srgrimes case 'e': 1091590Srgrimes addlist( elist , *++argv ); 1101590Srgrimes eflag = TRUE; 1111590Srgrimes break; 1121590Srgrimes case 'F': 1131590Srgrimes ++argv; 1141590Srgrimes addlist( Flist , *argv ); 1151590Srgrimes Fflag = TRUE; 1161590Srgrimes addlist( flist , *argv ); 1171590Srgrimes fflag = TRUE; 1181590Srgrimes break; 1191590Srgrimes case 'f': 1201590Srgrimes addlist( flist , *++argv ); 1211590Srgrimes fflag = TRUE; 1221590Srgrimes break; 1231590Srgrimes case 'k': 1241590Srgrimes addlist( kfromlist , *++argv ); 1251590Srgrimes addlist( ktolist , *++argv ); 1261590Srgrimes kflag = TRUE; 1271590Srgrimes break; 12885739Sgreen case 'K': 12985739Sgreen Kflag = TRUE; 13085739Sgreen break; 1315190Swollman case 'l': 1325190Swollman lflag = 1; 1335190Swollman Lflag = 0; 1345190Swollman break; 1355190Swollman case 'L': 1365190Swollman Lflag = 1; 1375190Swollman lflag = 0; 1385190Swollman break; 1395190Swollman case 's': 1401590Srgrimes sflag = TRUE; 1411590Srgrimes break; 1422513Sbde case 'u': 1432513Sbde uflag = TRUE; 1442513Sbde break; 1451590Srgrimes case 'z': 1461590Srgrimes zflag = TRUE; 1471590Srgrimes break; 1481590Srgrimes } 1491590Srgrimes argv++; 1501590Srgrimes } 1511590Srgrimes if ( *argv != 0 ) { 1521590Srgrimes a_outname = *argv; 1531590Srgrimes argv++; 1541590Srgrimes } else { 1551590Srgrimes a_outname = A_OUTNAME; 1561590Srgrimes } 1571590Srgrimes if ( *argv != 0 ) { 1581590Srgrimes gmonname = *argv; 1591590Srgrimes argv++; 1601590Srgrimes } else { 16147420Sjmz gmonname = (char *) malloc(strlen(a_outname)+6); 16247420Sjmz strcpy(gmonname, a_outname); 16347420Sjmz strcat(gmonname, ".gmon"); 1641590Srgrimes } 1651590Srgrimes /* 16638928Sjdp * get information from the executable file. 16738928Sjdp */ 16885739Sgreen if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) || 16985739Sgreen (elf_getnfile(a_outname, &defaultEs) == -1 && 17085739Sgreen aout_getnfile(a_outname, &defaultEs) == -1)) 17138928Sjdp errx(1, "%s: bad format", a_outname); 17238928Sjdp /* 17338928Sjdp * sort symbol table. 17438928Sjdp */ 17538928Sjdp qsort(nl, nname, sizeof(nltype), valcmp); 17638928Sjdp /* 1771590Srgrimes * turn off default functions 1781590Srgrimes */ 17938928Sjdp for ( sp = defaultEs ; *sp ; sp++ ) { 1801590Srgrimes Eflag = TRUE; 1811590Srgrimes addlist( Elist , *sp ); 1821590Srgrimes eflag = TRUE; 1831590Srgrimes addlist( elist , *sp ); 1841590Srgrimes } 1851590Srgrimes /* 1861590Srgrimes * get information about mon.out file(s). 1871590Srgrimes */ 1881590Srgrimes do { 1891590Srgrimes getpfile( gmonname ); 1901590Srgrimes if ( *argv != 0 ) { 1911590Srgrimes gmonname = *argv; 1921590Srgrimes } 1931590Srgrimes } while ( *argv++ != 0 ); 1941590Srgrimes /* 1951590Srgrimes * how many ticks per second? 1961590Srgrimes * if we can't tell, report time in ticks. 1971590Srgrimes */ 1981590Srgrimes if (hz == 0) { 1991590Srgrimes hz = 1; 2001590Srgrimes fprintf(stderr, "time is in ticks, not seconds\n"); 2011590Srgrimes } 2021590Srgrimes /* 2031590Srgrimes * dump out a gmon.sum file if requested 2041590Srgrimes */ 2051590Srgrimes if ( sflag ) { 2061590Srgrimes dumpsum( GMONSUM ); 2071590Srgrimes } 2081590Srgrimes /* 2091590Srgrimes * assign samples to procedures 2101590Srgrimes */ 2111590Srgrimes asgnsamples(); 2121590Srgrimes /* 2131590Srgrimes * assemble the dynamic profile 2141590Srgrimes */ 2151590Srgrimes timesortnlp = doarcs(); 2161590Srgrimes /* 2171590Srgrimes * print the dynamic profile 2181590Srgrimes */ 2195190Swollman if(!lflag) { 2208874Srgrimes printgprof( timesortnlp ); 2215190Swollman } 2221590Srgrimes /* 2231590Srgrimes * print the flat profile 2241590Srgrimes */ 2255190Swollman if(!Lflag) { 2265190Swollman printprof(); 2275190Swollman } 2281590Srgrimes /* 2291590Srgrimes * print the index 2301590Srgrimes */ 2318874Srgrimes printindex(); 2321590Srgrimes done(); 2331590Srgrimes} 2341590Srgrimes 2351590Srgrimes /* 2361590Srgrimes * information from a gmon.out file is in two parts: 2371590Srgrimes * an array of sampling hits within pc ranges, 2381590Srgrimes * and the arcs. 2391590Srgrimes */ 2401590Srgrimesgetpfile(filename) 2411590Srgrimes char *filename; 2421590Srgrimes{ 2431590Srgrimes FILE *pfile; 2441590Srgrimes FILE *openpfile(); 2451590Srgrimes struct rawarc arc; 2461590Srgrimes 2471590Srgrimes pfile = openpfile(filename); 2481590Srgrimes readsamples(pfile); 2491590Srgrimes /* 2501590Srgrimes * the rest of the file consists of 2511590Srgrimes * a bunch of <from,self,count> tuples. 2521590Srgrimes */ 2531590Srgrimes while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 2541590Srgrimes# ifdef DEBUG 2551590Srgrimes if ( debug & SAMPLEDEBUG ) { 25691018Sbde printf( "[getpfile] frompc 0x%lx selfpc 0x%lx count %ld\n" , 2571590Srgrimes arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 2581590Srgrimes } 2591590Srgrimes# endif DEBUG 2601590Srgrimes /* 2611590Srgrimes * add this arc 2621590Srgrimes */ 2631590Srgrimes tally( &arc ); 2641590Srgrimes } 2651590Srgrimes fclose(pfile); 2661590Srgrimes} 2671590Srgrimes 2681590SrgrimesFILE * 2691590Srgrimesopenpfile(filename) 2701590Srgrimes char *filename; 2711590Srgrimes{ 2721590Srgrimes struct gmonhdr tmp; 2731590Srgrimes FILE *pfile; 2741590Srgrimes int size; 2751590Srgrimes int rate; 2761590Srgrimes 2771590Srgrimes if((pfile = fopen(filename, "r")) == NULL) { 2781590Srgrimes perror(filename); 2791590Srgrimes done(); 2801590Srgrimes } 2811590Srgrimes fread(&tmp, sizeof(struct gmonhdr), 1, pfile); 2821590Srgrimes if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc || 2831590Srgrimes tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) { 28427313Scharnier warnx("%s: incompatible with first gmon file", filename); 2851590Srgrimes done(); 2861590Srgrimes } 2871590Srgrimes gmonhdr = tmp; 2881590Srgrimes if ( gmonhdr.version == GMONVERSION ) { 2891590Srgrimes rate = gmonhdr.profrate; 2901590Srgrimes size = sizeof(struct gmonhdr); 2911590Srgrimes } else { 2921590Srgrimes fseek(pfile, sizeof(struct ophdr), SEEK_SET); 2931590Srgrimes size = sizeof(struct ophdr); 2941590Srgrimes gmonhdr.profrate = rate = hertz(); 2951590Srgrimes gmonhdr.version = GMONVERSION; 2961590Srgrimes } 2971590Srgrimes if (hz == 0) { 2981590Srgrimes hz = rate; 2991590Srgrimes } else if (hz != rate) { 3001590Srgrimes fprintf(stderr, 30191018Sbde "%s: profile clock rate (%d) %s (%ld) in first gmon file\n", 3021590Srgrimes filename, rate, "incompatible with clock rate", hz); 3031590Srgrimes done(); 3041590Srgrimes } 3051590Srgrimes s_lowpc = (unsigned long) gmonhdr.lpc; 3061590Srgrimes s_highpc = (unsigned long) gmonhdr.hpc; 30791735Sbde lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2; 30891735Sbde highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2; 3091590Srgrimes sampbytes = gmonhdr.ncnt - size; 3101590Srgrimes nsamples = sampbytes / sizeof (UNIT); 3111590Srgrimes# ifdef DEBUG 3121590Srgrimes if ( debug & SAMPLEDEBUG ) { 31391018Sbde printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n", 3141590Srgrimes gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt ); 31591018Sbde printf( "[openpfile] s_lowpc 0x%lx s_highpc 0x%lx\n" , 3161590Srgrimes s_lowpc , s_highpc ); 31791018Sbde printf( "[openpfile] lowpc 0x%lx highpc 0x%lx\n" , 3181590Srgrimes lowpc , highpc ); 3191590Srgrimes printf( "[openpfile] sampbytes %d nsamples %d\n" , 3201590Srgrimes sampbytes , nsamples ); 32191018Sbde printf( "[openpfile] sample rate %ld\n" , hz ); 3221590Srgrimes } 3231590Srgrimes# endif DEBUG 3241590Srgrimes return(pfile); 3251590Srgrimes} 3261590Srgrimes 3271590Srgrimestally( rawp ) 3281590Srgrimes struct rawarc *rawp; 3291590Srgrimes{ 3301590Srgrimes nltype *parentp; 3311590Srgrimes nltype *childp; 3321590Srgrimes 3331590Srgrimes parentp = nllookup( rawp -> raw_frompc ); 3341590Srgrimes childp = nllookup( rawp -> raw_selfpc ); 3351590Srgrimes if ( parentp == 0 || childp == 0 ) 3361590Srgrimes return; 3371590Srgrimes if ( kflag 3381590Srgrimes && onlist( kfromlist , parentp -> name ) 3391590Srgrimes && onlist( ktolist , childp -> name ) ) { 3401590Srgrimes return; 3411590Srgrimes } 3421590Srgrimes childp -> ncall += rawp -> raw_count; 3431590Srgrimes# ifdef DEBUG 3441590Srgrimes if ( debug & TALLYDEBUG ) { 34591018Sbde printf( "[tally] arc from %s to %s traversed %ld times\n" , 3461590Srgrimes parentp -> name , childp -> name , rawp -> raw_count ); 3471590Srgrimes } 3481590Srgrimes# endif DEBUG 3491590Srgrimes addarc( parentp , childp , rawp -> raw_count ); 3501590Srgrimes} 3511590Srgrimes 3521590Srgrimes/* 3531590Srgrimes * dump out the gmon.sum file 3541590Srgrimes */ 3551590Srgrimesdumpsum( sumfile ) 3561590Srgrimes char *sumfile; 3571590Srgrimes{ 3581590Srgrimes register nltype *nlp; 3591590Srgrimes register arctype *arcp; 3601590Srgrimes struct rawarc arc; 3611590Srgrimes FILE *sfile; 3621590Srgrimes 3631590Srgrimes if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 3641590Srgrimes perror( sumfile ); 3651590Srgrimes done(); 3661590Srgrimes } 3671590Srgrimes /* 3681590Srgrimes * dump the header; use the last header read in 3691590Srgrimes */ 3701590Srgrimes if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) { 3711590Srgrimes perror( sumfile ); 3721590Srgrimes done(); 3731590Srgrimes } 3741590Srgrimes /* 3751590Srgrimes * dump the samples 3761590Srgrimes */ 3771590Srgrimes if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 3781590Srgrimes perror( sumfile ); 3791590Srgrimes done(); 3801590Srgrimes } 3811590Srgrimes /* 3821590Srgrimes * dump the normalized raw arc information 3831590Srgrimes */ 3841590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3851590Srgrimes for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 3861590Srgrimes arc.raw_frompc = arcp -> arc_parentp -> value; 3871590Srgrimes arc.raw_selfpc = arcp -> arc_childp -> value; 3881590Srgrimes arc.raw_count = arcp -> arc_count; 3891590Srgrimes if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 3901590Srgrimes perror( sumfile ); 3911590Srgrimes done(); 3921590Srgrimes } 3931590Srgrimes# ifdef DEBUG 3941590Srgrimes if ( debug & SAMPLEDEBUG ) { 39591018Sbde printf( "[dumpsum] frompc 0x%lx selfpc 0x%lx count %ld\n" , 3961590Srgrimes arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3971590Srgrimes } 3981590Srgrimes# endif DEBUG 3991590Srgrimes } 4001590Srgrimes } 4011590Srgrimes fclose( sfile ); 4021590Srgrimes} 4031590Srgrimes 40438928Sjdpstatic int 40538928Sjdpvalcmp(v1, v2) 40638928Sjdp const void *v1; 40738928Sjdp const void *v2; 4081590Srgrimes{ 40938928Sjdp const nltype *p1 = (const nltype *)v1; 41038928Sjdp const nltype *p2 = (const nltype *)v2; 41138928Sjdp 4121590Srgrimes if ( p1 -> value < p2 -> value ) { 4131590Srgrimes return LESSTHAN; 4141590Srgrimes } 4151590Srgrimes if ( p1 -> value > p2 -> value ) { 4161590Srgrimes return GREATERTHAN; 4171590Srgrimes } 4181590Srgrimes return EQUALTO; 4191590Srgrimes} 4201590Srgrimes 4211590Srgrimesreadsamples(pfile) 4221590Srgrimes FILE *pfile; 4231590Srgrimes{ 4241590Srgrimes register i; 4251590Srgrimes UNIT sample; 4268874Srgrimes 4271590Srgrimes if (samples == 0) { 4281590Srgrimes samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 4291590Srgrimes if (samples == 0) { 43027313Scharnier warnx("no room for %d sample pc's", sampbytes / sizeof (UNIT)); 4311590Srgrimes done(); 4321590Srgrimes } 4331590Srgrimes } 4341590Srgrimes for (i = 0; i < nsamples; i++) { 4351590Srgrimes fread(&sample, sizeof (UNIT), 1, pfile); 4361590Srgrimes if (feof(pfile)) 4371590Srgrimes break; 4381590Srgrimes samples[i] += sample; 4391590Srgrimes } 4401590Srgrimes if (i != nsamples) { 44127313Scharnier warnx("unexpected EOF after reading %d/%d samples", --i , nsamples ); 4421590Srgrimes done(); 4431590Srgrimes } 4441590Srgrimes} 4451590Srgrimes 4461590Srgrimes/* 4471590Srgrimes * Assign samples to the procedures to which they belong. 4481590Srgrimes * 4491590Srgrimes * There are three cases as to where pcl and pch can be 4501590Srgrimes * with respect to the routine entry addresses svalue0 and svalue1 4511590Srgrimes * as shown in the following diagram. overlap computes the 4521590Srgrimes * distance between the arrows, the fraction of the sample 4531590Srgrimes * that is to be credited to the routine which starts at svalue0. 4541590Srgrimes * 4551590Srgrimes * svalue0 svalue1 4561590Srgrimes * | | 4571590Srgrimes * v v 4581590Srgrimes * 4591590Srgrimes * +-----------------------------------------------+ 4601590Srgrimes * | | 4611590Srgrimes * | ->| |<- ->| |<- ->| |<- | 4621590Srgrimes * | | | | | | 4631590Srgrimes * +---------+ +---------+ +---------+ 4641590Srgrimes * 4651590Srgrimes * ^ ^ ^ ^ ^ ^ 4661590Srgrimes * | | | | | | 4671590Srgrimes * pcl pch pcl pch pcl pch 4681590Srgrimes * 4691590Srgrimes * For the vax we assert that samples will never fall in the first 4701590Srgrimes * two bytes of any routine, since that is the entry mask, 4711590Srgrimes * thus we give call alignentries() to adjust the entry points if 4721590Srgrimes * the entry mask falls in one bucket but the code for the routine 4731590Srgrimes * doesn't start until the next bucket. In conjunction with the 4741590Srgrimes * alignment of routine addresses, this should allow us to have 4751590Srgrimes * only one sample for every four bytes of text space and never 4761590Srgrimes * have any overlap (the two end cases, above). 4771590Srgrimes */ 4781590Srgrimesasgnsamples() 4791590Srgrimes{ 4801590Srgrimes register int j; 4811590Srgrimes UNIT ccnt; 4821590Srgrimes double time; 4831590Srgrimes unsigned long pcl, pch; 4841590Srgrimes register int i; 4851590Srgrimes unsigned long overlap; 4861590Srgrimes unsigned long svalue0, svalue1; 4871590Srgrimes 4881590Srgrimes /* read samples and assign to namelist symbols */ 4891590Srgrimes scale = highpc - lowpc; 4901590Srgrimes scale /= nsamples; 4911590Srgrimes alignentries(); 4921590Srgrimes for (i = 0, j = 1; i < nsamples; i++) { 4931590Srgrimes ccnt = samples[i]; 4941590Srgrimes if (ccnt == 0) 4951590Srgrimes continue; 49648839Ssimokawa pcl = lowpc + (unsigned long)(scale * i); 49748839Ssimokawa pch = lowpc + (unsigned long)(scale * (i + 1)); 4981590Srgrimes time = ccnt; 4991590Srgrimes# ifdef DEBUG 5001590Srgrimes if ( debug & SAMPLEDEBUG ) { 50191018Sbde printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %d\n" , 5021590Srgrimes pcl , pch , ccnt ); 5031590Srgrimes } 5041590Srgrimes# endif DEBUG 5051590Srgrimes totime += time; 5061590Srgrimes for (j = j - 1; j < nname; j++) { 5071590Srgrimes svalue0 = nl[j].svalue; 5081590Srgrimes svalue1 = nl[j+1].svalue; 5091590Srgrimes /* 5108874Srgrimes * if high end of tick is below entry address, 5111590Srgrimes * go for next tick. 5121590Srgrimes */ 5131590Srgrimes if (pch < svalue0) 5141590Srgrimes break; 5151590Srgrimes /* 5161590Srgrimes * if low end of tick into next routine, 5171590Srgrimes * go for next routine. 5181590Srgrimes */ 5191590Srgrimes if (pcl >= svalue1) 5201590Srgrimes continue; 5211590Srgrimes overlap = min(pch, svalue1) - max(pcl, svalue0); 5221590Srgrimes if (overlap > 0) { 5231590Srgrimes# ifdef DEBUG 5241590Srgrimes if (debug & SAMPLEDEBUG) { 52591018Sbde printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n", 52691735Sbde nl[j].value / HISTORICAL_SCALE_2, 52791735Sbde svalue0, svalue1, nl[j].name, 5281590Srgrimes overlap * time / scale, overlap); 5291590Srgrimes } 5301590Srgrimes# endif DEBUG 5311590Srgrimes nl[j].time += overlap * time / scale; 5321590Srgrimes } 5331590Srgrimes } 5341590Srgrimes } 5351590Srgrimes# ifdef DEBUG 5361590Srgrimes if (debug & SAMPLEDEBUG) { 5371590Srgrimes printf("[asgnsamples] totime %f\n", totime); 5381590Srgrimes } 5391590Srgrimes# endif DEBUG 5401590Srgrimes} 5411590Srgrimes 5421590Srgrimes 5431590Srgrimesunsigned long 5441590Srgrimesmin(a, b) 5451590Srgrimes unsigned long a,b; 5461590Srgrimes{ 5471590Srgrimes if (a<b) 5481590Srgrimes return(a); 5491590Srgrimes return(b); 5501590Srgrimes} 5511590Srgrimes 5521590Srgrimesunsigned long 5531590Srgrimesmax(a, b) 5541590Srgrimes unsigned long a,b; 5551590Srgrimes{ 5561590Srgrimes if (a>b) 5571590Srgrimes return(a); 5581590Srgrimes return(b); 5591590Srgrimes} 5601590Srgrimes 5611590Srgrimes /* 5621590Srgrimes * calculate scaled entry point addresses (to save time in asgnsamples), 5631590Srgrimes * and possibly push the scaled entry points over the entry mask, 5641590Srgrimes * if it turns out that the entry point is in one bucket and the code 5651590Srgrimes * for a routine is in the next bucket. 5661590Srgrimes */ 5671590Srgrimesalignentries() 5681590Srgrimes{ 5691590Srgrimes register struct nl *nlp; 5701590Srgrimes unsigned long bucket_of_entry; 5711590Srgrimes unsigned long bucket_of_code; 5721590Srgrimes 5731590Srgrimes for (nlp = nl; nlp < npe; nlp++) { 57491735Sbde nlp -> svalue = nlp -> value / HISTORICAL_SCALE_2; 5751590Srgrimes bucket_of_entry = (nlp->svalue - lowpc) / scale; 57691735Sbde bucket_of_code = (nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2 - 57791735Sbde lowpc) / scale; 5781590Srgrimes if (bucket_of_entry < bucket_of_code) { 5791590Srgrimes# ifdef DEBUG 5801590Srgrimes if (debug & SAMPLEDEBUG) { 58191018Sbde printf("[alignentries] pushing svalue 0x%lx to 0x%lx\n", 58291735Sbde nlp->svalue, 58391735Sbde nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2); 5841590Srgrimes } 5851590Srgrimes# endif DEBUG 58691735Sbde nlp->svalue += OFFSET_OF_CODE / HISTORICAL_SCALE_2; 5871590Srgrimes } 5881590Srgrimes } 5891590Srgrimes} 5901590Srgrimes 5911590Srgrimesdone() 5921590Srgrimes{ 5931590Srgrimes 5941590Srgrimes exit(0); 5951590Srgrimes} 596