1331722Seadler/* 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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3127313Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 36105243Scharnier#if 0 371590Srgrimes#ifndef lint 381590Srgrimesstatic char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 39105243Scharnier#endif /* not lint */ 4027313Scharnier#endif 41105243Scharnier 4299112Sobrien#include <sys/cdefs.h> 4399112Sobrien__FBSDID("$FreeBSD: stable/11/usr.bin/gprof/gprof.c 359763 2020-04-10 00:27:19Z kevans $"); 441590Srgrimes 4527313Scharnier#include <err.h> 4691738Sbde#include <limits.h> 4793123Smike#include <stdint.h> 48129657Sstefanf#include <string.h> 49129657Sstefanf 50359763Skevans#define EXTERN 511590Srgrimes#include "gprof.h" 521590Srgrimes 5338928Sjdpstatic int valcmp(const void *, const void *); 541590Srgrimes 551590Srgrimesstatic struct gmonhdr gmonhdr; 565190Swollmanstatic int lflag; 575190Swollmanstatic int Lflag; 581590Srgrimes 59105243Scharnierint 60246783Scharniermain(int argc, 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 'd': 841590Srgrimes dflag = TRUE; 851590Srgrimes setlinebuf(stdout); 861590Srgrimes debug |= atoi( *++argv ); 871590Srgrimes debug |= ANYDEBUG; 881590Srgrimes# ifdef DEBUG 891590Srgrimes printf("[main] debug = %d\n", debug); 9097631Swollman# else /* not DEBUG */ 9127313Scharnier printf("gprof: -d ignored\n"); 9297631Swollman# endif /* DEBUG */ 931590Srgrimes break; 941590Srgrimes case 'E': 951590Srgrimes ++argv; 961590Srgrimes addlist( Elist , *argv ); 971590Srgrimes Eflag = TRUE; 981590Srgrimes addlist( elist , *argv ); 991590Srgrimes eflag = TRUE; 1001590Srgrimes break; 1011590Srgrimes case 'e': 1021590Srgrimes addlist( elist , *++argv ); 1031590Srgrimes eflag = TRUE; 1041590Srgrimes break; 1051590Srgrimes case 'F': 1061590Srgrimes ++argv; 1071590Srgrimes addlist( Flist , *argv ); 1081590Srgrimes Fflag = TRUE; 1091590Srgrimes addlist( flist , *argv ); 1101590Srgrimes fflag = TRUE; 1111590Srgrimes break; 1121590Srgrimes case 'f': 1131590Srgrimes addlist( flist , *++argv ); 1141590Srgrimes fflag = TRUE; 1151590Srgrimes break; 1161590Srgrimes case 'k': 1171590Srgrimes addlist( kfromlist , *++argv ); 1181590Srgrimes addlist( ktolist , *++argv ); 1191590Srgrimes kflag = TRUE; 1201590Srgrimes break; 12185739Sgreen case 'K': 12285739Sgreen Kflag = TRUE; 12385739Sgreen break; 124105243Scharnier case 'l': 1255190Swollman lflag = 1; 1265190Swollman Lflag = 0; 1275190Swollman break; 128105243Scharnier case 'L': 1295190Swollman Lflag = 1; 1305190Swollman lflag = 0; 1315190Swollman break; 132105243Scharnier case 's': 1331590Srgrimes sflag = TRUE; 1341590Srgrimes break; 1352513Sbde case 'u': 1362513Sbde uflag = TRUE; 1372513Sbde break; 1381590Srgrimes case 'z': 1391590Srgrimes zflag = TRUE; 1401590Srgrimes break; 1411590Srgrimes } 1421590Srgrimes argv++; 1431590Srgrimes } 1441590Srgrimes if ( *argv != 0 ) { 1451590Srgrimes a_outname = *argv; 1461590Srgrimes argv++; 1471590Srgrimes } else { 1481590Srgrimes a_outname = A_OUTNAME; 1491590Srgrimes } 1501590Srgrimes if ( *argv != 0 ) { 1511590Srgrimes gmonname = *argv; 1521590Srgrimes argv++; 1531590Srgrimes } else { 15447420Sjmz gmonname = (char *) malloc(strlen(a_outname)+6); 15547420Sjmz strcpy(gmonname, a_outname); 15647420Sjmz strcat(gmonname, ".gmon"); 1571590Srgrimes } 1581590Srgrimes /* 15938928Sjdp * get information from the executable file. 16038928Sjdp */ 16185739Sgreen if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) || 162187116Sobrien (!Kflag && elf_getnfile(a_outname, &defaultEs) == -1 && 16385739Sgreen aout_getnfile(a_outname, &defaultEs) == -1)) 16438928Sjdp errx(1, "%s: bad format", a_outname); 16538928Sjdp /* 16638928Sjdp * sort symbol table. 16738928Sjdp */ 16838928Sjdp qsort(nl, nname, sizeof(nltype), valcmp); 16938928Sjdp /* 1701590Srgrimes * turn off default functions 1711590Srgrimes */ 17238928Sjdp for ( sp = defaultEs ; *sp ; sp++ ) { 1731590Srgrimes Eflag = TRUE; 1741590Srgrimes addlist( Elist , *sp ); 1751590Srgrimes eflag = TRUE; 1761590Srgrimes addlist( elist , *sp ); 1771590Srgrimes } 1781590Srgrimes /* 1791590Srgrimes * get information about mon.out file(s). 1801590Srgrimes */ 1811590Srgrimes do { 1821590Srgrimes getpfile( gmonname ); 1831590Srgrimes if ( *argv != 0 ) { 1841590Srgrimes gmonname = *argv; 1851590Srgrimes } 1861590Srgrimes } while ( *argv++ != 0 ); 1871590Srgrimes /* 1881590Srgrimes * how many ticks per second? 1891590Srgrimes * if we can't tell, report time in ticks. 1901590Srgrimes */ 1911590Srgrimes if (hz == 0) { 1921590Srgrimes hz = 1; 1931590Srgrimes fprintf(stderr, "time is in ticks, not seconds\n"); 1941590Srgrimes } 1951590Srgrimes /* 1961590Srgrimes * dump out a gmon.sum file if requested 1971590Srgrimes */ 1981590Srgrimes if ( sflag ) { 1991590Srgrimes dumpsum( GMONSUM ); 2001590Srgrimes } 2011590Srgrimes /* 2021590Srgrimes * assign samples to procedures 2031590Srgrimes */ 2041590Srgrimes asgnsamples(); 2051590Srgrimes /* 2061590Srgrimes * assemble the dynamic profile 2071590Srgrimes */ 2081590Srgrimes timesortnlp = doarcs(); 2091590Srgrimes /* 2101590Srgrimes * print the dynamic profile 2111590Srgrimes */ 2125190Swollman if(!lflag) { 2138874Srgrimes printgprof( timesortnlp ); 2145190Swollman } 2151590Srgrimes /* 2161590Srgrimes * print the flat profile 2171590Srgrimes */ 2185190Swollman if(!Lflag) { 2195190Swollman printprof(); 2205190Swollman } 2211590Srgrimes /* 2221590Srgrimes * print the index 2231590Srgrimes */ 2248874Srgrimes printindex(); 225105243Scharnier exit(0); 2261590Srgrimes} 2271590Srgrimes 2281590Srgrimes /* 2291590Srgrimes * information from a gmon.out file is in two parts: 2301590Srgrimes * an array of sampling hits within pc ranges, 2311590Srgrimes * and the arcs. 2321590Srgrimes */ 233105243Scharniervoid 234246783Scharniergetpfile(char *filename) 2351590Srgrimes{ 2361590Srgrimes FILE *pfile; 2371590Srgrimes struct rawarc arc; 2381590Srgrimes 2391590Srgrimes pfile = openpfile(filename); 2401590Srgrimes readsamples(pfile); 2411590Srgrimes /* 2421590Srgrimes * the rest of the file consists of 2431590Srgrimes * a bunch of <from,self,count> tuples. 2441590Srgrimes */ 2451590Srgrimes while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 2461590Srgrimes# ifdef DEBUG 2471590Srgrimes if ( debug & SAMPLEDEBUG ) { 24891018Sbde printf( "[getpfile] frompc 0x%lx selfpc 0x%lx count %ld\n" , 2491590Srgrimes arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 2501590Srgrimes } 25197631Swollman# endif /* DEBUG */ 2521590Srgrimes /* 2531590Srgrimes * add this arc 2541590Srgrimes */ 2551590Srgrimes tally( &arc ); 2561590Srgrimes } 2571590Srgrimes fclose(pfile); 2581590Srgrimes} 2591590Srgrimes 2601590SrgrimesFILE * 261246783Scharnieropenpfile(char *filename) 2621590Srgrimes{ 2631590Srgrimes struct gmonhdr tmp; 2641590Srgrimes FILE *pfile; 2651590Srgrimes int size; 2661590Srgrimes int rate; 2671590Srgrimes 268105243Scharnier if((pfile = fopen(filename, "r")) == NULL) 269105243Scharnier err(1, "%s", filename); 2701590Srgrimes fread(&tmp, sizeof(struct gmonhdr), 1, pfile); 2711590Srgrimes if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc || 272105243Scharnier tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) 273105243Scharnier errx(1, "%s: incompatible with first gmon file", filename); 2741590Srgrimes gmonhdr = tmp; 2751590Srgrimes if ( gmonhdr.version == GMONVERSION ) { 2761590Srgrimes rate = gmonhdr.profrate; 2771590Srgrimes size = sizeof(struct gmonhdr); 2781590Srgrimes } else { 2791590Srgrimes fseek(pfile, sizeof(struct ophdr), SEEK_SET); 2801590Srgrimes size = sizeof(struct ophdr); 2811590Srgrimes gmonhdr.profrate = rate = hertz(); 2821590Srgrimes gmonhdr.version = GMONVERSION; 2831590Srgrimes } 2841590Srgrimes if (hz == 0) { 2851590Srgrimes hz = rate; 286105243Scharnier } else if (hz != rate) 287105243Scharnier errx(0, "%s: profile clock rate (%d) %s (%ld) in first gmon file", 2881590Srgrimes filename, rate, "incompatible with clock rate", hz); 28991738Sbde if ( gmonhdr.histcounter_type == 0 ) { 29091738Sbde /* Historical case. The type was u_short (2 bytes in practice). */ 29191738Sbde histcounter_type = 16; 29291738Sbde histcounter_size = 2; 29391738Sbde } else { 29491738Sbde histcounter_type = gmonhdr.histcounter_type; 29591738Sbde histcounter_size = abs(histcounter_type) / CHAR_BIT; 29691738Sbde } 2971590Srgrimes s_lowpc = (unsigned long) gmonhdr.lpc; 2981590Srgrimes s_highpc = (unsigned long) gmonhdr.hpc; 29991735Sbde lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2; 30091735Sbde highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2; 3011590Srgrimes sampbytes = gmonhdr.ncnt - size; 30291738Sbde nsamples = sampbytes / histcounter_size; 3031590Srgrimes# ifdef DEBUG 3041590Srgrimes if ( debug & SAMPLEDEBUG ) { 30591018Sbde printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n", 3061590Srgrimes gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt ); 30791018Sbde printf( "[openpfile] s_lowpc 0x%lx s_highpc 0x%lx\n" , 3081590Srgrimes s_lowpc , s_highpc ); 30991018Sbde printf( "[openpfile] lowpc 0x%lx highpc 0x%lx\n" , 3101590Srgrimes lowpc , highpc ); 3111590Srgrimes printf( "[openpfile] sampbytes %d nsamples %d\n" , 3121590Srgrimes sampbytes , nsamples ); 31391018Sbde printf( "[openpfile] sample rate %ld\n" , hz ); 3141590Srgrimes } 31597631Swollman# endif /* DEBUG */ 3161590Srgrimes return(pfile); 3171590Srgrimes} 3181590Srgrimes 319105243Scharniervoid 320246783Scharniertally(struct rawarc *rawp) 3211590Srgrimes{ 3221590Srgrimes nltype *parentp; 3231590Srgrimes nltype *childp; 3241590Srgrimes 3251590Srgrimes parentp = nllookup( rawp -> raw_frompc ); 3261590Srgrimes childp = nllookup( rawp -> raw_selfpc ); 3271590Srgrimes if ( parentp == 0 || childp == 0 ) 3281590Srgrimes return; 3291590Srgrimes if ( kflag 3301590Srgrimes && onlist( kfromlist , parentp -> name ) 3311590Srgrimes && onlist( ktolist , childp -> name ) ) { 3321590Srgrimes return; 3331590Srgrimes } 3341590Srgrimes childp -> ncall += rawp -> raw_count; 3351590Srgrimes# ifdef DEBUG 3361590Srgrimes if ( debug & TALLYDEBUG ) { 33791018Sbde printf( "[tally] arc from %s to %s traversed %ld times\n" , 3381590Srgrimes parentp -> name , childp -> name , rawp -> raw_count ); 3391590Srgrimes } 34097631Swollman# endif /* DEBUG */ 3411590Srgrimes addarc( parentp , childp , rawp -> raw_count ); 3421590Srgrimes} 3431590Srgrimes 3441590Srgrimes/* 3451590Srgrimes * dump out the gmon.sum file 3461590Srgrimes */ 347105243Scharniervoid 348246783Scharnierdumpsum(const char *sumfile) 3491590Srgrimes{ 3501590Srgrimes register nltype *nlp; 3511590Srgrimes register arctype *arcp; 3521590Srgrimes struct rawarc arc; 3531590Srgrimes FILE *sfile; 3541590Srgrimes 355105243Scharnier if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) 356105243Scharnier err( 1 , "%s" , sumfile ); 3571590Srgrimes /* 3581590Srgrimes * dump the header; use the last header read in 3591590Srgrimes */ 360105243Scharnier if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) 361105243Scharnier err( 1 , "%s" , sumfile ); 3621590Srgrimes /* 3631590Srgrimes * dump the samples 3641590Srgrimes */ 365105243Scharnier if (fwrite(samples, histcounter_size, nsamples, sfile) != nsamples) 366105243Scharnier err( 1 , "%s" , sumfile ); 3671590Srgrimes /* 3681590Srgrimes * dump the normalized raw arc information 3691590Srgrimes */ 3701590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3711590Srgrimes for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 3721590Srgrimes arc.raw_frompc = arcp -> arc_parentp -> value; 3731590Srgrimes arc.raw_selfpc = arcp -> arc_childp -> value; 3741590Srgrimes arc.raw_count = arcp -> arc_count; 375105243Scharnier if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) 376105243Scharnier err( 1 , "%s" , sumfile ); 3771590Srgrimes# ifdef DEBUG 3781590Srgrimes if ( debug & SAMPLEDEBUG ) { 37991018Sbde printf( "[dumpsum] frompc 0x%lx selfpc 0x%lx count %ld\n" , 3801590Srgrimes arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3811590Srgrimes } 38297631Swollman# endif /* DEBUG */ 3831590Srgrimes } 3841590Srgrimes } 3851590Srgrimes fclose( sfile ); 3861590Srgrimes} 3871590Srgrimes 38838928Sjdpstatic int 389246783Scharniervalcmp(const void *v1, const void *v2) 3901590Srgrimes{ 39138928Sjdp const nltype *p1 = (const nltype *)v1; 39238928Sjdp const nltype *p2 = (const nltype *)v2; 39338928Sjdp 3941590Srgrimes if ( p1 -> value < p2 -> value ) { 3951590Srgrimes return LESSTHAN; 3961590Srgrimes } 3971590Srgrimes if ( p1 -> value > p2 -> value ) { 3981590Srgrimes return GREATERTHAN; 3991590Srgrimes } 4001590Srgrimes return EQUALTO; 4011590Srgrimes} 4021590Srgrimes 403105243Scharniervoid 404246783Scharnierreadsamples(FILE *pfile) 4051590Srgrimes{ 406131990Sstefanf int i; 40791738Sbde intmax_t sample; 4088874Srgrimes 4091590Srgrimes if (samples == 0) { 41091738Sbde samples = (double *) calloc(nsamples, sizeof(double)); 411299877Saraujo if (samples == NULL) 412105243Scharnier errx(0, "no room for %d sample pc's", nsamples); 4131590Srgrimes } 4141590Srgrimes for (i = 0; i < nsamples; i++) { 41591738Sbde fread(&sample, histcounter_size, 1, pfile); 4161590Srgrimes if (feof(pfile)) 4171590Srgrimes break; 41891738Sbde switch ( histcounter_type ) { 41991738Sbde case -8: 42091738Sbde samples[i] += *(int8_t *)&sample; 42191738Sbde break; 42291738Sbde case 8: 42391738Sbde samples[i] += *(u_int8_t *)&sample; 42491738Sbde break; 42591738Sbde case -16: 42691738Sbde samples[i] += *(int16_t *)&sample; 42791738Sbde break; 42891738Sbde case 16: 42991738Sbde samples[i] += *(u_int16_t *)&sample; 43091738Sbde break; 43191738Sbde case -32: 43291738Sbde samples[i] += *(int32_t *)&sample; 43391738Sbde break; 43491738Sbde case 32: 43591738Sbde samples[i] += *(u_int32_t *)&sample; 43691738Sbde break; 43791738Sbde case -64: 43891738Sbde samples[i] += *(int64_t *)&sample; 43991738Sbde break; 44091738Sbde case 64: 44191738Sbde samples[i] += *(u_int64_t *)&sample; 44291738Sbde break; 44391738Sbde default: 44491738Sbde err(1, "unsupported histogram counter type %d", histcounter_type); 44591738Sbde } 4461590Srgrimes } 447105243Scharnier if (i != nsamples) 448105243Scharnier errx(1, "unexpected EOF after reading %d/%d samples", --i , nsamples ); 4491590Srgrimes} 4501590Srgrimes 4511590Srgrimes/* 4521590Srgrimes * Assign samples to the procedures to which they belong. 4531590Srgrimes * 4541590Srgrimes * There are three cases as to where pcl and pch can be 4551590Srgrimes * with respect to the routine entry addresses svalue0 and svalue1 4561590Srgrimes * as shown in the following diagram. overlap computes the 4571590Srgrimes * distance between the arrows, the fraction of the sample 4581590Srgrimes * that is to be credited to the routine which starts at svalue0. 4591590Srgrimes * 4601590Srgrimes * svalue0 svalue1 4611590Srgrimes * | | 4621590Srgrimes * v v 4631590Srgrimes * 4641590Srgrimes * +-----------------------------------------------+ 4651590Srgrimes * | | 4661590Srgrimes * | ->| |<- ->| |<- ->| |<- | 4671590Srgrimes * | | | | | | 4681590Srgrimes * +---------+ +---------+ +---------+ 4691590Srgrimes * 4701590Srgrimes * ^ ^ ^ ^ ^ ^ 4711590Srgrimes * | | | | | | 4721590Srgrimes * pcl pch pcl pch pcl pch 4731590Srgrimes * 4741590Srgrimes * For the vax we assert that samples will never fall in the first 4751590Srgrimes * two bytes of any routine, since that is the entry mask, 4761590Srgrimes * thus we give call alignentries() to adjust the entry points if 4771590Srgrimes * the entry mask falls in one bucket but the code for the routine 4781590Srgrimes * doesn't start until the next bucket. In conjunction with the 4791590Srgrimes * alignment of routine addresses, this should allow us to have 4801590Srgrimes * only one sample for every four bytes of text space and never 4811590Srgrimes * have any overlap (the two end cases, above). 4821590Srgrimes */ 483105243Scharniervoid 484246783Scharnierasgnsamples(void) 4851590Srgrimes{ 4861590Srgrimes register int j; 48791738Sbde double ccnt; 488246783Scharnier double thetime; 4891590Srgrimes unsigned long pcl, pch; 4901590Srgrimes register int i; 4911590Srgrimes unsigned long overlap; 4921590Srgrimes unsigned long svalue0, svalue1; 4931590Srgrimes 4941590Srgrimes /* read samples and assign to namelist symbols */ 4951590Srgrimes scale = highpc - lowpc; 4961590Srgrimes scale /= nsamples; 4971590Srgrimes alignentries(); 4981590Srgrimes for (i = 0, j = 1; i < nsamples; i++) { 4991590Srgrimes ccnt = samples[i]; 5001590Srgrimes if (ccnt == 0) 5011590Srgrimes continue; 50248839Ssimokawa pcl = lowpc + (unsigned long)(scale * i); 50348839Ssimokawa pch = lowpc + (unsigned long)(scale * (i + 1)); 504246783Scharnier thetime = ccnt; 5051590Srgrimes# ifdef DEBUG 5061590Srgrimes if ( debug & SAMPLEDEBUG ) { 50791738Sbde printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %.0f\n" , 5081590Srgrimes pcl , pch , ccnt ); 5091590Srgrimes } 51097631Swollman# endif /* DEBUG */ 511246783Scharnier totime += thetime; 5121590Srgrimes for (j = j - 1; j < nname; j++) { 5131590Srgrimes svalue0 = nl[j].svalue; 5141590Srgrimes svalue1 = nl[j+1].svalue; 5151590Srgrimes /* 5168874Srgrimes * if high end of tick is below entry address, 5171590Srgrimes * go for next tick. 5181590Srgrimes */ 5191590Srgrimes if (pch < svalue0) 5201590Srgrimes break; 5211590Srgrimes /* 5221590Srgrimes * if low end of tick into next routine, 5231590Srgrimes * go for next routine. 5241590Srgrimes */ 5251590Srgrimes if (pcl >= svalue1) 5261590Srgrimes continue; 5271590Srgrimes overlap = min(pch, svalue1) - max(pcl, svalue0); 5281590Srgrimes if (overlap > 0) { 5291590Srgrimes# ifdef DEBUG 5301590Srgrimes if (debug & SAMPLEDEBUG) { 53191018Sbde printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n", 53291735Sbde nl[j].value / HISTORICAL_SCALE_2, 53391735Sbde svalue0, svalue1, nl[j].name, 534246783Scharnier overlap * thetime / scale, overlap); 5351590Srgrimes } 53697631Swollman# endif /* DEBUG */ 537246783Scharnier nl[j].time += overlap * thetime / scale; 5381590Srgrimes } 5391590Srgrimes } 5401590Srgrimes } 5411590Srgrimes# ifdef DEBUG 5421590Srgrimes if (debug & SAMPLEDEBUG) { 5431590Srgrimes printf("[asgnsamples] totime %f\n", totime); 5441590Srgrimes } 54597631Swollman# endif /* DEBUG */ 5461590Srgrimes} 5471590Srgrimes 5481590Srgrimes 5491590Srgrimesunsigned long 550246783Scharniermin(unsigned long a, unsigned long b) 5511590Srgrimes{ 5521590Srgrimes if (a<b) 5531590Srgrimes return(a); 5541590Srgrimes return(b); 5551590Srgrimes} 5561590Srgrimes 5571590Srgrimesunsigned long 558246783Scharniermax(unsigned long a, unsigned long b) 5591590Srgrimes{ 5601590Srgrimes if (a>b) 5611590Srgrimes return(a); 5621590Srgrimes return(b); 5631590Srgrimes} 5641590Srgrimes 5651590Srgrimes /* 5661590Srgrimes * calculate scaled entry point addresses (to save time in asgnsamples), 5671590Srgrimes * and possibly push the scaled entry points over the entry mask, 5681590Srgrimes * if it turns out that the entry point is in one bucket and the code 5691590Srgrimes * for a routine is in the next bucket. 5701590Srgrimes */ 571105243Scharniervoid 572246783Scharnieralignentries(void) 5731590Srgrimes{ 5741590Srgrimes register struct nl *nlp; 5751590Srgrimes unsigned long bucket_of_entry; 5761590Srgrimes unsigned long bucket_of_code; 5771590Srgrimes 5781590Srgrimes for (nlp = nl; nlp < npe; nlp++) { 57991735Sbde nlp -> svalue = nlp -> value / HISTORICAL_SCALE_2; 5801590Srgrimes bucket_of_entry = (nlp->svalue - lowpc) / scale; 58191735Sbde bucket_of_code = (nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2 - 58291735Sbde lowpc) / scale; 5831590Srgrimes if (bucket_of_entry < bucket_of_code) { 5841590Srgrimes# ifdef DEBUG 5851590Srgrimes if (debug & SAMPLEDEBUG) { 58691018Sbde printf("[alignentries] pushing svalue 0x%lx to 0x%lx\n", 58791735Sbde nlp->svalue, 58891735Sbde nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2); 5891590Srgrimes } 59097631Swollman# endif /* DEBUG */ 59191735Sbde nlp->svalue += OFFSET_OF_CODE / HISTORICAL_SCALE_2; 5921590Srgrimes } 5931590Srgrimes } 5941590Srgrimes} 595