1*21960Sdist /* 2*21960Sdist * Copyright (c) 1983 Regents of the University of California. 3*21960Sdist * All rights reserved. The Berkeley software License Agreement 4*21960Sdist * specifies the terms and conditions for redistribution. 5*21960Sdist */ 6*21960Sdist 74510Speter #ifndef lint 8*21960Sdist char copyright[] = 9*21960Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*21960Sdist All rights reserved.\n"; 11*21960Sdist #endif not lint 124510Speter 13*21960Sdist #ifndef lint 14*21960Sdist static char sccsid[] = "@(#)gprof.c 5.1 (Berkeley) 06/04/85"; 15*21960Sdist #endif not lint 16*21960Sdist 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; 824866Smckusic case 's': 837173Speter sflag = TRUE; 844866Smckusic break; 854866Smckusic case 'z': 867173Speter zflag = TRUE; 874866Smckusic break; 884510Speter } 894510Speter argv++; 904510Speter } 914510Speter if ( *argv != 0 ) { 924510Speter a_outname = *argv; 934510Speter argv++; 944510Speter } else { 954510Speter a_outname = A_OUTNAME; 964510Speter } 974510Speter if ( *argv != 0 ) { 984563Speter gmonname = *argv; 994510Speter argv++; 1004510Speter } else { 1014563Speter gmonname = GMONNAME; 1024510Speter } 1034510Speter /* 1047173Speter * turn off default functions 1057173Speter */ 1067223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 1077223Speter Eflag = TRUE; 1087223Speter addlist( Elist , *sp ); 1097173Speter eflag = TRUE; 1107223Speter addlist( elist , *sp ); 1117173Speter } 1127173Speter /* 11315910Speter * how many ticks per second? 11415910Speter * if we can't tell, report time in ticks. 11510249Speter */ 11610249Speter hz = hertz(); 11715910Speter if (hz == 0) { 11815910Speter hz = 1; 11915910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 12015910Speter } 12110249Speter /* 1224510Speter * get information about a.out file. 1234510Speter */ 1244510Speter getnfile(); 1254510Speter /* 1264510Speter * get information about mon.out file(s). 1274510Speter */ 1284866Smckusic do { 1294866Smckusic getpfile( gmonname ); 1304866Smckusic if ( *argv != 0 ) { 1314866Smckusic gmonname = *argv; 1324866Smckusic } 1337128Speter } while ( *argv++ != 0 ); 1344510Speter /* 1354866Smckusic * dump out a gmon.sum file if requested 1364866Smckusic */ 1377128Speter if ( sflag ) { 1387128Speter dumpsum( GMONSUM ); 1397128Speter } 1404866Smckusic /* 1414510Speter * assign samples to procedures 1424510Speter */ 1434510Speter asgnsamples(); 1444510Speter /* 14516852Smckusick * assemble the dynamic profile 1464510Speter */ 14716852Smckusick timesortnlp = doarcs(); 14816852Smckusick /* 14916852Smckusick * print the dynamic profile 15016852Smckusick */ 15116852Smckusick printgprof( timesortnlp ); 15216852Smckusick /* 15316852Smckusick * print the flat profile 15416852Smckusick */ 1554510Speter printprof(); 1564510Speter /* 15716852Smckusick * print the index 1584510Speter */ 15916852Smckusick printindex(); 1604510Speter done(); 1614510Speter } 1624510Speter 1637128Speter /* 1647128Speter * Set up string and symbol tables from a.out. 1657128Speter * and optionally the text space. 1667128Speter * On return symbol table is sorted by value. 1677128Speter */ 1684510Speter getnfile() 1694510Speter { 1704510Speter FILE *nfile; 1714510Speter 1724510Speter nfile = fopen( a_outname ,"r"); 1734510Speter if (nfile == NULL) { 1744510Speter perror( a_outname ); 1754510Speter done(); 1764510Speter } 1774510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1784510Speter if (N_BADMAG(xbuf)) { 1797128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1804510Speter done(); 1814510Speter } 1824510Speter getstrtab(nfile); 1834510Speter getsymtab(nfile); 1844720Speter gettextspace( nfile ); 1854510Speter qsort(nl, nname, sizeof(nltype), valcmp); 1864510Speter fclose(nfile); 1874510Speter # ifdef DEBUG 1884510Speter if ( debug & AOUTDEBUG ) { 1894510Speter register int j; 1904510Speter 1914510Speter for (j = 0; j < nname; j++){ 1924510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 1934510Speter } 1944510Speter } 1954510Speter # endif DEBUG 1964510Speter } 1974510Speter 1984510Speter getstrtab(nfile) 1994510Speter FILE *nfile; 2004510Speter { 2014510Speter 2024510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 2034510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 2047128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 2057128Speter whoami , a_outname ); 2064510Speter done(); 2074510Speter } 2084510Speter strtab = (char *)calloc(ssiz, 1); 2094510Speter if (strtab == NULL) { 2107128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 2117128Speter whoami , a_outname , ssiz); 2124510Speter done(); 2134510Speter } 2144510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2157128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2167128Speter whoami , a_outname ); 2174510Speter done(); 2184510Speter } 2194510Speter } 2204510Speter 2214510Speter /* 2224510Speter * Read in symbol table 2234510Speter */ 2244510Speter getsymtab(nfile) 2254510Speter FILE *nfile; 2264510Speter { 2274510Speter register long i; 2284510Speter int askfor; 2294510Speter struct nlist nbuf; 2304510Speter 2314510Speter /* pass1 - count symbols */ 2324510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2334510Speter nname = 0; 2344510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2354510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2364845Speter if ( ! funcsymbol( &nbuf ) ) { 2374510Speter continue; 2384510Speter } 2394510Speter nname++; 2404510Speter } 2414510Speter if (nname == 0) { 2427128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2434510Speter done(); 2444510Speter } 2457128Speter askfor = nname + 1; 2464510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2474510Speter if (nl == 0) { 2487128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2497128Speter whoami, askfor * sizeof(nltype) ); 2504510Speter done(); 2514510Speter } 2524510Speter 2534510Speter /* pass2 - read symbols */ 2544510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2554510Speter npe = nl; 2564510Speter nname = 0; 2574510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2584510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2594845Speter if ( ! funcsymbol( &nbuf ) ) { 2604845Speter # ifdef DEBUG 2614845Speter if ( debug & AOUTDEBUG ) { 2624845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2634845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2644845Speter } 2654845Speter # endif DEBUG 2664510Speter continue; 2674510Speter } 2684510Speter npe->value = nbuf.n_value; 2694510Speter npe->name = strtab+nbuf.n_un.n_strx; 2704510Speter # ifdef DEBUG 2714510Speter if ( debug & AOUTDEBUG ) { 2724510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2734510Speter nname , npe -> name , npe -> value ); 2744510Speter } 2754510Speter # endif DEBUG 2764510Speter npe++; 2774510Speter nname++; 2784510Speter } 2794510Speter npe->value = -1; 2804510Speter } 2814510Speter 2824510Speter /* 2834720Speter * read in the text space of an a.out file 2844720Speter */ 2854720Speter gettextspace( nfile ) 2864720Speter FILE *nfile; 2874720Speter { 2884720Speter unsigned char *malloc(); 2894720Speter 2904720Speter if ( cflag == 0 ) { 2914720Speter return; 2924720Speter } 2934720Speter textspace = malloc( xbuf.a_text ); 2944720Speter if ( textspace == 0 ) { 2957128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 2967128Speter whoami , xbuf.a_text ); 2977128Speter fprintf( stderr , "can't do -c\n" ); 2984720Speter return; 2994720Speter } 3004720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 3014720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 3027128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 3037128Speter fprintf( stderr , "can't do -c\n" ); 3044720Speter free( textspace ); 3054720Speter textspace = 0; 3064720Speter return; 3074720Speter } 3084720Speter } 3094720Speter /* 3104563Speter * information from a gmon.out file is in two parts: 3114510Speter * an array of sampling hits within pc ranges, 3124510Speter * and the arcs. 3134510Speter */ 3144510Speter getpfile(filename) 3154510Speter char *filename; 3164510Speter { 3174510Speter FILE *pfile; 3184510Speter FILE *openpfile(); 3194510Speter struct rawarc arc; 3204510Speter 3214510Speter pfile = openpfile(filename); 3224510Speter readsamples(pfile); 3234510Speter /* 3244510Speter * the rest of the file consists of 3254510Speter * a bunch of <from,self,count> tuples. 3264510Speter */ 3274510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3284510Speter # ifdef DEBUG 3294510Speter if ( debug & SAMPLEDEBUG ) { 3304752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3314510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3324510Speter } 3334510Speter # endif DEBUG 3344510Speter /* 3354510Speter * add this arc 3364510Speter */ 3374510Speter tally( &arc ); 3384510Speter } 3394510Speter fclose(pfile); 3404510Speter } 3414510Speter 3424841Speter FILE * 3434841Speter openpfile(filename) 3444510Speter char *filename; 3454510Speter { 3464866Smckusic struct hdr tmp; 3474510Speter FILE *pfile; 3484510Speter 3494510Speter if((pfile = fopen(filename, "r")) == NULL) { 3504510Speter perror(filename); 3514510Speter done(); 3524510Speter } 3534866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3544866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3554866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3564866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3574866Smckusic done(); 3584866Smckusic } 3594866Smckusic h = tmp; 3604752Speter s_lowpc = (unsigned long) h.lowpc; 3614752Speter s_highpc = (unsigned long) h.highpc; 3627227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3637227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3644510Speter sampbytes = h.ncnt - sizeof(struct hdr); 3654510Speter nsamples = sampbytes / sizeof (unsigned UNIT); 3667226Speter # ifdef DEBUG 3677226Speter if ( debug & SAMPLEDEBUG ) { 3687226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3697226Speter h.lowpc , h.highpc , h.ncnt ); 3707226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3717226Speter s_lowpc , s_highpc ); 3727226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3737226Speter lowpc , highpc ); 3747226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3757226Speter sampbytes , nsamples ); 3767226Speter } 3777226Speter # endif DEBUG 3784510Speter return(pfile); 3794510Speter } 3804510Speter 3814510Speter tally( rawp ) 3824510Speter struct rawarc *rawp; 3834510Speter { 3844510Speter nltype *parentp; 3854510Speter nltype *childp; 3864510Speter 3874510Speter parentp = nllookup( rawp -> raw_frompc ); 3884510Speter childp = nllookup( rawp -> raw_selfpc ); 3894510Speter childp -> ncall += rawp -> raw_count; 3904510Speter # ifdef DEBUG 3914510Speter if ( debug & TALLYDEBUG ) { 3924510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 3934510Speter parentp -> name , childp -> name , rawp -> raw_count ); 3944510Speter } 3954510Speter # endif DEBUG 3964720Speter addarc( parentp , childp , rawp -> raw_count ); 3974510Speter } 3984510Speter 3994866Smckusic /* 4004866Smckusic * dump out the gmon.sum file 4014866Smckusic */ 4024866Smckusic dumpsum( sumfile ) 4034866Smckusic char *sumfile; 4044866Smckusic { 4054866Smckusic register nltype *nlp; 4064866Smckusic register arctype *arcp; 4074866Smckusic struct rawarc arc; 4084866Smckusic FILE *sfile; 4094866Smckusic 4104866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 4114866Smckusic perror( sumfile ); 4124866Smckusic done(); 4134866Smckusic } 4144866Smckusic /* 4154866Smckusic * dump the header; use the last header read in 4164866Smckusic */ 4174866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4184866Smckusic perror( sumfile ); 4194866Smckusic done(); 4204866Smckusic } 4214866Smckusic /* 4224866Smckusic * dump the samples 4234866Smckusic */ 4244866Smckusic if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) { 4254866Smckusic perror( sumfile ); 4264866Smckusic done(); 4274866Smckusic } 4284866Smckusic /* 4294866Smckusic * dump the normalized raw arc information 4304866Smckusic */ 43111807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4324866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4334866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4344866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4354866Smckusic arc.raw_count = arcp -> arc_count; 4364866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4374866Smckusic perror( sumfile ); 4384866Smckusic done(); 4394866Smckusic } 4404866Smckusic # ifdef DEBUG 4414866Smckusic if ( debug & SAMPLEDEBUG ) { 4424866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4434866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4444866Smckusic } 4454866Smckusic # endif DEBUG 4464866Smckusic } 4474866Smckusic } 4484866Smckusic fclose( sfile ); 4494866Smckusic } 4504866Smckusic 4514510Speter valcmp(p1, p2) 4524510Speter nltype *p1, *p2; 4534510Speter { 4544510Speter if ( p1 -> value < p2 -> value ) { 4554510Speter return LESSTHAN; 4564510Speter } 4574510Speter if ( p1 -> value > p2 -> value ) { 4584510Speter return GREATERTHAN; 4594510Speter } 4604510Speter return EQUALTO; 4614510Speter } 4624510Speter 4634510Speter readsamples(pfile) 4644510Speter FILE *pfile; 4654510Speter { 4664510Speter register i; 4674510Speter unsigned UNIT sample; 4684510Speter 4694510Speter if (samples == 0) { 4704510Speter samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT)); 4714510Speter if (samples == 0) { 4727128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 4737128Speter whoami , sampbytes / sizeof (unsigned UNIT)); 4744510Speter done(); 4754510Speter } 4764510Speter } 4774510Speter for (i = 0; i < nsamples; i++) { 4784510Speter fread(&sample, sizeof (unsigned UNIT), 1, pfile); 4794510Speter if (feof(pfile)) 4804510Speter break; 4814510Speter samples[i] += sample; 4824510Speter } 4834510Speter if (i != nsamples) { 4844510Speter fprintf(stderr, 4857128Speter "%s: unexpected EOF after reading %d/%d samples\n", 4867128Speter whoami , --i , nsamples ); 4874510Speter done(); 4884510Speter } 4894510Speter } 4904510Speter 4914510Speter /* 49211523Smckusick * Assign samples to the procedures to which they belong. 49311523Smckusick * 49411523Smckusick * There are three cases as to where pcl and pch can be 49511523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 49611523Smckusick * as shown in the following diagram. overlap computes the 49711523Smckusick * distance between the arrows, the fraction of the sample 49811523Smckusick * that is to be credited to the routine which starts at svalue0. 49911523Smckusick * 50011523Smckusick * svalue0 svalue1 50111523Smckusick * | | 50211523Smckusick * v v 50311523Smckusick * 50411523Smckusick * +-----------------------------------------------+ 50511523Smckusick * | | 50611523Smckusick * | ->| |<- ->| |<- ->| |<- | 50711523Smckusick * | | | | | | 50811523Smckusick * +---------+ +---------+ +---------+ 50911523Smckusick * 51011523Smckusick * ^ ^ ^ ^ ^ ^ 51111523Smckusick * | | | | | | 51211523Smckusick * pcl pch pcl pch pcl pch 51311523Smckusick * 51411523Smckusick * For the vax we assert that samples will never fall in the first 51511807Smckusick * two bytes of any routine, since that is the entry mask, 51611807Smckusick * thus we give call alignentries() to adjust the entry points if 51711807Smckusick * the entry mask falls in one bucket but the code for the routine 51811807Smckusick * doesn't start until the next bucket. In conjunction with the 51911807Smckusick * alignment of routine addresses, this should allow us to have 52011807Smckusick * only one sample for every four bytes of text space and never 52111807Smckusick * have any overlap (the two end cases, above). 5224510Speter */ 5234510Speter asgnsamples() 5244510Speter { 5254510Speter register int j; 5264510Speter unsigned UNIT ccnt; 5274510Speter double time; 5284510Speter unsigned long pcl, pch; 5294510Speter register int i; 5304841Speter unsigned long overlap; 5314510Speter unsigned long svalue0, svalue1; 5324510Speter 5334510Speter /* read samples and assign to namelist symbols */ 5344510Speter scale = highpc - lowpc; 5354510Speter scale /= nsamples; 53611807Smckusick alignentries(); 5377257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5384510Speter ccnt = samples[i]; 5394510Speter if (ccnt == 0) 5404510Speter continue; 54111523Smckusick pcl = lowpc + scale * i; 54211523Smckusick pch = lowpc + scale * (i + 1); 5434510Speter time = ccnt; 5444510Speter # ifdef DEBUG 5454510Speter if ( debug & SAMPLEDEBUG ) { 5465072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5475072Smckusic pcl , pch , ccnt ); 5484510Speter } 5494510Speter # endif DEBUG 5504510Speter totime += time; 5517252Smckusick for (j = j - 1; j < nname; j++) { 55211807Smckusick svalue0 = nl[j].svalue; 55311807Smckusick svalue1 = nl[j+1].svalue; 55411807Smckusick /* 55511807Smckusick * if high end of tick is below entry address, 55611807Smckusick * go for next tick. 55711807Smckusick */ 5584510Speter if (pch < svalue0) 5594510Speter break; 56011807Smckusick /* 56111807Smckusick * if low end of tick into next routine, 56211807Smckusick * go for next routine. 56311807Smckusick */ 5644510Speter if (pcl >= svalue1) 5654510Speter continue; 56611807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 56711523Smckusick if (overlap > 0) { 5684510Speter # ifdef DEBUG 56911523Smckusick if (debug & SAMPLEDEBUG) { 57011807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 57111807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 57211807Smckusick nl[j].name, 57311807Smckusick overlap * time / scale, overlap); 5744510Speter } 5754510Speter # endif DEBUG 57611523Smckusick nl[j].time += overlap * time / scale; 5774510Speter } 5784510Speter } 5794510Speter } 5804510Speter # ifdef DEBUG 58111523Smckusick if (debug & SAMPLEDEBUG) { 58211523Smckusick printf("[asgnsamples] totime %f\n", totime); 5834510Speter } 5844510Speter # endif DEBUG 5854510Speter } 5864510Speter 5874510Speter 5884841Speter unsigned long 5894510Speter min(a, b) 5904841Speter unsigned long a,b; 5914510Speter { 5924510Speter if (a<b) 5934510Speter return(a); 5944510Speter return(b); 5954510Speter } 5964510Speter 5974841Speter unsigned long 5984510Speter max(a, b) 5994841Speter unsigned long a,b; 6004510Speter { 6014510Speter if (a>b) 6024510Speter return(a); 6034510Speter return(b); 6044510Speter } 6054510Speter 60611807Smckusick /* 60711807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 60811807Smckusick * and possibly push the scaled entry points over the entry mask, 60911807Smckusick * if it turns out that the entry point is in one bucket and the code 61011807Smckusick * for a routine is in the next bucket. 61111807Smckusick */ 61211807Smckusick alignentries() 61311807Smckusick { 61411807Smckusick register struct nl *nlp; 61511807Smckusick unsigned long bucket_of_entry; 61611807Smckusick unsigned long bucket_of_code; 61711807Smckusick 61811807Smckusick for (nlp = nl; nlp < npe; nlp++) { 61911807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 62011807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 62111807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 62211807Smckusick if (bucket_of_entry < bucket_of_code) { 62311807Smckusick # ifdef DEBUG 62411807Smckusick if (debug & SAMPLEDEBUG) { 62511807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 62611807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 62711807Smckusick } 62811807Smckusick # endif DEBUG 62911807Smckusick nlp->svalue += UNITS_TO_CODE; 63011807Smckusick } 63111807Smckusick } 63211807Smckusick } 63311807Smckusick 6344845Speter bool 6354845Speter funcsymbol( nlistp ) 6364845Speter struct nlist *nlistp; 6374845Speter { 6384845Speter extern char *strtab; /* string table from a.out */ 6394851Speter extern int aflag; /* if static functions aren't desired */ 6404845Speter char *name; 6414845Speter 6424845Speter /* 6434845Speter * must be a text symbol, 6444851Speter * and static text symbols don't qualify if aflag set. 6454845Speter */ 6464845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6474851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6484845Speter return FALSE; 6494845Speter } 6504845Speter /* 6517128Speter * can't have any `funny' characters in name, 6524845Speter * where `funny' includes `.', .o file names 6534845Speter * and `$', pascal labels. 6544845Speter */ 6554845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6564845Speter if ( *name == '.' || *name == '$' ) { 6574845Speter return FALSE; 6584845Speter } 6594845Speter } 6604845Speter return TRUE; 6614845Speter } 6624845Speter 6634510Speter done() 6644510Speter { 6654510Speter 6664510Speter exit(0); 6674510Speter } 668