14510Speter #ifndef lint 2*16852Smckusick static char *sccsid = "@(#)gprof.c 1.24 (Berkeley) 08/07/84"; 34510Speter #endif lint 44510Speter 54563Speter #include "gprof.h" 64510Speter 77128Speter char *whoami = "gprof"; 87128Speter 97223Speter /* 107223Speter * things which get -E excluded by default. 117223Speter */ 127223Speter char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; 137173Speter 144510Speter main(argc, argv) 157173Speter int argc; 167173Speter char **argv; 174510Speter { 187173Speter char **sp; 19*16852Smckusick nltype **timesortnlp; 204510Speter 214510Speter --argc; 224510Speter argv++; 234510Speter debug = 0; 2412385Smckusick bflag = TRUE; 254510Speter while ( *argv != 0 && **argv == '-' ) { 264510Speter (*argv)++; 274866Smckusic switch ( **argv ) { 287173Speter case 'a': 297173Speter aflag = TRUE; 307173Speter break; 317173Speter case 'b': 3212385Smckusick bflag = FALSE; 337173Speter break; 347173Speter case 'c': 357173Speter cflag = TRUE; 367173Speter break; 374866Smckusic case 'd': 387173Speter dflag = TRUE; 394510Speter (*argv)++; 404510Speter debug |= atoi( *argv ); 414510Speter debug |= ANYDEBUG; 424510Speter # ifdef DEBUG 4311807Smckusick printf("[main] debug = %d\n", debug); 4411807Smckusick # else not DEBUG 4511807Smckusick printf("%s: -d ignored\n", whoami); 464510Speter # endif DEBUG 474866Smckusic break; 487223Speter case 'E': 497223Speter ++argv; 507223Speter addlist( Elist , *argv ); 517223Speter Eflag = TRUE; 527223Speter addlist( elist , *argv ); 537223Speter eflag = TRUE; 547223Speter break; 557173Speter case 'e': 567223Speter addlist( elist , *++argv ); 577173Speter eflag = TRUE; 584866Smckusic break; 597223Speter case 'F': 607223Speter ++argv; 617223Speter addlist( Flist , *argv ); 627223Speter Fflag = TRUE; 637223Speter addlist( flist , *argv ); 647223Speter fflag = TRUE; 657223Speter break; 667173Speter case 'f': 677223Speter addlist( flist , *++argv ); 687173Speter fflag = TRUE; 694866Smckusic break; 704866Smckusic case 's': 717173Speter sflag = TRUE; 724866Smckusic break; 734866Smckusic case 'z': 747173Speter zflag = TRUE; 754866Smckusic break; 764510Speter } 774510Speter argv++; 784510Speter } 794510Speter if ( *argv != 0 ) { 804510Speter a_outname = *argv; 814510Speter argv++; 824510Speter } else { 834510Speter a_outname = A_OUTNAME; 844510Speter } 854510Speter if ( *argv != 0 ) { 864563Speter gmonname = *argv; 874510Speter argv++; 884510Speter } else { 894563Speter gmonname = GMONNAME; 904510Speter } 914510Speter /* 927173Speter * turn off default functions 937173Speter */ 947223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 957223Speter Eflag = TRUE; 967223Speter addlist( Elist , *sp ); 977173Speter eflag = TRUE; 987223Speter addlist( elist , *sp ); 997173Speter } 1007173Speter /* 10115910Speter * how many ticks per second? 10215910Speter * if we can't tell, report time in ticks. 10310249Speter */ 10410249Speter hz = hertz(); 10515910Speter if (hz == 0) { 10615910Speter hz = 1; 10715910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 10815910Speter } 10910249Speter /* 1104510Speter * get information about a.out file. 1114510Speter */ 1124510Speter getnfile(); 1134510Speter /* 1144510Speter * get information about mon.out file(s). 1154510Speter */ 1164866Smckusic do { 1174866Smckusic getpfile( gmonname ); 1184866Smckusic if ( *argv != 0 ) { 1194866Smckusic gmonname = *argv; 1204866Smckusic } 1217128Speter } while ( *argv++ != 0 ); 1224510Speter /* 1234866Smckusic * dump out a gmon.sum file if requested 1244866Smckusic */ 1257128Speter if ( sflag ) { 1267128Speter dumpsum( GMONSUM ); 1277128Speter } 1284866Smckusic /* 1294510Speter * assign samples to procedures 1304510Speter */ 1314510Speter asgnsamples(); 1324510Speter /* 133*16852Smckusick * assemble the dynamic profile 1344510Speter */ 135*16852Smckusick timesortnlp = doarcs(); 136*16852Smckusick /* 137*16852Smckusick * print the dynamic profile 138*16852Smckusick */ 139*16852Smckusick printgprof( timesortnlp ); 140*16852Smckusick /* 141*16852Smckusick * print the flat profile 142*16852Smckusick */ 1434510Speter printprof(); 1444510Speter /* 145*16852Smckusick * print the index 1464510Speter */ 147*16852Smckusick printindex(); 1484510Speter done(); 1494510Speter } 1504510Speter 1517128Speter /* 1527128Speter * Set up string and symbol tables from a.out. 1537128Speter * and optionally the text space. 1547128Speter * On return symbol table is sorted by value. 1557128Speter */ 1564510Speter getnfile() 1574510Speter { 1584510Speter FILE *nfile; 1594510Speter 1604510Speter nfile = fopen( a_outname ,"r"); 1614510Speter if (nfile == NULL) { 1624510Speter perror( a_outname ); 1634510Speter done(); 1644510Speter } 1654510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1664510Speter if (N_BADMAG(xbuf)) { 1677128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1684510Speter done(); 1694510Speter } 1704510Speter getstrtab(nfile); 1714510Speter getsymtab(nfile); 1724720Speter gettextspace( nfile ); 1734510Speter qsort(nl, nname, sizeof(nltype), valcmp); 1744510Speter fclose(nfile); 1754510Speter # ifdef DEBUG 1764510Speter if ( debug & AOUTDEBUG ) { 1774510Speter register int j; 1784510Speter 1794510Speter for (j = 0; j < nname; j++){ 1804510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 1814510Speter } 1824510Speter } 1834510Speter # endif DEBUG 1844510Speter } 1854510Speter 1864510Speter getstrtab(nfile) 1874510Speter FILE *nfile; 1884510Speter { 1894510Speter 1904510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 1914510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 1927128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 1937128Speter whoami , a_outname ); 1944510Speter done(); 1954510Speter } 1964510Speter strtab = (char *)calloc(ssiz, 1); 1974510Speter if (strtab == NULL) { 1987128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 1997128Speter whoami , a_outname , ssiz); 2004510Speter done(); 2014510Speter } 2024510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 2037128Speter fprintf(stderr, "%s: %s: error reading string table\n", 2047128Speter whoami , a_outname ); 2054510Speter done(); 2064510Speter } 2074510Speter } 2084510Speter 2094510Speter /* 2104510Speter * Read in symbol table 2114510Speter */ 2124510Speter getsymtab(nfile) 2134510Speter FILE *nfile; 2144510Speter { 2154510Speter register long i; 2164510Speter int askfor; 2174510Speter struct nlist nbuf; 2184510Speter 2194510Speter /* pass1 - count symbols */ 2204510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2214510Speter nname = 0; 2224510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2234510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2244845Speter if ( ! funcsymbol( &nbuf ) ) { 2254510Speter continue; 2264510Speter } 2274510Speter nname++; 2284510Speter } 2294510Speter if (nname == 0) { 2307128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2314510Speter done(); 2324510Speter } 2337128Speter askfor = nname + 1; 2344510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2354510Speter if (nl == 0) { 2367128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2377128Speter whoami, askfor * sizeof(nltype) ); 2384510Speter done(); 2394510Speter } 2404510Speter 2414510Speter /* pass2 - read symbols */ 2424510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2434510Speter npe = nl; 2444510Speter nname = 0; 2454510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2464510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2474845Speter if ( ! funcsymbol( &nbuf ) ) { 2484845Speter # ifdef DEBUG 2494845Speter if ( debug & AOUTDEBUG ) { 2504845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2514845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2524845Speter } 2534845Speter # endif DEBUG 2544510Speter continue; 2554510Speter } 2564510Speter npe->value = nbuf.n_value; 2574510Speter npe->name = strtab+nbuf.n_un.n_strx; 2584510Speter # ifdef DEBUG 2594510Speter if ( debug & AOUTDEBUG ) { 2604510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2614510Speter nname , npe -> name , npe -> value ); 2624510Speter } 2634510Speter # endif DEBUG 2644510Speter npe++; 2654510Speter nname++; 2664510Speter } 2674510Speter npe->value = -1; 2684510Speter } 2694510Speter 2704510Speter /* 2714720Speter * read in the text space of an a.out file 2724720Speter */ 2734720Speter gettextspace( nfile ) 2744720Speter FILE *nfile; 2754720Speter { 2764720Speter unsigned char *malloc(); 2774720Speter 2784720Speter if ( cflag == 0 ) { 2794720Speter return; 2804720Speter } 2814720Speter textspace = malloc( xbuf.a_text ); 2824720Speter if ( textspace == 0 ) { 2837128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 2847128Speter whoami , xbuf.a_text ); 2857128Speter fprintf( stderr , "can't do -c\n" ); 2864720Speter return; 2874720Speter } 2884720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 2894720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 2907128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 2917128Speter fprintf( stderr , "can't do -c\n" ); 2924720Speter free( textspace ); 2934720Speter textspace = 0; 2944720Speter return; 2954720Speter } 2964720Speter } 2974720Speter /* 2984563Speter * information from a gmon.out file is in two parts: 2994510Speter * an array of sampling hits within pc ranges, 3004510Speter * and the arcs. 3014510Speter */ 3024510Speter getpfile(filename) 3034510Speter char *filename; 3044510Speter { 3054510Speter FILE *pfile; 3064510Speter FILE *openpfile(); 3074510Speter struct rawarc arc; 3084510Speter 3094510Speter pfile = openpfile(filename); 3104510Speter readsamples(pfile); 3114510Speter /* 3124510Speter * the rest of the file consists of 3134510Speter * a bunch of <from,self,count> tuples. 3144510Speter */ 3154510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3164510Speter # ifdef DEBUG 3174510Speter if ( debug & SAMPLEDEBUG ) { 3184752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3194510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3204510Speter } 3214510Speter # endif DEBUG 3224510Speter /* 3234510Speter * add this arc 3244510Speter */ 3254510Speter tally( &arc ); 3264510Speter } 3274510Speter fclose(pfile); 3284510Speter } 3294510Speter 3304841Speter FILE * 3314841Speter openpfile(filename) 3324510Speter char *filename; 3334510Speter { 3344866Smckusic struct hdr tmp; 3354510Speter FILE *pfile; 3364510Speter 3374510Speter if((pfile = fopen(filename, "r")) == NULL) { 3384510Speter perror(filename); 3394510Speter done(); 3404510Speter } 3414866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3424866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3434866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3444866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3454866Smckusic done(); 3464866Smckusic } 3474866Smckusic h = tmp; 3484752Speter s_lowpc = (unsigned long) h.lowpc; 3494752Speter s_highpc = (unsigned long) h.highpc; 3507227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3517227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3524510Speter sampbytes = h.ncnt - sizeof(struct hdr); 3534510Speter nsamples = sampbytes / sizeof (unsigned UNIT); 3547226Speter # ifdef DEBUG 3557226Speter if ( debug & SAMPLEDEBUG ) { 3567226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3577226Speter h.lowpc , h.highpc , h.ncnt ); 3587226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3597226Speter s_lowpc , s_highpc ); 3607226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3617226Speter lowpc , highpc ); 3627226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3637226Speter sampbytes , nsamples ); 3647226Speter } 3657226Speter # endif DEBUG 3664510Speter return(pfile); 3674510Speter } 3684510Speter 3694510Speter tally( rawp ) 3704510Speter struct rawarc *rawp; 3714510Speter { 3724510Speter nltype *parentp; 3734510Speter nltype *childp; 3744510Speter 3754510Speter parentp = nllookup( rawp -> raw_frompc ); 3764510Speter childp = nllookup( rawp -> raw_selfpc ); 3774510Speter childp -> ncall += rawp -> raw_count; 3784510Speter # ifdef DEBUG 3794510Speter if ( debug & TALLYDEBUG ) { 3804510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 3814510Speter parentp -> name , childp -> name , rawp -> raw_count ); 3824510Speter } 3834510Speter # endif DEBUG 3844720Speter addarc( parentp , childp , rawp -> raw_count ); 3854510Speter } 3864510Speter 3874866Smckusic /* 3884866Smckusic * dump out the gmon.sum file 3894866Smckusic */ 3904866Smckusic dumpsum( sumfile ) 3914866Smckusic char *sumfile; 3924866Smckusic { 3934866Smckusic register nltype *nlp; 3944866Smckusic register arctype *arcp; 3954866Smckusic struct rawarc arc; 3964866Smckusic FILE *sfile; 3974866Smckusic 3984866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 3994866Smckusic perror( sumfile ); 4004866Smckusic done(); 4014866Smckusic } 4024866Smckusic /* 4034866Smckusic * dump the header; use the last header read in 4044866Smckusic */ 4054866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 4064866Smckusic perror( sumfile ); 4074866Smckusic done(); 4084866Smckusic } 4094866Smckusic /* 4104866Smckusic * dump the samples 4114866Smckusic */ 4124866Smckusic if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) { 4134866Smckusic perror( sumfile ); 4144866Smckusic done(); 4154866Smckusic } 4164866Smckusic /* 4174866Smckusic * dump the normalized raw arc information 4184866Smckusic */ 41911807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4204866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4214866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4224866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4234866Smckusic arc.raw_count = arcp -> arc_count; 4244866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4254866Smckusic perror( sumfile ); 4264866Smckusic done(); 4274866Smckusic } 4284866Smckusic # ifdef DEBUG 4294866Smckusic if ( debug & SAMPLEDEBUG ) { 4304866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4314866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4324866Smckusic } 4334866Smckusic # endif DEBUG 4344866Smckusic } 4354866Smckusic } 4364866Smckusic fclose( sfile ); 4374866Smckusic } 4384866Smckusic 4394510Speter valcmp(p1, p2) 4404510Speter nltype *p1, *p2; 4414510Speter { 4424510Speter if ( p1 -> value < p2 -> value ) { 4434510Speter return LESSTHAN; 4444510Speter } 4454510Speter if ( p1 -> value > p2 -> value ) { 4464510Speter return GREATERTHAN; 4474510Speter } 4484510Speter return EQUALTO; 4494510Speter } 4504510Speter 4514510Speter readsamples(pfile) 4524510Speter FILE *pfile; 4534510Speter { 4544510Speter register i; 4554510Speter unsigned UNIT sample; 4564510Speter 4574510Speter if (samples == 0) { 4584510Speter samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT)); 4594510Speter if (samples == 0) { 4607128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 4617128Speter whoami , sampbytes / sizeof (unsigned UNIT)); 4624510Speter done(); 4634510Speter } 4644510Speter } 4654510Speter for (i = 0; i < nsamples; i++) { 4664510Speter fread(&sample, sizeof (unsigned UNIT), 1, pfile); 4674510Speter if (feof(pfile)) 4684510Speter break; 4694510Speter samples[i] += sample; 4704510Speter } 4714510Speter if (i != nsamples) { 4724510Speter fprintf(stderr, 4737128Speter "%s: unexpected EOF after reading %d/%d samples\n", 4747128Speter whoami , --i , nsamples ); 4754510Speter done(); 4764510Speter } 4774510Speter } 4784510Speter 4794510Speter /* 48011523Smckusick * Assign samples to the procedures to which they belong. 48111523Smckusick * 48211523Smckusick * There are three cases as to where pcl and pch can be 48311523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 48411523Smckusick * as shown in the following diagram. overlap computes the 48511523Smckusick * distance between the arrows, the fraction of the sample 48611523Smckusick * that is to be credited to the routine which starts at svalue0. 48711523Smckusick * 48811523Smckusick * svalue0 svalue1 48911523Smckusick * | | 49011523Smckusick * v v 49111523Smckusick * 49211523Smckusick * +-----------------------------------------------+ 49311523Smckusick * | | 49411523Smckusick * | ->| |<- ->| |<- ->| |<- | 49511523Smckusick * | | | | | | 49611523Smckusick * +---------+ +---------+ +---------+ 49711523Smckusick * 49811523Smckusick * ^ ^ ^ ^ ^ ^ 49911523Smckusick * | | | | | | 50011523Smckusick * pcl pch pcl pch pcl pch 50111523Smckusick * 50211523Smckusick * For the vax we assert that samples will never fall in the first 50311807Smckusick * two bytes of any routine, since that is the entry mask, 50411807Smckusick * thus we give call alignentries() to adjust the entry points if 50511807Smckusick * the entry mask falls in one bucket but the code for the routine 50611807Smckusick * doesn't start until the next bucket. In conjunction with the 50711807Smckusick * alignment of routine addresses, this should allow us to have 50811807Smckusick * only one sample for every four bytes of text space and never 50911807Smckusick * have any overlap (the two end cases, above). 5104510Speter */ 5114510Speter asgnsamples() 5124510Speter { 5134510Speter register int j; 5144510Speter unsigned UNIT ccnt; 5154510Speter double time; 5164510Speter unsigned long pcl, pch; 5174510Speter register int i; 5184841Speter unsigned long overlap; 5194510Speter unsigned long svalue0, svalue1; 5204510Speter 5214510Speter /* read samples and assign to namelist symbols */ 5224510Speter scale = highpc - lowpc; 5234510Speter scale /= nsamples; 52411807Smckusick alignentries(); 5257257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5264510Speter ccnt = samples[i]; 5274510Speter if (ccnt == 0) 5284510Speter continue; 52911523Smckusick pcl = lowpc + scale * i; 53011523Smckusick pch = lowpc + scale * (i + 1); 5314510Speter time = ccnt; 5324510Speter # ifdef DEBUG 5334510Speter if ( debug & SAMPLEDEBUG ) { 5345072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5355072Smckusic pcl , pch , ccnt ); 5364510Speter } 5374510Speter # endif DEBUG 5384510Speter totime += time; 5397252Smckusick for (j = j - 1; j < nname; j++) { 54011807Smckusick svalue0 = nl[j].svalue; 54111807Smckusick svalue1 = nl[j+1].svalue; 54211807Smckusick /* 54311807Smckusick * if high end of tick is below entry address, 54411807Smckusick * go for next tick. 54511807Smckusick */ 5464510Speter if (pch < svalue0) 5474510Speter break; 54811807Smckusick /* 54911807Smckusick * if low end of tick into next routine, 55011807Smckusick * go for next routine. 55111807Smckusick */ 5524510Speter if (pcl >= svalue1) 5534510Speter continue; 55411807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 55511523Smckusick if (overlap > 0) { 5564510Speter # ifdef DEBUG 55711523Smckusick if (debug & SAMPLEDEBUG) { 55811807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 55911807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 56011807Smckusick nl[j].name, 56111807Smckusick overlap * time / scale, overlap); 5624510Speter } 5634510Speter # endif DEBUG 56411523Smckusick nl[j].time += overlap * time / scale; 5654510Speter } 5664510Speter } 5674510Speter } 5684510Speter # ifdef DEBUG 56911523Smckusick if (debug & SAMPLEDEBUG) { 57011523Smckusick printf("[asgnsamples] totime %f\n", totime); 5714510Speter } 5724510Speter # endif DEBUG 5734510Speter } 5744510Speter 5754510Speter 5764841Speter unsigned long 5774510Speter min(a, b) 5784841Speter unsigned long a,b; 5794510Speter { 5804510Speter if (a<b) 5814510Speter return(a); 5824510Speter return(b); 5834510Speter } 5844510Speter 5854841Speter unsigned long 5864510Speter max(a, b) 5874841Speter unsigned long a,b; 5884510Speter { 5894510Speter if (a>b) 5904510Speter return(a); 5914510Speter return(b); 5924510Speter } 5934510Speter 59411807Smckusick /* 59511807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 59611807Smckusick * and possibly push the scaled entry points over the entry mask, 59711807Smckusick * if it turns out that the entry point is in one bucket and the code 59811807Smckusick * for a routine is in the next bucket. 59911807Smckusick */ 60011807Smckusick alignentries() 60111807Smckusick { 60211807Smckusick register struct nl *nlp; 60311807Smckusick unsigned long bucket_of_entry; 60411807Smckusick unsigned long bucket_of_code; 60511807Smckusick 60611807Smckusick for (nlp = nl; nlp < npe; nlp++) { 60711807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 60811807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 60911807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 61011807Smckusick if (bucket_of_entry < bucket_of_code) { 61111807Smckusick # ifdef DEBUG 61211807Smckusick if (debug & SAMPLEDEBUG) { 61311807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 61411807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 61511807Smckusick } 61611807Smckusick # endif DEBUG 61711807Smckusick nlp->svalue += UNITS_TO_CODE; 61811807Smckusick } 61911807Smckusick } 62011807Smckusick } 62111807Smckusick 6224845Speter bool 6234845Speter funcsymbol( nlistp ) 6244845Speter struct nlist *nlistp; 6254845Speter { 6264845Speter extern char *strtab; /* string table from a.out */ 6274851Speter extern int aflag; /* if static functions aren't desired */ 6284845Speter char *name; 6294845Speter 6304845Speter /* 6314845Speter * must be a text symbol, 6324851Speter * and static text symbols don't qualify if aflag set. 6334845Speter */ 6344845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6354851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6364845Speter return FALSE; 6374845Speter } 6384845Speter /* 6397128Speter * can't have any `funny' characters in name, 6404845Speter * where `funny' includes `.', .o file names 6414845Speter * and `$', pascal labels. 6424845Speter */ 6434845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6444845Speter if ( *name == '.' || *name == '$' ) { 6454845Speter return FALSE; 6464845Speter } 6474845Speter } 6484845Speter return TRUE; 6494845Speter } 6504845Speter 6514510Speter done() 6524510Speter { 6534510Speter 6544510Speter exit(0); 6554510Speter } 656