gprof.c revision 91735
1274955Ssvnmir/* 2274955Ssvnmir * Copyright (c) 1983, 1993 3274955Ssvnmir * The Regents of the University of California. All rights reserved. 4274955Ssvnmir * 5274955Ssvnmir * Redistribution and use in source and binary forms, with or without 6274955Ssvnmir * modification, are permitted provided that the following conditions 7274955Ssvnmir * are met: 8274955Ssvnmir * 1. Redistributions of source code must retain the above copyright 9274955Ssvnmir * notice, this list of conditions and the following disclaimer. 10274955Ssvnmir * 2. Redistributions in binary form must reproduce the above copyright 11274955Ssvnmir * notice, this list of conditions and the following disclaimer in the 12274955Ssvnmir * documentation and/or other materials provided with the distribution. 13274955Ssvnmir * 3. All advertising materials mentioning features or use of this software 14274955Ssvnmir * must display the following acknowledgement: 15280031Sdim * This product includes software developed by the University of 16280031Sdim * California, Berkeley and its contributors. 17274955Ssvnmir * 4. Neither the name of the University nor the names of its contributors 18274955Ssvnmir * may be used to endorse or promote products derived from this software 19274955Ssvnmir * without specific prior written permission. 20274955Ssvnmir * 21280031Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22280031Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23274955Ssvnmir * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24274955Ssvnmir * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25274955Ssvnmir * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26296417Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27274955Ssvnmir * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28274955Ssvnmir * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29274955Ssvnmir * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30274955Ssvnmir * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31274955Ssvnmir * SUCH DAMAGE. 32274955Ssvnmir */ 33274955Ssvnmir 34274955Ssvnmir#ifndef lint 35274955Ssvnmirstatic const char copyright[] = 36274955Ssvnmir"@(#) Copyright (c) 1983, 1993\n\ 37274955Ssvnmir The Regents of the University of California. All rights reserved.\n"; 38274955Ssvnmir#endif /* not lint */ 39274955Ssvnmir 40274955Ssvnmir#ifndef lint 41274955Ssvnmir#if 0 42274955Ssvnmirstatic char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 43274955Ssvnmir#endif 44274955Ssvnmirstatic const char rcsid[] = 45274955Ssvnmir "$FreeBSD: head/usr.bin/gprof/gprof.c 91735 2002-03-06 09:47:36Z bde $"; 46274955Ssvnmir#endif /* not lint */ 47274955Ssvnmir 48274955Ssvnmir#include <err.h> 49274955Ssvnmir#include "gprof.h" 50274955Ssvnmir 51274955Ssvnmirstatic int valcmp(const void *, const void *); 52274955Ssvnmir 53274955Ssvnmir 54274955Ssvnmirstatic struct gmonhdr gmonhdr; 55274955Ssvnmirstatic int lflag; 56274955Ssvnmirstatic int Lflag; 57296417Sdim 58274955Ssvnmirmain(argc, argv) 59274955Ssvnmir int argc; 60274955Ssvnmir char **argv; 61274955Ssvnmir{ 62274955Ssvnmir char **sp; 63274955Ssvnmir nltype **timesortnlp; 64274955Ssvnmir char **defaultEs; 65274955Ssvnmir 66274955Ssvnmir --argc; 67274955Ssvnmir argv++; 68296417Sdim debug = 0; 69296417Sdim bflag = TRUE; 70296417Sdim while ( *argv != 0 && **argv == '-' ) { 71296417Sdim (*argv)++; 72296417Sdim switch ( **argv ) { 73296417Sdim case 'a': 74296417Sdim aflag = TRUE; 75296417Sdim break; 76296417Sdim case 'b': 77296417Sdim bflag = FALSE; 78296417Sdim break; 79296417Sdim case 'C': 80274955Ssvnmir Cflag = TRUE; 81296417Sdim cyclethreshold = atoi( *++argv ); 82274955Ssvnmir break; 83274955Ssvnmir case 'c': 84274955Ssvnmir#if defined(vax) || defined(tahoe) 85274955Ssvnmir cflag = TRUE; 86274955Ssvnmir#else 87274955Ssvnmir errx(1, "-c isn't supported on this architecture yet"); 88274955Ssvnmir#endif 89274955Ssvnmir break; 90274955Ssvnmir case 'd': 91274955Ssvnmir dflag = TRUE; 92274955Ssvnmir setlinebuf(stdout); 93274955Ssvnmir debug |= atoi( *++argv ); 94274955Ssvnmir debug |= ANYDEBUG; 95274955Ssvnmir# ifdef DEBUG 96274955Ssvnmir printf("[main] debug = %d\n", debug); 97274955Ssvnmir# else not DEBUG 98274955Ssvnmir printf("gprof: -d ignored\n"); 99274955Ssvnmir# endif DEBUG 100274955Ssvnmir break; 101280031Sdim case 'E': 102288943Sdim ++argv; 103288943Sdim addlist( Elist , *argv ); 104288943Sdim Eflag = TRUE; 105274955Ssvnmir addlist( elist , *argv ); 106274955Ssvnmir eflag = TRUE; 107274955Ssvnmir break; 108274955Ssvnmir case 'e': 109274955Ssvnmir addlist( elist , *++argv ); 110274955Ssvnmir eflag = TRUE; 111274955Ssvnmir break; 112274955Ssvnmir case 'F': 113274955Ssvnmir ++argv; 114274955Ssvnmir addlist( Flist , *argv ); 115274955Ssvnmir Fflag = TRUE; 116274955Ssvnmir addlist( flist , *argv ); 117274955Ssvnmir fflag = TRUE; 118274955Ssvnmir break; 119274955Ssvnmir case 'f': 120274955Ssvnmir addlist( flist , *++argv ); 121274955Ssvnmir fflag = TRUE; 122288943Sdim break; 123288943Sdim case 'k': 124296417Sdim addlist( kfromlist , *++argv ); 125296417Sdim addlist( ktolist , *++argv ); 126274955Ssvnmir kflag = TRUE; 127274955Ssvnmir break; 128280031Sdim case 'K': 129274955Ssvnmir Kflag = TRUE; 130296417Sdim break; 131296417Sdim case 'l': 132296417Sdim lflag = 1; 133274955Ssvnmir Lflag = 0; 134296417Sdim break; 135274955Ssvnmir case 'L': 136274955Ssvnmir Lflag = 1; 137296417Sdim lflag = 0; 138296417Sdim break; 139296417Sdim case 's': 140296417Sdim sflag = TRUE; 141296417Sdim break; 142274955Ssvnmir case 'u': 143274955Ssvnmir uflag = TRUE; 144274955Ssvnmir break; 145274955Ssvnmir case 'z': 146274955Ssvnmir zflag = TRUE; 147274955Ssvnmir break; 148274955Ssvnmir } 149274955Ssvnmir argv++; 150274955Ssvnmir } 151274955Ssvnmir if ( *argv != 0 ) { 152274955Ssvnmir a_outname = *argv; 153274955Ssvnmir argv++; 154274955Ssvnmir } else { 155274955Ssvnmir a_outname = A_OUTNAME; 156274955Ssvnmir } 157274955Ssvnmir if ( *argv != 0 ) { 158274955Ssvnmir gmonname = *argv; 159296417Sdim argv++; 160296417Sdim } else { 161274955Ssvnmir gmonname = (char *) malloc(strlen(a_outname)+6); 162274955Ssvnmir strcpy(gmonname, a_outname); 163296417Sdim strcat(gmonname, ".gmon"); 164274955Ssvnmir } 165296417Sdim /* 166296417Sdim * get information from the executable file. 167274955Ssvnmir */ 168296417Sdim if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) || 169296417Sdim (elf_getnfile(a_outname, &defaultEs) == -1 && 170288943Sdim aout_getnfile(a_outname, &defaultEs) == -1)) 171288943Sdim errx(1, "%s: bad format", a_outname); 172274955Ssvnmir /* 173274955Ssvnmir * sort symbol table. 174274955Ssvnmir */ 175274955Ssvnmir qsort(nl, nname, sizeof(nltype), valcmp); 176274955Ssvnmir /* 177274955Ssvnmir * turn off default functions 178274955Ssvnmir */ 179274955Ssvnmir for ( sp = defaultEs ; *sp ; sp++ ) { 180296417Sdim Eflag = TRUE; 181296417Sdim addlist( Elist , *sp ); 182296417Sdim eflag = TRUE; 183296417Sdim addlist( elist , *sp ); 184296417Sdim } 185274955Ssvnmir /* 186296417Sdim * get information about mon.out file(s). 187274955Ssvnmir */ 188296417Sdim do { 189296417Sdim getpfile( gmonname ); 190274955Ssvnmir if ( *argv != 0 ) { 191274955Ssvnmir gmonname = *argv; 192296417Sdim } 193296417Sdim } while ( *argv++ != 0 ); 194296417Sdim /* 195296417Sdim * how many ticks per second? 196296417Sdim * if we can't tell, report time in ticks. 197296417Sdim */ 198296417Sdim if (hz == 0) { 199296417Sdim hz = 1; 200296417Sdim fprintf(stderr, "time is in ticks, not seconds\n"); 201296417Sdim } 202296417Sdim /* 203296417Sdim * dump out a gmon.sum file if requested 204296417Sdim */ 205296417Sdim if ( sflag ) { 206296417Sdim dumpsum( GMONSUM ); 207296417Sdim } 208296417Sdim /* 209296417Sdim * assign samples to procedures 210296417Sdim */ 211296417Sdim asgnsamples(); 212296417Sdim /* 213296417Sdim * assemble the dynamic profile 214296417Sdim */ 215274955Ssvnmir timesortnlp = doarcs(); 216274955Ssvnmir /* 217274955Ssvnmir * print the dynamic profile 218274955Ssvnmir */ 219274955Ssvnmir if(!lflag) { 220274955Ssvnmir printgprof( timesortnlp ); 221274955Ssvnmir } 222274955Ssvnmir /* 223274955Ssvnmir * print the flat profile 224274955Ssvnmir */ 225274955Ssvnmir if(!Lflag) { 226274955Ssvnmir printprof(); 227274955Ssvnmir } 228274955Ssvnmir /* 229274955Ssvnmir * print the index 230274955Ssvnmir */ 231274955Ssvnmir printindex(); 232274955Ssvnmir done(); 233274955Ssvnmir} 234274955Ssvnmir 235288943Sdim /* 236274955Ssvnmir * information from a gmon.out file is in two parts: 237288943Sdim * an array of sampling hits within pc ranges, 238296417Sdim * and the arcs. 239296417Sdim */ 240296417Sdimgetpfile(filename) 241296417Sdim char *filename; 242288943Sdim{ 243274955Ssvnmir FILE *pfile; 244288943Sdim FILE *openpfile(); 245296417Sdim struct rawarc arc; 246296417Sdim 247274955Ssvnmir pfile = openpfile(filename); 248288943Sdim readsamples(pfile); 249288943Sdim /* 250274955Ssvnmir * the rest of the file consists of 251274955Ssvnmir * a bunch of <from,self,count> tuples. 252274955Ssvnmir */ 253274955Ssvnmir while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { 254274955Ssvnmir# ifdef DEBUG 255274955Ssvnmir if ( debug & SAMPLEDEBUG ) { 256274955Ssvnmir printf( "[getpfile] frompc 0x%lx selfpc 0x%lx count %ld\n" , 257296417Sdim arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 258274955Ssvnmir } 259274955Ssvnmir# endif DEBUG 260274955Ssvnmir /* 261274955Ssvnmir * add this arc 262274955Ssvnmir */ 263274955Ssvnmir tally( &arc ); 264274955Ssvnmir } 265274955Ssvnmir fclose(pfile); 266274955Ssvnmir} 267274955Ssvnmir 268274955SsvnmirFILE * 269274955Ssvnmiropenpfile(filename) 270274955Ssvnmir char *filename; 271274955Ssvnmir{ 272274955Ssvnmir struct gmonhdr tmp; 273296417Sdim FILE *pfile; 274296417Sdim int size; 275288943Sdim int rate; 276296417Sdim 277296417Sdim if((pfile = fopen(filename, "r")) == NULL) { 278296417Sdim perror(filename); 279296417Sdim done(); 280296417Sdim } 281288943Sdim fread(&tmp, sizeof(struct gmonhdr), 1, pfile); 282274955Ssvnmir if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc || 283296417Sdim tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) { 284296417Sdim warnx("%s: incompatible with first gmon file", filename); 285296417Sdim done(); 286296417Sdim } 287296417Sdim gmonhdr = tmp; 288296417Sdim if ( gmonhdr.version == GMONVERSION ) { 289296417Sdim rate = gmonhdr.profrate; 290296417Sdim size = sizeof(struct gmonhdr); 291296417Sdim } else { 292296417Sdim fseek(pfile, sizeof(struct ophdr), SEEK_SET); 293296417Sdim size = sizeof(struct ophdr); 294296417Sdim gmonhdr.profrate = rate = hertz(); 295296417Sdim gmonhdr.version = GMONVERSION; 296296417Sdim } 297296417Sdim if (hz == 0) { 298274955Ssvnmir hz = rate; 299296417Sdim } else if (hz != rate) { 300274955Ssvnmir fprintf(stderr, 301296417Sdim "%s: profile clock rate (%d) %s (%ld) in first gmon file\n", 302296417Sdim filename, rate, "incompatible with clock rate", hz); 303296417Sdim done(); 304296417Sdim } 305296417Sdim s_lowpc = (unsigned long) gmonhdr.lpc; 306296417Sdim s_highpc = (unsigned long) gmonhdr.hpc; 307296417Sdim lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2; 308296417Sdim highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2; 309296417Sdim sampbytes = gmonhdr.ncnt - size; 310296417Sdim nsamples = sampbytes / sizeof (UNIT); 311296417Sdim# ifdef DEBUG 312296417Sdim if ( debug & SAMPLEDEBUG ) { 313296417Sdim printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n", 314296417Sdim gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt ); 315296417Sdim printf( "[openpfile] s_lowpc 0x%lx s_highpc 0x%lx\n" , 316296417Sdim s_lowpc , s_highpc ); 317296417Sdim printf( "[openpfile] lowpc 0x%lx highpc 0x%lx\n" , 318296417Sdim lowpc , highpc ); 319296417Sdim printf( "[openpfile] sampbytes %d nsamples %d\n" , 320296417Sdim sampbytes , nsamples ); 321296417Sdim printf( "[openpfile] sample rate %ld\n" , hz ); 322296417Sdim } 323296417Sdim# endif DEBUG 324296417Sdim return(pfile); 325296417Sdim} 326296417Sdim 327296417Sdimtally( rawp ) 328296417Sdim struct rawarc *rawp; 329296417Sdim{ 330296417Sdim nltype *parentp; 331296417Sdim nltype *childp; 332274955Ssvnmir 333274955Ssvnmir parentp = nllookup( rawp -> raw_frompc ); 334274955Ssvnmir childp = nllookup( rawp -> raw_selfpc ); 335274955Ssvnmir if ( parentp == 0 || childp == 0 ) 336274955Ssvnmir return; 337274955Ssvnmir if ( kflag 338296417Sdim && onlist( kfromlist , parentp -> name ) 339280031Sdim && onlist( ktolist , childp -> name ) ) { 340274955Ssvnmir return; 341274955Ssvnmir } 342288943Sdim childp -> ncall += rawp -> raw_count; 343288943Sdim# ifdef DEBUG 344296417Sdim if ( debug & TALLYDEBUG ) { 345274955Ssvnmir printf( "[tally] arc from %s to %s traversed %ld times\n" , 346296417Sdim parentp -> name , childp -> name , rawp -> raw_count ); 347274955Ssvnmir } 348288943Sdim# endif DEBUG 349274955Ssvnmir addarc( parentp , childp , rawp -> raw_count ); 350274955Ssvnmir} 351274955Ssvnmir 352274955Ssvnmir/* 353274955Ssvnmir * dump out the gmon.sum file 354274955Ssvnmir */ 355274955Ssvnmirdumpsum( sumfile ) 356274955Ssvnmir char *sumfile; 357274955Ssvnmir{ 358296417Sdim register nltype *nlp; 359296417Sdim register arctype *arcp; 360296417Sdim struct rawarc arc; 361296417Sdim FILE *sfile; 362296417Sdim 363274955Ssvnmir if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { 364280031Sdim perror( sumfile ); 365274955Ssvnmir done(); 366296417Sdim } 367274955Ssvnmir /* 368274955Ssvnmir * dump the header; use the last header read in 369274955Ssvnmir */ 370274955Ssvnmir if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) { 371288943Sdim perror( sumfile ); 372288943Sdim done(); 373288943Sdim } 374288943Sdim /* 375288943Sdim * dump the samples 376296417Sdim */ 377296417Sdim if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { 378296417Sdim perror( sumfile ); 379296417Sdim done(); 380296417Sdim } 381296417Sdim /* 382296417Sdim * dump the normalized raw arc information 383296417Sdim */ 384296417Sdim for ( nlp = nl ; nlp < npe ; nlp++ ) { 385296417Sdim for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 386274955Ssvnmir arc.raw_frompc = arcp -> arc_parentp -> value; 387274955Ssvnmir arc.raw_selfpc = arcp -> arc_childp -> value; 388274955Ssvnmir arc.raw_count = arcp -> arc_count; 389274955Ssvnmir if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { 390280031Sdim perror( sumfile ); 391 done(); 392 } 393# ifdef DEBUG 394 if ( debug & SAMPLEDEBUG ) { 395 printf( "[dumpsum] frompc 0x%lx selfpc 0x%lx count %ld\n" , 396 arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); 397 } 398# endif DEBUG 399 } 400 } 401 fclose( sfile ); 402} 403 404static int 405valcmp(v1, v2) 406 const void *v1; 407 const void *v2; 408{ 409 const nltype *p1 = (const nltype *)v1; 410 const nltype *p2 = (const nltype *)v2; 411 412 if ( p1 -> value < p2 -> value ) { 413 return LESSTHAN; 414 } 415 if ( p1 -> value > p2 -> value ) { 416 return GREATERTHAN; 417 } 418 return EQUALTO; 419} 420 421readsamples(pfile) 422 FILE *pfile; 423{ 424 register i; 425 UNIT sample; 426 427 if (samples == 0) { 428 samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); 429 if (samples == 0) { 430 warnx("no room for %d sample pc's", sampbytes / sizeof (UNIT)); 431 done(); 432 } 433 } 434 for (i = 0; i < nsamples; i++) { 435 fread(&sample, sizeof (UNIT), 1, pfile); 436 if (feof(pfile)) 437 break; 438 samples[i] += sample; 439 } 440 if (i != nsamples) { 441 warnx("unexpected EOF after reading %d/%d samples", --i , nsamples ); 442 done(); 443 } 444} 445 446/* 447 * Assign samples to the procedures to which they belong. 448 * 449 * There are three cases as to where pcl and pch can be 450 * with respect to the routine entry addresses svalue0 and svalue1 451 * as shown in the following diagram. overlap computes the 452 * distance between the arrows, the fraction of the sample 453 * that is to be credited to the routine which starts at svalue0. 454 * 455 * svalue0 svalue1 456 * | | 457 * v v 458 * 459 * +-----------------------------------------------+ 460 * | | 461 * | ->| |<- ->| |<- ->| |<- | 462 * | | | | | | 463 * +---------+ +---------+ +---------+ 464 * 465 * ^ ^ ^ ^ ^ ^ 466 * | | | | | | 467 * pcl pch pcl pch pcl pch 468 * 469 * For the vax we assert that samples will never fall in the first 470 * two bytes of any routine, since that is the entry mask, 471 * thus we give call alignentries() to adjust the entry points if 472 * the entry mask falls in one bucket but the code for the routine 473 * doesn't start until the next bucket. In conjunction with the 474 * alignment of routine addresses, this should allow us to have 475 * only one sample for every four bytes of text space and never 476 * have any overlap (the two end cases, above). 477 */ 478asgnsamples() 479{ 480 register int j; 481 UNIT ccnt; 482 double time; 483 unsigned long pcl, pch; 484 register int i; 485 unsigned long overlap; 486 unsigned long svalue0, svalue1; 487 488 /* read samples and assign to namelist symbols */ 489 scale = highpc - lowpc; 490 scale /= nsamples; 491 alignentries(); 492 for (i = 0, j = 1; i < nsamples; i++) { 493 ccnt = samples[i]; 494 if (ccnt == 0) 495 continue; 496 pcl = lowpc + (unsigned long)(scale * i); 497 pch = lowpc + (unsigned long)(scale * (i + 1)); 498 time = ccnt; 499# ifdef DEBUG 500 if ( debug & SAMPLEDEBUG ) { 501 printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %d\n" , 502 pcl , pch , ccnt ); 503 } 504# endif DEBUG 505 totime += time; 506 for (j = j - 1; j < nname; j++) { 507 svalue0 = nl[j].svalue; 508 svalue1 = nl[j+1].svalue; 509 /* 510 * if high end of tick is below entry address, 511 * go for next tick. 512 */ 513 if (pch < svalue0) 514 break; 515 /* 516 * if low end of tick into next routine, 517 * go for next routine. 518 */ 519 if (pcl >= svalue1) 520 continue; 521 overlap = min(pch, svalue1) - max(pcl, svalue0); 522 if (overlap > 0) { 523# ifdef DEBUG 524 if (debug & SAMPLEDEBUG) { 525 printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n", 526 nl[j].value / HISTORICAL_SCALE_2, 527 svalue0, svalue1, nl[j].name, 528 overlap * time / scale, overlap); 529 } 530# endif DEBUG 531 nl[j].time += overlap * time / scale; 532 } 533 } 534 } 535# ifdef DEBUG 536 if (debug & SAMPLEDEBUG) { 537 printf("[asgnsamples] totime %f\n", totime); 538 } 539# endif DEBUG 540} 541 542 543unsigned long 544min(a, b) 545 unsigned long a,b; 546{ 547 if (a<b) 548 return(a); 549 return(b); 550} 551 552unsigned long 553max(a, b) 554 unsigned long a,b; 555{ 556 if (a>b) 557 return(a); 558 return(b); 559} 560 561 /* 562 * calculate scaled entry point addresses (to save time in asgnsamples), 563 * and possibly push the scaled entry points over the entry mask, 564 * if it turns out that the entry point is in one bucket and the code 565 * for a routine is in the next bucket. 566 */ 567alignentries() 568{ 569 register struct nl *nlp; 570 unsigned long bucket_of_entry; 571 unsigned long bucket_of_code; 572 573 for (nlp = nl; nlp < npe; nlp++) { 574 nlp -> svalue = nlp -> value / HISTORICAL_SCALE_2; 575 bucket_of_entry = (nlp->svalue - lowpc) / scale; 576 bucket_of_code = (nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2 - 577 lowpc) / scale; 578 if (bucket_of_entry < bucket_of_code) { 579# ifdef DEBUG 580 if (debug & SAMPLEDEBUG) { 581 printf("[alignentries] pushing svalue 0x%lx to 0x%lx\n", 582 nlp->svalue, 583 nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2); 584 } 585# endif DEBUG 586 nlp->svalue += OFFSET_OF_CODE / HISTORICAL_SCALE_2; 587 } 588 } 589} 590 591done() 592{ 593 594 exit(0); 595} 596