121960Sdist /* 221960Sdist * Copyright (c) 1983 Regents of the University of California. 321960Sdist * All rights reserved. The Berkeley software License Agreement 421960Sdist * specifies the terms and conditions for redistribution. 521960Sdist */ 621960Sdist 74510Speter #ifndef lint 821960Sdist char copyright[] = 921960Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021960Sdist All rights reserved.\n"; 1121960Sdist #endif not lint 124510Speter 1321960Sdist #ifndef lint 14*33226Sbostic static char sccsid[] = "@(#)gprof.c 5.3 (Berkeley) 01/02/88"; 1521960Sdist #endif not lint 1621960Sdist 174563Speter #include "gprof.h" 184510Speter 197128Speter char *whoami = "gprof"; 207128Speter 217223Speter /* 227223Speter * things which get -E excluded by default. 237223Speter */ 247223Speter char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; 257173Speter 264510Speter main(argc, argv) 277173Speter int argc; 287173Speter char **argv; 294510Speter { 307173Speter char **sp; 3116852Smckusick nltype **timesortnlp; 324510Speter 334510Speter --argc; 344510Speter argv++; 354510Speter debug = 0; 3612385Smckusick bflag = TRUE; 374510Speter while ( *argv != 0 && **argv == '-' ) { 384510Speter (*argv)++; 394866Smckusic switch ( **argv ) { 407173Speter case 'a': 417173Speter aflag = TRUE; 427173Speter break; 437173Speter case 'b': 4412385Smckusick bflag = FALSE; 457173Speter break; 467173Speter case 'c': 477173Speter cflag = TRUE; 487173Speter break; 494866Smckusic case 'd': 507173Speter dflag = TRUE; 514510Speter (*argv)++; 524510Speter debug |= atoi( *argv ); 534510Speter debug |= ANYDEBUG; 544510Speter # ifdef DEBUG 5511807Smckusick printf("[main] debug = %d\n", debug); 5611807Smckusick # else not DEBUG 5711807Smckusick printf("%s: -d ignored\n", whoami); 584510Speter # endif DEBUG 594866Smckusic break; 607223Speter case 'E': 617223Speter ++argv; 627223Speter addlist( Elist , *argv ); 637223Speter Eflag = TRUE; 647223Speter addlist( elist , *argv ); 657223Speter eflag = TRUE; 667223Speter break; 677173Speter case 'e': 687223Speter addlist( elist , *++argv ); 697173Speter eflag = TRUE; 704866Smckusic break; 717223Speter case 'F': 727223Speter ++argv; 737223Speter addlist( Flist , *argv ); 747223Speter Fflag = TRUE; 757223Speter addlist( flist , *argv ); 767223Speter fflag = TRUE; 777223Speter break; 787173Speter case 'f': 797223Speter addlist( flist , *++argv ); 807173Speter fflag = TRUE; 814866Smckusic break; 8230963Smckusick case 'k': 8330963Smckusick addlist( kfromlist , *++argv ); 8430963Smckusick addlist( ktolist , *++argv ); 8530963Smckusick kflag = TRUE; 8630963Smckusick break; 874866Smckusic case 's': 887173Speter sflag = TRUE; 894866Smckusic break; 904866Smckusic case 'z': 917173Speter zflag = TRUE; 924866Smckusic break; 934510Speter } 944510Speter argv++; 954510Speter } 964510Speter if ( *argv != 0 ) { 974510Speter a_outname = *argv; 984510Speter argv++; 994510Speter } else { 1004510Speter a_outname = A_OUTNAME; 1014510Speter } 1024510Speter if ( *argv != 0 ) { 1034563Speter gmonname = *argv; 1044510Speter argv++; 1054510Speter } else { 1064563Speter gmonname = GMONNAME; 1074510Speter } 1084510Speter /* 1097173Speter * turn off default functions 1107173Speter */ 1117223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 1127223Speter Eflag = TRUE; 1137223Speter addlist( Elist , *sp ); 1147173Speter eflag = TRUE; 1157223Speter addlist( elist , *sp ); 1167173Speter } 1177173Speter /* 11815910Speter * how many ticks per second? 11915910Speter * if we can't tell, report time in ticks. 12010249Speter */ 12110249Speter hz = hertz(); 12215910Speter if (hz == 0) { 12315910Speter hz = 1; 12415910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 12515910Speter } 12610249Speter /* 1274510Speter * get information about a.out file. 1284510Speter */ 1294510Speter getnfile(); 1304510Speter /* 1314510Speter * get information about mon.out file(s). 1324510Speter */ 1334866Smckusic do { 1344866Smckusic getpfile( gmonname ); 1354866Smckusic if ( *argv != 0 ) { 1364866Smckusic gmonname = *argv; 1374866Smckusic } 1387128Speter } while ( *argv++ != 0 ); 1394510Speter /* 1404866Smckusic * dump out a gmon.sum file if requested 1414866Smckusic */ 1427128Speter if ( sflag ) { 1437128Speter dumpsum( GMONSUM ); 1447128Speter } 1454866Smckusic /* 1464510Speter * assign samples to procedures 1474510Speter */ 1484510Speter asgnsamples(); 1494510Speter /* 15016852Smckusick * assemble the dynamic profile 1514510Speter */ 15216852Smckusick timesortnlp = doarcs(); 15316852Smckusick /* 15416852Smckusick * print the dynamic profile 15516852Smckusick */ 15616852Smckusick printgprof( timesortnlp ); 15716852Smckusick /* 15816852Smckusick * print the flat profile 15916852Smckusick */ 1604510Speter printprof(); 1614510Speter /* 16216852Smckusick * print the index 1634510Speter */ 16416852Smckusick printindex(); 1654510Speter done(); 1664510Speter } 1674510Speter 1687128Speter /* 1697128Speter * Set up string and symbol tables from a.out. 1707128Speter * and optionally the text space. 1717128Speter * On return symbol table is sorted by value. 1727128Speter */ 1734510Speter getnfile() 1744510Speter { 1754510Speter FILE *nfile; 176*33226Sbostic int valcmp(); 1774510Speter 1784510Speter nfile = fopen( a_outname ,"r"); 1794510Speter if (nfile == NULL) { 1804510Speter perror( a_outname ); 1814510Speter done(); 1824510Speter } 1834510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1844510Speter if (N_BADMAG(xbuf)) { 1857128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1864510Speter done(); 1874510Speter } 1884510Speter getstrtab(nfile); 1894510Speter getsymtab(nfile); 1904720Speter gettextspace( nfile ); 1914510Speter qsort(nl, nname, sizeof(nltype), valcmp); 1924510Speter fclose(nfile); 1934510Speter # ifdef DEBUG 1944510Speter if ( debug & AOUTDEBUG ) { 1954510Speter register int j; 1964510Speter 1974510Speter for (j = 0; j < nname; j++){ 1984510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 1994510Speter } 2004510Speter } 2014510Speter # endif DEBUG 2024510Speter } 2034510Speter 2044510Speter getstrtab(nfile) 2054510Speter FILE *nfile; 2064510Speter { 2074510Speter 2084510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 2094510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 2107128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 2117128Speter whoami , a_outname ); 2124510Speter done(); 2134510Speter } 2144510Speter strtab = (char *)calloc(ssiz, 1); 2154510Speter if (strtab == NULL) { 2167128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 2177128Speter whoami , a_outname , ssiz); 2184510Speter done(); 2194510Speter } 2204510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2217128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2227128Speter whoami , a_outname ); 2234510Speter done(); 2244510Speter } 2254510Speter } 2264510Speter 2274510Speter /* 2284510Speter * Read in symbol table 2294510Speter */ 2304510Speter getsymtab(nfile) 2314510Speter FILE *nfile; 2324510Speter { 2334510Speter register long i; 2344510Speter int askfor; 2354510Speter struct nlist nbuf; 2364510Speter 2374510Speter /* pass1 - count symbols */ 2384510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2394510Speter nname = 0; 2404510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2414510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2424845Speter if ( ! funcsymbol( &nbuf ) ) { 2434510Speter continue; 2444510Speter } 2454510Speter nname++; 2464510Speter } 2474510Speter if (nname == 0) { 2487128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2494510Speter done(); 2504510Speter } 2517128Speter askfor = nname + 1; 2524510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2534510Speter if (nl == 0) { 2547128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2557128Speter whoami, askfor * sizeof(nltype) ); 2564510Speter done(); 2574510Speter } 2584510Speter 2594510Speter /* pass2 - read symbols */ 2604510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2614510Speter npe = nl; 2624510Speter nname = 0; 2634510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2644510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2654845Speter if ( ! funcsymbol( &nbuf ) ) { 2664845Speter # ifdef DEBUG 2674845Speter if ( debug & AOUTDEBUG ) { 2684845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2694845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2704845Speter } 2714845Speter # endif DEBUG 2724510Speter continue; 2734510Speter } 2744510Speter npe->value = nbuf.n_value; 2754510Speter npe->name = strtab+nbuf.n_un.n_strx; 2764510Speter # ifdef DEBUG 2774510Speter if ( debug & AOUTDEBUG ) { 2784510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2794510Speter nname , npe -> name , npe -> value ); 2804510Speter } 2814510Speter # endif DEBUG 2824510Speter npe++; 2834510Speter nname++; 2844510Speter } 2854510Speter npe->value = -1; 2864510Speter } 2874510Speter 2884510Speter /* 2894720Speter * read in the text space of an a.out file 2904720Speter */ 2914720Speter gettextspace( nfile ) 2924720Speter FILE *nfile; 2934720Speter { 294*33226Sbostic char *malloc(); 2954720Speter 2964720Speter if ( cflag == 0 ) { 2974720Speter return; 2984720Speter } 299*33226Sbostic textspace = (u_char *) malloc( xbuf.a_text ); 3004720Speter if ( textspace == 0 ) { 3017128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 3027128Speter whoami , xbuf.a_text ); 3037128Speter fprintf( stderr , "can't do -c\n" ); 3044720Speter return; 3054720Speter } 3064720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 3074720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 3087128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 3097128Speter fprintf( stderr , "can't do -c\n" ); 3104720Speter free( textspace ); 3114720Speter textspace = 0; 3124720Speter return; 3134720Speter } 3144720Speter } 3154720Speter /* 3164563Speter * information from a gmon.out file is in two parts: 3174510Speter * an array of sampling hits within pc ranges, 3184510Speter * and the arcs. 3194510Speter */ 3204510Speter getpfile(filename) 3214510Speter char *filename; 3224510Speter { 3234510Speter FILE *pfile; 3244510Speter FILE *openpfile(); 3254510Speter struct rawarc arc; 3264510Speter 3274510Speter pfile = openpfile(filename); 3284510Speter readsamples(pfile); 3294510Speter /* 3304510Speter * the rest of the file consists of 3314510Speter * a bunch of <from,self,count> tuples. 3324510Speter */ 3334510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3344510Speter # ifdef DEBUG 3354510Speter if ( debug & SAMPLEDEBUG ) { 3364752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3374510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3384510Speter } 3394510Speter # endif DEBUG 3404510Speter /* 3414510Speter * add this arc 3424510Speter */ 3434510Speter tally( &arc ); 3444510Speter } 3454510Speter fclose(pfile); 3464510Speter } 3474510Speter 3484841Speter FILE * 3494841Speter openpfile(filename) 3504510Speter char *filename; 3514510Speter { 3524866Smckusic struct hdr tmp; 3534510Speter FILE *pfile; 3544510Speter 3554510Speter if((pfile = fopen(filename, "r")) == NULL) { 3564510Speter perror(filename); 3574510Speter done(); 3584510Speter } 3594866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3604866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3614866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3624866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3634866Smckusic done(); 3644866Smckusic } 3654866Smckusic h = tmp; 3664752Speter s_lowpc = (unsigned long) h.lowpc; 3674752Speter s_highpc = (unsigned long) h.highpc; 3687227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3697227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3704510Speter sampbytes = h.ncnt - sizeof(struct hdr); 371*33226Sbostic nsamples = sampbytes / sizeof (UNIT); 3727226Speter # ifdef DEBUG 3737226Speter if ( debug & SAMPLEDEBUG ) { 3747226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3757226Speter h.lowpc , h.highpc , h.ncnt ); 3767226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3777226Speter s_lowpc , s_highpc ); 3787226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3797226Speter lowpc , highpc ); 3807226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3817226Speter sampbytes , nsamples ); 3827226Speter } 3837226Speter # endif DEBUG 3844510Speter return(pfile); 3854510Speter } 3864510Speter 3874510Speter tally( rawp ) 3884510Speter struct rawarc *rawp; 3894510Speter { 3904510Speter nltype *parentp; 3914510Speter nltype *childp; 3924510Speter 3934510Speter parentp = nllookup( rawp -> raw_frompc ); 3944510Speter childp = nllookup( rawp -> raw_selfpc ); 39530963Smckusick if ( kflag 39630963Smckusick && onlist( kfromlist , parentp -> name ) 39730963Smckusick && onlist( ktolist , childp -> name ) ) { 39830963Smckusick return; 39930963Smckusick } 4004510Speter childp -> ncall += rawp -> raw_count; 4014510Speter # ifdef DEBUG 4024510Speter if ( debug & TALLYDEBUG ) { 4034510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 4044510Speter parentp -> name , childp -> name , rawp -> raw_count ); 4054510Speter } 4064510Speter # endif DEBUG 4074720Speter addarc( parentp , childp , rawp -> raw_count ); 4084510Speter } 4094510Speter 4104866Smckusic /* 4114866Smckusic * dump out the gmon.sum file 4124866Smckusic */ 4134866Smckusic dumpsum( sumfile ) 4144866Smckusic char *sumfile; 4154866Smckusic { 4164866Smckusic register nltype *nlp; 4174866Smckusic register arctype *arcp; 4184866Smckusic struct rawarc arc; 4194866Smckusic FILE *sfile; 4204866Smckusic 4214866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 4224866Smckusic perror( sumfile ); 4234866Smckusic done(); 4244866Smckusic } 4254866Smckusic /* 4264866Smckusic * dump the header; use the last header read in 4274866Smckusic */ 4284866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4294866Smckusic perror( sumfile ); 4304866Smckusic done(); 4314866Smckusic } 4324866Smckusic /* 4334866Smckusic * dump the samples 4344866Smckusic */ 435*33226Sbostic if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 4364866Smckusic perror( sumfile ); 4374866Smckusic done(); 4384866Smckusic } 4394866Smckusic /* 4404866Smckusic * dump the normalized raw arc information 4414866Smckusic */ 44211807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4434866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4444866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4454866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4464866Smckusic arc.raw_count = arcp -> arc_count; 4474866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4484866Smckusic perror( sumfile ); 4494866Smckusic done(); 4504866Smckusic } 4514866Smckusic # ifdef DEBUG 4524866Smckusic if ( debug & SAMPLEDEBUG ) { 4534866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4544866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4554866Smckusic } 4564866Smckusic # endif DEBUG 4574866Smckusic } 4584866Smckusic } 4594866Smckusic fclose( sfile ); 4604866Smckusic } 4614866Smckusic 4624510Speter valcmp(p1, p2) 4634510Speter nltype *p1, *p2; 4644510Speter { 4654510Speter if ( p1 -> value < p2 -> value ) { 4664510Speter return LESSTHAN; 4674510Speter } 4684510Speter if ( p1 -> value > p2 -> value ) { 4694510Speter return GREATERTHAN; 4704510Speter } 4714510Speter return EQUALTO; 4724510Speter } 4734510Speter 4744510Speter readsamples(pfile) 4754510Speter FILE *pfile; 4764510Speter { 4774510Speter register i; 478*33226Sbostic UNIT sample; 4794510Speter 4804510Speter if (samples == 0) { 481*33226Sbostic samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 4824510Speter if (samples == 0) { 4837128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 484*33226Sbostic whoami , sampbytes / sizeof (UNIT)); 4854510Speter done(); 4864510Speter } 4874510Speter } 4884510Speter for (i = 0; i < nsamples; i++) { 489*33226Sbostic fread(&sample, sizeof (UNIT), 1, pfile); 4904510Speter if (feof(pfile)) 4914510Speter break; 4924510Speter samples[i] += sample; 4934510Speter } 4944510Speter if (i != nsamples) { 4954510Speter fprintf(stderr, 4967128Speter "%s: unexpected EOF after reading %d/%d samples\n", 4977128Speter whoami , --i , nsamples ); 4984510Speter done(); 4994510Speter } 5004510Speter } 5014510Speter 5024510Speter /* 50311523Smckusick * Assign samples to the procedures to which they belong. 50411523Smckusick * 50511523Smckusick * There are three cases as to where pcl and pch can be 50611523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 50711523Smckusick * as shown in the following diagram. overlap computes the 50811523Smckusick * distance between the arrows, the fraction of the sample 50911523Smckusick * that is to be credited to the routine which starts at svalue0. 51011523Smckusick * 51111523Smckusick * svalue0 svalue1 51211523Smckusick * | | 51311523Smckusick * v v 51411523Smckusick * 51511523Smckusick * +-----------------------------------------------+ 51611523Smckusick * | | 51711523Smckusick * | ->| |<- ->| |<- ->| |<- | 51811523Smckusick * | | | | | | 51911523Smckusick * +---------+ +---------+ +---------+ 52011523Smckusick * 52111523Smckusick * ^ ^ ^ ^ ^ ^ 52211523Smckusick * | | | | | | 52311523Smckusick * pcl pch pcl pch pcl pch 52411523Smckusick * 52511523Smckusick * For the vax we assert that samples will never fall in the first 52611807Smckusick * two bytes of any routine, since that is the entry mask, 52711807Smckusick * thus we give call alignentries() to adjust the entry points if 52811807Smckusick * the entry mask falls in one bucket but the code for the routine 52911807Smckusick * doesn't start until the next bucket. In conjunction with the 53011807Smckusick * alignment of routine addresses, this should allow us to have 53111807Smckusick * only one sample for every four bytes of text space and never 53211807Smckusick * have any overlap (the two end cases, above). 5334510Speter */ 5344510Speter asgnsamples() 5354510Speter { 5364510Speter register int j; 537*33226Sbostic UNIT ccnt; 5384510Speter double time; 5394510Speter unsigned long pcl, pch; 5404510Speter register int i; 5414841Speter unsigned long overlap; 5424510Speter unsigned long svalue0, svalue1; 5434510Speter 5444510Speter /* read samples and assign to namelist symbols */ 5454510Speter scale = highpc - lowpc; 5464510Speter scale /= nsamples; 54711807Smckusick alignentries(); 5487257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5494510Speter ccnt = samples[i]; 5504510Speter if (ccnt == 0) 5514510Speter continue; 55211523Smckusick pcl = lowpc + scale * i; 55311523Smckusick pch = lowpc + scale * (i + 1); 5544510Speter time = ccnt; 5554510Speter # ifdef DEBUG 5564510Speter if ( debug & SAMPLEDEBUG ) { 5575072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5585072Smckusic pcl , pch , ccnt ); 5594510Speter } 5604510Speter # endif DEBUG 5614510Speter totime += time; 5627252Smckusick for (j = j - 1; j < nname; j++) { 56311807Smckusick svalue0 = nl[j].svalue; 56411807Smckusick svalue1 = nl[j+1].svalue; 56511807Smckusick /* 56611807Smckusick * if high end of tick is below entry address, 56711807Smckusick * go for next tick. 56811807Smckusick */ 5694510Speter if (pch < svalue0) 5704510Speter break; 57111807Smckusick /* 57211807Smckusick * if low end of tick into next routine, 57311807Smckusick * go for next routine. 57411807Smckusick */ 5754510Speter if (pcl >= svalue1) 5764510Speter continue; 57711807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 57811523Smckusick if (overlap > 0) { 5794510Speter # ifdef DEBUG 58011523Smckusick if (debug & SAMPLEDEBUG) { 58111807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 58211807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 58311807Smckusick nl[j].name, 58411807Smckusick overlap * time / scale, overlap); 5854510Speter } 5864510Speter # endif DEBUG 58711523Smckusick nl[j].time += overlap * time / scale; 5884510Speter } 5894510Speter } 5904510Speter } 5914510Speter # ifdef DEBUG 59211523Smckusick if (debug & SAMPLEDEBUG) { 59311523Smckusick printf("[asgnsamples] totime %f\n", totime); 5944510Speter } 5954510Speter # endif DEBUG 5964510Speter } 5974510Speter 5984510Speter 5994841Speter unsigned long 6004510Speter min(a, b) 6014841Speter unsigned long a,b; 6024510Speter { 6034510Speter if (a<b) 6044510Speter return(a); 6054510Speter return(b); 6064510Speter } 6074510Speter 6084841Speter unsigned long 6094510Speter max(a, b) 6104841Speter unsigned long a,b; 6114510Speter { 6124510Speter if (a>b) 6134510Speter return(a); 6144510Speter return(b); 6154510Speter } 6164510Speter 61711807Smckusick /* 61811807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 61911807Smckusick * and possibly push the scaled entry points over the entry mask, 62011807Smckusick * if it turns out that the entry point is in one bucket and the code 62111807Smckusick * for a routine is in the next bucket. 62211807Smckusick */ 62311807Smckusick alignentries() 62411807Smckusick { 62511807Smckusick register struct nl *nlp; 62611807Smckusick unsigned long bucket_of_entry; 62711807Smckusick unsigned long bucket_of_code; 62811807Smckusick 62911807Smckusick for (nlp = nl; nlp < npe; nlp++) { 63011807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 63111807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 63211807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 63311807Smckusick if (bucket_of_entry < bucket_of_code) { 63411807Smckusick # ifdef DEBUG 63511807Smckusick if (debug & SAMPLEDEBUG) { 63611807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 63711807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 63811807Smckusick } 63911807Smckusick # endif DEBUG 64011807Smckusick nlp->svalue += UNITS_TO_CODE; 64111807Smckusick } 64211807Smckusick } 64311807Smckusick } 64411807Smckusick 6454845Speter bool 6464845Speter funcsymbol( nlistp ) 6474845Speter struct nlist *nlistp; 6484845Speter { 6494845Speter extern char *strtab; /* string table from a.out */ 6504851Speter extern int aflag; /* if static functions aren't desired */ 6514845Speter char *name; 6524845Speter 6534845Speter /* 6544845Speter * must be a text symbol, 6554851Speter * and static text symbols don't qualify if aflag set. 6564845Speter */ 6574845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6584851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6594845Speter return FALSE; 6604845Speter } 6614845Speter /* 6627128Speter * can't have any `funny' characters in name, 6634845Speter * where `funny' includes `.', .o file names 6644845Speter * and `$', pascal labels. 6654845Speter */ 6664845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6674845Speter if ( *name == '.' || *name == '$' ) { 6684845Speter return FALSE; 6694845Speter } 6704845Speter } 6714845Speter return TRUE; 6724845Speter } 6734845Speter 6744510Speter done() 6754510Speter { 6764510Speter 6774510Speter exit(0); 6784510Speter } 679