shorten name of blurb file
[unix-history] / usr / src / usr.bin / gprof / gprof.c
index 50c9fbb..a382081 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-    static     char *sccsid = "@(#)gprof.c     1.15 (Berkeley) %G%";
+    static     char *sccsid = "@(#)gprof.c     1.24 (Berkeley) %G%";
 #endif lint
 
 #include "gprof.h"
 #endif lint
 
 #include "gprof.h"
@@ -16,10 +16,12 @@ main(argc, argv)
     char **argv;
 {
     char       **sp;
     char **argv;
 {
     char       **sp;
+    nltype     **timesortnlp;
 
     --argc;
     argv++;
     debug = 0;
 
     --argc;
     argv++;
     debug = 0;
+    bflag = TRUE;
     while ( *argv != 0 && **argv == '-' ) {
        (*argv)++;
        switch ( **argv ) {
     while ( *argv != 0 && **argv == '-' ) {
        (*argv)++;
        switch ( **argv ) {
@@ -27,7 +29,7 @@ main(argc, argv)
            aflag = TRUE;
            break;
        case 'b':
            aflag = TRUE;
            break;
        case 'b':
-           bflag = TRUE;
+           bflag = FALSE;
            break;
        case 'c':
            cflag = TRUE;
            break;
        case 'c':
            cflag = TRUE;
@@ -38,7 +40,9 @@ main(argc, argv)
            debug |= atoi( *argv );
            debug |= ANYDEBUG;
 #          ifdef DEBUG
            debug |= atoi( *argv );
            debug |= ANYDEBUG;
 #          ifdef DEBUG
-               printf( "[main] debug = %d\n" , debug );
+               printf("[main] debug = %d\n", debug);
+#          else not DEBUG
+               printf("%s: -d ignored\n", whoami);
 #          endif DEBUG
            break;
        case 'E':
 #          endif DEBUG
            break;
        case 'E':
@@ -92,6 +96,15 @@ main(argc, argv)
        addlist( Elist , *sp );
        eflag = TRUE;
        addlist( elist , *sp );
        addlist( Elist , *sp );
        eflag = TRUE;
        addlist( elist , *sp );
+    }
+       /*
+        *      how many ticks per second?
+        *      if we can't tell, report time in ticks.
+        */
+    hz = hertz();
+    if (hz == 0) {
+       hz = 1;
+       fprintf(stderr, "time is in ticks, not seconds\n");
     }
        /*
         *      get information about a.out file.
     }
        /*
         *      get information about a.out file.
@@ -117,13 +130,21 @@ main(argc, argv)
         */
     asgnsamples();
        /*
         */
     asgnsamples();
        /*
-        *      print the usual profile
+        *      assemble the dynamic profile
+        */
+    timesortnlp = doarcs();
+       /*
+        *      print the dynamic profile
+        */
+    printgprof( timesortnlp ); 
+       /*
+        *      print the flat profile
         */
     printprof();       
        /*
         */
     printprof();       
        /*
-        *      assemble and print the dynamic profile
+        *      print the index
         */
         */
-    doarcs();
+    printindex();      
     done();
 }
 
     done();
 }
 
@@ -244,7 +265,6 @@ getsymtab(nfile)
        nname++;
     }
     npe->value = -1;
        nname++;
     }
     npe->value = -1;
-    npe++;
 }
 
     /*
 }
 
     /*
@@ -327,8 +347,8 @@ openpfile(filename)
     h = tmp;
     s_lowpc = (unsigned long) h.lowpc;
     s_highpc = (unsigned long) h.highpc;
     h = tmp;
     s_lowpc = (unsigned long) h.lowpc;
     s_highpc = (unsigned long) h.highpc;
-    lowpc = h.lowpc - (UNIT *)0;
-    highpc = h.highpc - (UNIT *)0;
+    lowpc = (unsigned long)h.lowpc / sizeof(UNIT);
+    highpc = (unsigned long)h.highpc / sizeof(UNIT);
     sampbytes = h.ncnt - sizeof(struct hdr);
     nsamples = sampbytes / sizeof (unsigned UNIT);
 #   ifdef DEBUG
     sampbytes = h.ncnt - sizeof(struct hdr);
     nsamples = sampbytes / sizeof (unsigned UNIT);
 #   ifdef DEBUG
@@ -396,7 +416,7 @@ dumpsum( sumfile )
     /*
      * dump the normalized raw arc information
      */
     /*
      * dump the normalized raw arc information
      */
