14510Speter #ifndef lint 2*15910Speter static char *sccsid = "@(#)gprof.c 1.23 (Berkeley) 01/30/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; 194510Speter 204510Speter --argc; 214510Speter argv++; 224510Speter debug = 0; 2312385Smckusick bflag = TRUE; 244510Speter while ( *argv != 0 && **argv == '-' ) { 254510Speter (*argv)++; 264866Smckusic switch ( **argv ) { 277173Speter case 'a': 287173Speter aflag = TRUE; 297173Speter break; 307173Speter case 'b': 3112385Smckusick bflag = FALSE; 327173Speter break; 337173Speter case 'c': 347173Speter cflag = TRUE; 357173Speter break; 364866Smckusic case 'd': 377173Speter dflag = TRUE; 384510Speter (*argv)++; 394510Speter debug |= atoi( *argv ); 404510Speter debug |= ANYDEBUG; 414510Speter # ifdef DEBUG 4211807Smckusick printf("[main] debug = %d\n", debug); 4311807Smckusick # else not DEBUG 4411807Smckusick printf("%s: -d ignored\n", whoami); 454510Speter # endif DEBUG 464866Smckusic break; 477223Speter case 'E': 487223Speter ++argv; 497223Speter addlist( Elist , *argv ); 507223Speter Eflag = TRUE; 517223Speter addlist( elist , *argv ); 527223Speter eflag = TRUE; 537223Speter break; 547173Speter case 'e': 557223Speter addlist( elist , *++argv ); 567173Speter eflag = TRUE; 574866Smckusic break; 587223Speter case 'F': 597223Speter ++argv; 607223Speter addlist( Flist , *argv ); 617223Speter Fflag = TRUE; 627223Speter addlist( flist , *argv ); 637223Speter fflag = TRUE; 647223Speter break; 657173Speter case 'f': 667223Speter addlist( flist , *++argv ); 677173Speter fflag = TRUE; 684866Smckusic break; 694866Smckusic case 's': 707173Speter sflag = TRUE; 714866Smckusic break; 724866Smckusic case 'z': 737173Speter zflag = TRUE; 744866Smckusic break; 754510Speter } 764510Speter argv++; 774510Speter } 784510Speter if ( *argv != 0 ) { 794510Speter a_outname = *argv; 804510Speter argv++; 814510Speter } else { 824510Speter a_outname = A_OUTNAME; 834510Speter } 844510Speter if ( *argv != 0 ) { 854563Speter gmonname = *argv; 864510Speter argv++; 874510Speter } else { 884563Speter gmonname = GMONNAME; 894510Speter } 904510Speter /* 917173Speter * turn off default functions 927173Speter */ 937223Speter for ( sp = &defaultEs[0] ; *sp ; sp++ ) { 947223Speter Eflag = TRUE; 957223Speter addlist( Elist , *sp ); 967173Speter eflag = TRUE; 977223Speter addlist( elist , *sp ); 987173Speter } 997173Speter /* 100*15910Speter * how many ticks per second? 101*15910Speter * if we can't tell, report time in ticks. 10210249Speter */ 10310249Speter hz = hertz(); 104*15910Speter if (hz == 0) { 105*15910Speter hz = 1; 106*15910Speter fprintf(stderr, "time is in ticks, not seconds\n"); 107*15910Speter } 10810249Speter /* 1094510Speter * get information about a.out file. 1104510Speter */ 1114510Speter getnfile(); 1124510Speter /* 1134510Speter * get information about mon.out file(s). 1144510Speter */ 1154866Smckusic do { 1164866Smckusic getpfile( gmonname ); 1174866Smckusic if ( *argv != 0 ) { 1184866Smckusic gmonname = *argv; 1194866Smckusic } 1207128Speter } while ( *argv++ != 0 ); 1214510Speter /* 1224866Smckusic * dump out a gmon.sum file if requested 1234866Smckusic */ 1247128Speter if ( sflag ) { 1257128Speter dumpsum( GMONSUM ); 1267128Speter } 1274866Smckusic /* 1284510Speter * assign samples to procedures 1294510Speter */ 1304510Speter asgnsamples(); 1314510Speter /* 1324510Speter * print the usual profile 1334510Speter */ 1344510Speter printprof(); 1354510Speter /* 1364510Speter * assemble and print the dynamic profile 1374510Speter */ 1384510Speter doarcs(); 1394510Speter done(); 1404510Speter } 1414510Speter 1427128Speter /* 1437128Speter * Set up string and symbol tables from a.out. 1447128Speter * and optionally the text space. 1457128Speter * On return symbol table is sorted by value. 1467128Speter */ 1474510Speter getnfile() 1484510Speter { 1494510Speter FILE *nfile; 1504510Speter 1514510Speter nfile = fopen( a_outname ,"r"); 1524510Speter if (nfile == NULL) { 1534510Speter perror( a_outname ); 1544510Speter done(); 1554510Speter } 1564510Speter fread(&xbuf, 1, sizeof(xbuf), nfile); 1574510Speter if (N_BADMAG(xbuf)) { 1587128Speter fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); 1594510Speter done(); 1604510Speter } 1614510Speter getstrtab(nfile); 1624510Speter getsymtab(nfile); 1634720Speter gettextspace( nfile ); 1644510Speter qsort(nl, nname, sizeof(nltype), valcmp); 1654510Speter fclose(nfile); 1664510Speter # ifdef DEBUG 1674510Speter if ( debug & AOUTDEBUG ) { 1684510Speter register int j; 1694510Speter 1704510Speter for (j = 0; j < nname; j++){ 1714510Speter printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); 1724510Speter } 1734510Speter } 1744510Speter # endif DEBUG 1754510Speter } 1764510Speter 1774510Speter getstrtab(nfile) 1784510Speter FILE *nfile; 1794510Speter { 1804510Speter 1814510Speter fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 1824510Speter if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { 1837128Speter fprintf(stderr, "%s: %s: no string table (old format?)\n" , 1847128Speter whoami , a_outname ); 1854510Speter done(); 1864510Speter } 1874510Speter strtab = (char *)calloc(ssiz, 1); 1884510Speter if (strtab == NULL) { 1897128Speter fprintf(stderr, "%s: %s: no room for %d bytes of string table", 1907128Speter whoami , a_outname , ssiz); 1914510Speter done(); 1924510Speter } 1934510Speter if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { 1947128Speter fprintf(stderr, "%s: %s: error reading string table\n", 1957128Speter whoami , a_outname ); 1964510Speter done(); 1974510Speter } 1984510Speter } 1994510Speter 2004510Speter /* 2014510Speter * Read in symbol table 2024510Speter */ 2034510Speter getsymtab(nfile) 2044510Speter FILE *nfile; 2054510Speter { 2064510Speter register long i; 2074510Speter int askfor; 2084510Speter struct nlist nbuf; 2094510Speter 2104510Speter /* pass1 - count symbols */ 2114510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2124510Speter nname = 0; 2134510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2144510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2154845Speter if ( ! funcsymbol( &nbuf ) ) { 2164510Speter continue; 2174510Speter } 2184510Speter nname++; 2194510Speter } 2204510Speter if (nname == 0) { 2217128Speter fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); 2224510Speter done(); 2234510Speter } 2247128Speter askfor = nname + 1; 2254510Speter nl = (nltype *) calloc( askfor , sizeof(nltype) ); 2264510Speter if (nl == 0) { 2277128Speter fprintf(stderr, "%s: No room for %d bytes of symbol table\n", 2287128Speter whoami, askfor * sizeof(nltype) ); 2294510Speter done(); 2304510Speter } 2314510Speter 2324510Speter /* pass2 - read symbols */ 2334510Speter fseek(nfile, (long)N_SYMOFF(xbuf), 0); 2344510Speter npe = nl; 2354510Speter nname = 0; 2364510Speter for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 2374510Speter fread(&nbuf, sizeof(nbuf), 1, nfile); 2384845Speter if ( ! funcsymbol( &nbuf ) ) { 2394845Speter # ifdef DEBUG 2404845Speter if ( debug & AOUTDEBUG ) { 2414845Speter printf( "[getsymtab] rejecting: 0x%x %s\n" , 2424845Speter nbuf.n_type , strtab + nbuf.n_un.n_strx ); 2434845Speter } 2444845Speter # endif DEBUG 2454510Speter continue; 2464510Speter } 2474510Speter npe->value = nbuf.n_value; 2484510Speter npe->name = strtab+nbuf.n_un.n_strx; 2494510Speter # ifdef DEBUG 2504510Speter if ( debug & AOUTDEBUG ) { 2514510Speter printf( "[getsymtab] %d %s 0x%08x\n" , 2524510Speter nname , npe -> name , npe -> value ); 2534510Speter } 2544510Speter # endif DEBUG 2554510Speter npe++; 2564510Speter nname++; 2574510Speter } 2584510Speter npe->value = -1; 2594510Speter } 2604510Speter 2614510Speter /* 2624720Speter * read in the text space of an a.out file 2634720Speter */ 2644720Speter gettextspace( nfile ) 2654720Speter FILE *nfile; 2664720Speter { 2674720Speter unsigned char *malloc(); 2684720Speter 2694720Speter if ( cflag == 0 ) { 2704720Speter return; 2714720Speter } 2724720Speter textspace = malloc( xbuf.a_text ); 2734720Speter if ( textspace == 0 ) { 2747128Speter fprintf( stderr , "%s: ran out room for %d bytes of text space: " , 2757128Speter whoami , xbuf.a_text ); 2767128Speter fprintf( stderr , "can't do -c\n" ); 2774720Speter return; 2784720Speter } 2794720Speter (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 2804720Speter if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 2817128Speter fprintf( stderr , "%s: couldn't read text space: " , whoami ); 2827128Speter fprintf( stderr , "can't do -c\n" ); 2834720Speter free( textspace ); 2844720Speter textspace = 0; 2854720Speter return; 2864720Speter } 2874720Speter } 2884720Speter /* 2894563Speter * information from a gmon.out file is in two parts: 2904510Speter * an array of sampling hits within pc ranges, 2914510Speter * and the arcs. 2924510Speter */ 2934510Speter getpfile(filename) 2944510Speter char *filename; 2954510Speter { 2964510Speter FILE *pfile; 2974510Speter FILE *openpfile(); 2984510Speter struct rawarc arc; 2994510Speter 3004510Speter pfile = openpfile(filename); 3014510Speter readsamples(pfile); 3024510Speter /* 3034510Speter * the rest of the file consists of 3044510Speter * a bunch of <from,self,count> tuples. 3054510Speter */ 3064510Speter while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 3074510Speter # ifdef DEBUG 3084510Speter if ( debug & SAMPLEDEBUG ) { 3094752Speter printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , 3104510Speter arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 3114510Speter } 3124510Speter # endif DEBUG 3134510Speter /* 3144510Speter * add this arc 3154510Speter */ 3164510Speter tally( &arc ); 3174510Speter } 3184510Speter fclose(pfile); 3194510Speter } 3204510Speter 3214841Speter FILE * 3224841Speter openpfile(filename) 3234510Speter char *filename; 3244510Speter { 3254866Smckusic struct hdr tmp; 3264510Speter FILE *pfile; 3274510Speter 3284510Speter if((pfile = fopen(filename, "r")) == NULL) { 3294510Speter perror(filename); 3304510Speter done(); 3314510Speter } 3324866Smckusic fread(&tmp, sizeof(struct hdr), 1, pfile); 3334866Smckusic if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || 3344866Smckusic tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { 3354866Smckusic fprintf(stderr, "%s: incompatible with first gmon file\n", filename); 3364866Smckusic done(); 3374866Smckusic } 3384866Smckusic h = tmp; 3394752Speter s_lowpc = (unsigned long) h.lowpc; 3404752Speter s_highpc = (unsigned long) h.highpc; 3417227Smckusick lowpc = (unsigned long)h.lowpc / sizeof(UNIT); 3427227Smckusick highpc = (unsigned long)h.highpc / sizeof(UNIT); 3434510Speter sampbytes = h.ncnt - sizeof(struct hdr); 3444510Speter nsamples = sampbytes / sizeof (unsigned UNIT); 3457226Speter # ifdef DEBUG 3467226Speter if ( debug & SAMPLEDEBUG ) { 3477226Speter printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", 3487226Speter h.lowpc , h.highpc , h.ncnt ); 3497226Speter printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , 3507226Speter s_lowpc , s_highpc ); 3517226Speter printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , 3527226Speter lowpc , highpc ); 3537226Speter printf( "[openpfile] sampbytes %d nsamples %d\n" , 3547226Speter sampbytes , nsamples ); 3557226Speter } 3567226Speter # endif DEBUG 3574510Speter return(pfile); 3584510Speter } 3594510Speter 3604510Speter tally( rawp ) 3614510Speter struct rawarc *rawp; 3624510Speter { 3634510Speter nltype *parentp; 3644510Speter nltype *childp; 3654510Speter 3664510Speter parentp = nllookup( rawp -> raw_frompc ); 3674510Speter childp = nllookup( rawp -> raw_selfpc ); 3684510Speter childp -> ncall += rawp -> raw_count; 3694510Speter # ifdef DEBUG 3704510Speter if ( debug & TALLYDEBUG ) { 3714510Speter printf( "[tally] arc from %s to %s traversed %d times\n" , 3724510Speter parentp -> name , childp -> name , rawp -> raw_count ); 3734510Speter } 3744510Speter # endif DEBUG 3754720Speter addarc( parentp , childp , rawp -> raw_count ); 3764510Speter } 3774510Speter 3784866Smckusic /* 3794866Smckusic * dump out the gmon.sum file 3804866Smckusic */ 3814866Smckusic dumpsum( sumfile ) 3824866Smckusic char *sumfile; 3834866Smckusic { 3844866Smckusic register nltype *nlp; 3854866Smckusic register arctype *arcp; 3864866Smckusic struct rawarc arc; 3874866Smckusic FILE *sfile; 3884866Smckusic 3894866Smckusic if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 3904866Smckusic perror( sumfile ); 3914866Smckusic done(); 3924866Smckusic } 3934866Smckusic /* 3944866Smckusic * dump the header; use the last header read in 3954866Smckusic */ 3964866Smckusic if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { 3974866Smckusic perror( sumfile ); 3984866Smckusic done(); 3994866Smckusic } 4004866Smckusic /* 4014866Smckusic * dump the samples 4024866Smckusic */ 4034866Smckusic if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) { 4044866Smckusic perror( sumfile ); 4054866Smckusic done(); 4064866Smckusic } 4074866Smckusic /* 4084866Smckusic * dump the normalized raw arc information 4094866Smckusic */ 41011807Smckusick for ( nlp = nl ; nlp < npe ; nlp++ ) { 4114866Smckusic for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 4124866Smckusic arc.raw_frompc = arcp -> arc_parentp -> value; 4134866Smckusic arc.raw_selfpc = arcp -> arc_childp -> value; 4144866Smckusic arc.raw_count = arcp -> arc_count; 4154866Smckusic if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 4164866Smckusic perror( sumfile ); 4174866Smckusic done(); 4184866Smckusic } 4194866Smckusic # ifdef DEBUG 4204866Smckusic if ( debug & SAMPLEDEBUG ) { 4214866Smckusic printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , 4224866Smckusic arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 4234866Smckusic } 4244866Smckusic # endif DEBUG 4254866Smckusic } 4264866Smckusic } 4274866Smckusic fclose( sfile ); 4284866Smckusic } 4294866Smckusic 4304510Speter valcmp(p1, p2) 4314510Speter nltype *p1, *p2; 4324510Speter { 4334510Speter if ( p1 -> value < p2 -> value ) { 4344510Speter return LESSTHAN; 4354510Speter } 4364510Speter if ( p1 -> value > p2 -> value ) { 4374510Speter return GREATERTHAN; 4384510Speter } 4394510Speter return EQUALTO; 4404510Speter } 4414510Speter 4424510Speter readsamples(pfile) 4434510Speter FILE *pfile; 4444510Speter { 4454510Speter register i; 4464510Speter unsigned UNIT sample; 4474510Speter 4484510Speter if (samples == 0) { 4494510Speter samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT)); 4504510Speter if (samples == 0) { 4517128Speter fprintf( stderr , "%s: No room for %d sample pc's\n", 4527128Speter whoami , sampbytes / sizeof (unsigned UNIT)); 4534510Speter done(); 4544510Speter } 4554510Speter } 4564510Speter for (i = 0; i < nsamples; i++) { 4574510Speter fread(&sample, sizeof (unsigned UNIT), 1, pfile); 4584510Speter if (feof(pfile)) 4594510Speter break; 4604510Speter samples[i] += sample; 4614510Speter } 4624510Speter if (i != nsamples) { 4634510Speter fprintf(stderr, 4647128Speter "%s: unexpected EOF after reading %d/%d samples\n", 4657128Speter whoami , --i , nsamples ); 4664510Speter done(); 4674510Speter } 4684510Speter } 4694510Speter 4704510Speter /* 47111523Smckusick * Assign samples to the procedures to which they belong. 47211523Smckusick * 47311523Smckusick * There are three cases as to where pcl and pch can be 47411523Smckusick * with respect to the routine entry addresses svalue0 and svalue1 47511523Smckusick * as shown in the following diagram. overlap computes the 47611523Smckusick * distance between the arrows, the fraction of the sample 47711523Smckusick * that is to be credited to the routine which starts at svalue0. 47811523Smckusick * 47911523Smckusick * svalue0 svalue1 48011523Smckusick * | | 48111523Smckusick * v v 48211523Smckusick * 48311523Smckusick * +-----------------------------------------------+ 48411523Smckusick * | | 48511523Smckusick * | ->| |<- ->| |<- ->| |<- | 48611523Smckusick * | | | | | | 48711523Smckusick * +---------+ +---------+ +---------+ 48811523Smckusick * 48911523Smckusick * ^ ^ ^ ^ ^ ^ 49011523Smckusick * | | | | | | 49111523Smckusick * pcl pch pcl pch pcl pch 49211523Smckusick * 49311523Smckusick * For the vax we assert that samples will never fall in the first 49411807Smckusick * two bytes of any routine, since that is the entry mask, 49511807Smckusick * thus we give call alignentries() to adjust the entry points if 49611807Smckusick * the entry mask falls in one bucket but the code for the routine 49711807Smckusick * doesn't start until the next bucket. In conjunction with the 49811807Smckusick * alignment of routine addresses, this should allow us to have 49911807Smckusick * only one sample for every four bytes of text space and never 50011807Smckusick * have any overlap (the two end cases, above). 5014510Speter */ 5024510Speter asgnsamples() 5034510Speter { 5044510Speter register int j; 5054510Speter unsigned UNIT ccnt; 5064510Speter double time; 5074510Speter unsigned long pcl, pch; 5084510Speter register int i; 5094841Speter unsigned long overlap; 5104510Speter unsigned long svalue0, svalue1; 5114510Speter 5124510Speter /* read samples and assign to namelist symbols */ 5134510Speter scale = highpc - lowpc; 5144510Speter scale /= nsamples; 51511807Smckusick alignentries(); 5167257Smckusick for (i = 0, j = 1; i < nsamples; i++) { 5174510Speter ccnt = samples[i]; 5184510Speter if (ccnt == 0) 5194510Speter continue; 52011523Smckusick pcl = lowpc + scale * i; 52111523Smckusick pch = lowpc + scale * (i + 1); 5224510Speter time = ccnt; 5234510Speter # ifdef DEBUG 5244510Speter if ( debug & SAMPLEDEBUG ) { 5255072Smckusic printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , 5265072Smckusic pcl , pch , ccnt ); 5274510Speter } 5284510Speter # endif DEBUG 5294510Speter totime += time; 5307252Smckusick for (j = j - 1; j < nname; j++) { 53111807Smckusick svalue0 = nl[j].svalue; 53211807Smckusick svalue1 = nl[j+1].svalue; 53311807Smckusick /* 53411807Smckusick * if high end of tick is below entry address, 53511807Smckusick * go for next tick. 53611807Smckusick */ 5374510Speter if (pch < svalue0) 5384510Speter break; 53911807Smckusick /* 54011807Smckusick * if low end of tick into next routine, 54111807Smckusick * go for next routine. 54211807Smckusick */ 5434510Speter if (pcl >= svalue1) 5444510Speter continue; 54511807Smckusick overlap = min(pch, svalue1) - max(pcl, svalue0); 54611523Smckusick if (overlap > 0) { 5474510Speter # ifdef DEBUG 54811523Smckusick if (debug & SAMPLEDEBUG) { 54911807Smckusick printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", 55011807Smckusick nl[j].value/sizeof(UNIT), svalue0, svalue1, 55111807Smckusick nl[j].name, 55211807Smckusick overlap * time / scale, overlap); 5534510Speter } 5544510Speter # endif DEBUG 55511523Smckusick nl[j].time += overlap * time / scale; 5564510Speter } 5574510Speter } 5584510Speter } 5594510Speter # ifdef DEBUG 56011523Smckusick if (debug & SAMPLEDEBUG) { 56111523Smckusick printf("[asgnsamples] totime %f\n", totime); 5624510Speter } 5634510Speter # endif DEBUG 5644510Speter } 5654510Speter 5664510Speter 5674841Speter unsigned long 5684510Speter min(a, b) 5694841Speter unsigned long a,b; 5704510Speter { 5714510Speter if (a<b) 5724510Speter return(a); 5734510Speter return(b); 5744510Speter } 5754510Speter 5764841Speter unsigned long 5774510Speter max(a, b) 5784841Speter unsigned long a,b; 5794510Speter { 5804510Speter if (a>b) 5814510Speter return(a); 5824510Speter return(b); 5834510Speter } 5844510Speter 58511807Smckusick /* 58611807Smckusick * calculate scaled entry point addresses (to save time in asgnsamples), 58711807Smckusick * and possibly push the scaled entry points over the entry mask, 58811807Smckusick * if it turns out that the entry point is in one bucket and the code 58911807Smckusick * for a routine is in the next bucket. 59011807Smckusick */ 59111807Smckusick alignentries() 59211807Smckusick { 59311807Smckusick register struct nl *nlp; 59411807Smckusick unsigned long bucket_of_entry; 59511807Smckusick unsigned long bucket_of_code; 59611807Smckusick 59711807Smckusick for (nlp = nl; nlp < npe; nlp++) { 59811807Smckusick nlp -> svalue = nlp -> value / sizeof(UNIT); 59911807Smckusick bucket_of_entry = (nlp->svalue - lowpc) / scale; 60011807Smckusick bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; 60111807Smckusick if (bucket_of_entry < bucket_of_code) { 60211807Smckusick # ifdef DEBUG 60311807Smckusick if (debug & SAMPLEDEBUG) { 60411807Smckusick printf("[alignentries] pushing svalue 0x%x to 0x%x\n", 60511807Smckusick nlp->svalue, nlp->svalue + UNITS_TO_CODE); 60611807Smckusick } 60711807Smckusick # endif DEBUG 60811807Smckusick nlp->svalue += UNITS_TO_CODE; 60911807Smckusick } 61011807Smckusick } 61111807Smckusick } 61211807Smckusick 6134845Speter bool 6144845Speter funcsymbol( nlistp ) 6154845Speter struct nlist *nlistp; 6164845Speter { 6174845Speter extern char *strtab; /* string table from a.out */ 6184851Speter extern int aflag; /* if static functions aren't desired */ 6194845Speter char *name; 6204845Speter 6214845Speter /* 6224845Speter * must be a text symbol, 6234851Speter * and static text symbols don't qualify if aflag set. 6244845Speter */ 6254845Speter if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 6264851Speter || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 6274845Speter return FALSE; 6284845Speter } 6294845Speter /* 6307128Speter * can't have any `funny' characters in name, 6314845Speter * where `funny' includes `.', .o file names 6324845Speter * and `$', pascal labels. 6334845Speter */ 6344845Speter for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { 6354845Speter if ( *name == '.' || *name == '$' ) { 6364845Speter return FALSE; 6374845Speter } 6384845Speter } 6394845Speter return TRUE; 6404845Speter } 6414845Speter 6424510Speter done() 6434510Speter { 6444510Speter 6454510Speter exit(0); 6464510Speter } 647