-    for ( nlp = nl ; nlp < npe - 1 ; nlp++ ) {
+    for ( nlp = nl ; nlp < npe ; nlp++ ) {
        for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
            arc.raw_frompc = arcp -> arc_parentp -> value;
            arc.raw_selfpc = arcp -> arc_childp -> value;
        for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
            arc.raw_frompc = arcp -> arc_parentp -> value;
            arc.raw_selfpc = arcp -> arc_childp -> value;
@@ -457,7 +477,36 @@ readsamples(pfile)
 }
 
 /*
 }
 
 /*
- * Assign samples to the procedures to which they belong.
+ *     Assign samples to the procedures to which they belong.
+ *
+ *     There are three cases as to where pcl and pch can be
+ *     with respect to the routine entry addresses svalue0 and svalue1
+ *     as shown in the following diagram.  overlap computes the
+ *     distance between the arrows, the fraction of the sample
+ *     that is to be credited to the routine which starts at svalue0.
+ *
+ *         svalue0                                         svalue1
+ *            |                                               |
+ *            v                                               v
+ *
+ *            +-----------------------------------------------+
+ *            |                                               |
+ *       |  ->|    |<-         ->|         |<-         ->|    |<-  |
+ *       |         |             |         |             |         |
+ *       +---------+             +---------+             +---------+
+ *
+ *       ^         ^             ^         ^             ^         ^
+ *       |         |             |         |             |         |
+ *      pcl       pch           pcl       pch           pcl       pch
+ *
+ *     For the vax we assert that samples will never fall in the first
+ *     two bytes of any routine, since that is the entry mask,
+ *     thus we give call alignentries() to adjust the entry points if
+ *     the entry mask falls in one bucket but the code for the routine
+ *     doesn't start until the next bucket.  In conjunction with the
+ *     alignment of routine addresses, this should allow us to have
+ *     only one sample for every four bytes of text space and never
+ *     have any overlap (the two end cases, above).
  */
 asgnsamples()
 {
  */
 asgnsamples()
 {
@@ -472,12 +521,13 @@ asgnsamples()
     /* read samples and assign to namelist symbols */
     scale = highpc - lowpc;
     scale /= nsamples;
     /* read samples and assign to namelist symbols */
     scale = highpc - lowpc;
     scale /= nsamples;
-    for (i=0; i < nsamples; i++) {
+    alignentries();
+    for (i = 0, j = 1; i < nsamples; i++) {
        ccnt = samples[i];
        if (ccnt == 0)
                continue;
        ccnt = samples[i];
        if (ccnt == 0)
                continue;
-       pcl = lowpc + scale*i;
-       pch = lowpc + scale*(i+1);
+       pcl = lowpc + scale * i;
+       pch = lowpc + scale * (i + 1);
        time = ccnt;
 #      ifdef DEBUG
            if ( debug & SAMPLEDEBUG ) {
        time = ccnt;
 #      ifdef DEBUG
            if ( debug & SAMPLEDEBUG ) {
@@ -486,29 +536,38 @@ asgnsamples()
            }
 #      endif DEBUG
        totime += time;
            }
 #      endif DEBUG
        totime += time;
-       for (j=0; j<nname; j++) {
-           svalue0 = nl[j].value / sizeof(UNIT);
-           svalue1 = nl[j+1].value / sizeof(UNIT);
+       for (j = j - 1; j < nname; j++) {
+           svalue0 = nl[j].svalue;
+           svalue1 = nl[j+1].svalue;
+               /*
+                *      if high end of tick is below entry address, 
+                *      go for next tick.
+                */
            if (pch < svalue0)
                    break;
            if (pch < svalue0)
                    break;
+               /*
+                *      if low end of tick into next routine,
+                *      go for next routine.
+                */
            if (pcl >= svalue1)
                    continue;
            if (pcl >= svalue1)
                    continue;
-           overlap=min(pch,svalue1) - max(pcl,svalue0);
-           if (overlap>0) {
+           overlap = min(pch, svalue1) - max(pcl, svalue0);
+           if (overlap > 0) {
 #              ifdef DEBUG
 #              ifdef DEBUG
-                   if ( debug & SAMPLEDEBUG ) {
-                       printf( "[asgnsamples] (0x%x-0x%x) %s gets %f ticks\n" ,
-                               svalue0 , svalue1 , nl[j].name , 
-                               overlap*time/scale );
+                   if (debug & SAMPLEDEBUG) {
+                       printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n",
+                               nl[j].value/sizeof(UNIT), svalue0, svalue1,
+                               nl[j].name, 
+                               overlap * time / scale, overlap);
                    }
 #              endif DEBUG
                    }
 #              endif DEBUG
-               nl[j].time += overlap*time/scale;
+               nl[j].time += overlap * time / scale;
            }
        }
     }
 #   ifdef DEBUG
            }
        }
     }
 #   ifdef DEBUG
-       if ( debug & SAMPLEDEBUG ) {
-           printf( "[asgnsamples] totime %f\n" , totime );
+       if (debug & SAMPLEDEBUG) {
+           printf("[asgnsamples] totime %f\n", totime);
        }
 #   endif DEBUG
 }
        }
 #   endif DEBUG
 }
@@ -532,6 +591,34 @@ max(a, b)
     return(b);
 }
 
     return(b);
 }
 
+    /*
+     * calculate scaled entry point addresses (to save time in asgnsamples),
+     * and possibly push the scaled entry points over the entry mask,
+     * if it turns out that the entry point is in one bucket and the code
+     * for a routine is in the next bucket.
+     */
+alignentries()
+{
+    register struct nl *nlp;
+    unsigned long      bucket_of_entry;
+    unsigned long      bucket_of_code;
+
+    for (nlp = nl; nlp < npe; nlp++) {
+       nlp -> svalue = nlp -> value / sizeof(UNIT);
+       bucket_of_entry = (nlp->svalue - lowpc) / scale;
+       bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale;
+       if (bucket_of_entry < bucket_of_code) {
+#          ifdef DEBUG
+               if (debug & SAMPLEDEBUG) {
+                   printf("[alignentries] pushing svalue 0x%x to 0x%x\n",
+                           nlp->svalue, nlp->svalue + UNITS_TO_CODE);
+               }
+#          endif DEBUG
+           nlp->svalue += UNITS_TO_CODE;
+       }
+    }
+}
+
 bool
 funcsymbol( nlistp )
     struct nlist       *nlistp;
 bool
 funcsymbol( nlistp )
     struct nlist       *nlistp;