daily update
[deliverable/binutils-gdb.git] / gprof / hist.c
index f63e37db5ac46b7a605b1512c7639e62cd5f3c75..024f6653e662194638034a85a91a9b7c790901fd 100644 (file)
@@ -1,6 +1,7 @@
 /* hist.c  -  Histogram related operations.
 
-   Copyright 2000 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002, 2004, 2005
+   Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 \f
-#include <stdio.h>
 #include "libiberty.h"
 #include "gprof.h"
+#include "search_list.h"
+#include "source.h"
+#include "symtab.h"
 #include "corefile.h"
 #include "gmon_io.h"
 #include "gmon_out.h"
 #include "hist.h"
-#include "symtab.h"
 #include "sym_ids.h"
 #include "utils.h"
 
 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
 
-static void scale_and_align_entries PARAMS ((void));
+static void scale_and_align_entries (void);
+static void print_header (int);
+static void print_line (Sym *, double);
+static int cmp_time (const PTR, const PTR);
 
 /* Declarations of automatically generated functions to output blurbs.  */
-extern void flat_blurb PARAMS ((FILE * fp));
+extern void flat_blurb (FILE * fp);
 
 bfd_vma s_lowpc;               /* Lowest address in .text.  */
 bfd_vma s_highpc = 0;          /* Highest address in .text.  */
 bfd_vma lowpc, highpc;         /* Same, but expressed in UNITs.  */
-int hist_num_bins = 0;         /* Number of histogram samples.  */
+unsigned int hist_num_bins = 0;        /* Number of histogram samples.  */
 int *hist_sample = 0;          /* Histogram samples (shorts in the file!).  */
 double hist_scale;
-char hist_dimension[sizeof (((struct gmon_hist_hdr *) 0)->dimen) + 1] =
-  "seconds";
-char hist_dimension_abbrev = 's';
+static char hist_dimension[16] = "seconds";
+static char hist_dimension_abbrev = 's';
 
-static double accum_time;      /* Accumulated time so far for print_line().  */
+static double accum_time;      /* Accumulated time so far for print_line(). */
 static double total_time;      /* Total time for all routines.  */
 
 /* Table of SI prefixes for powers of 10 (used to automatically
@@ -59,50 +63,17 @@ const struct
   }
 SItab[] =
 {
-  {
-    'T', 1e-12
-  }
-  ,                            /* tera */
-  {
-    'G', 1e-09
-  }
-  ,                            /* giga */
-  {
-    'M', 1e-06
-  }
-  ,                            /* mega */
-  {
-    'K', 1e-03
-  }
-  ,                            /* kilo */
-  {
-    ' ', 1e-00
-  }
-  ,
-  {
-    'm', 1e+03
-  }
-  ,                            /* milli */
-  {
-    'u', 1e+06
-  }
-  ,                            /* micro */
-  {
-    'n', 1e+09
-  }
-  ,                            /* nano */
-  {
-    'p', 1e+12
-  }
-  ,                            /* pico */
-  {
-    'f', 1e+15
-  }
-  ,                            /* femto */
-  {
-    'a', 1e+18
-  }
-  ,                            /* ato */
+  { 'T', 1e-12 },                              /* tera */
+  { 'G', 1e-09 },                              /* giga */
+  { 'M', 1e-06 },                              /* mega */
+  { 'K', 1e-03 },                              /* kilo */
+  { ' ', 1e-00 },
+  { 'm', 1e+03 },                              /* milli */
+  { 'u', 1e+06 },                              /* micro */
+  { 'n', 1e+09 },                              /* nano */
+  { 'p', 1e+12 },                              /* pico */
+  { 'f', 1e+15 },                              /* femto */
+  { 'a', 1e+18 }                               /* ato */
 };
 
 
@@ -110,28 +81,25 @@ SItab[] =
    is provided for formatting error messages only.  */
 
 void
-DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
+hist_read_rec (FILE * ifp, const char *filename)
 {
-  struct gmon_hist_hdr hdr;
   bfd_vma n_lowpc, n_highpc;
-  int i, ncnt, profrate;
+  unsigned int i, ncnt, profrate;
   UNIT count;
 
-  if (fread (&hdr, sizeof (hdr), 1, ifp) != 1)
+  if (gmon_io_read_vma (ifp, &n_lowpc)
+      || gmon_io_read_vma (ifp, &n_highpc)
+      || gmon_io_read_32 (ifp, &ncnt)
+      || gmon_io_read_32 (ifp, &profrate)
+      || gmon_io_read (ifp, hist_dimension, 15)
+      || gmon_io_read (ifp, &hist_dimension_abbrev, 1))
     {
       fprintf (stderr, _("%s: %s: unexpected end of file\n"),
               whoami, filename);
+
       done (1);
     }
 
-  n_lowpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.low_pc);
-  n_highpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.high_pc);
-  ncnt = bfd_get_32 (core_bfd, (bfd_byte *) hdr.hist_size);
-  profrate = bfd_get_32 (core_bfd, (bfd_byte *) hdr.prof_rate);
-  strncpy (hist_dimension, hdr.dimen, sizeof (hdr.dimen));
-  hist_dimension[sizeof (hdr.dimen)] = '\0';
-  hist_dimension_abbrev = hdr.dimen_abbrev;
-
   if (!s_highpc)
     {
       /* This is the first histogram record.  */
@@ -144,16 +112,16 @@ DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
     }
 
   DBG (SAMPLEDEBUG,
-       printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
+       printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %u\n",
               (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
-       printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
+       printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %u\n",
               (unsigned long) s_lowpc, (unsigned long) s_highpc,
               hist_num_bins);
        printf ("[hist_read_rec]   lowpc 0x%lx   highpc 0x%lx\n",
               (unsigned long) lowpc, (unsigned long) highpc));
 
   if (n_lowpc != s_lowpc || n_highpc != s_highpc
-      || ncnt != hist_num_bins || hz != profrate)
+      || ncnt != hist_num_bins || hz != (int) profrate)
     {
       fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
               whoami, filename);
@@ -171,11 +139,15 @@ DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
       if (fread (&count[0], sizeof (count), 1, ifp) != 1)
        {
          fprintf (stderr,
-                  _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
+                 _("%s: %s: unexpected EOF after reading %u of %u samples\n"),
                   whoami, filename, i, hist_num_bins);
          done (1);
        }
       hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
+      DBG (SAMPLEDEBUG,
+          printf ("[hist_read_rec] 0x%lx: %u\n",
+                  (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt),
+                  hist_sample[i]));
     }
 }
 
@@ -184,25 +156,20 @@ DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
    of OFP and is provided for formatting error-messages only.  */
 
 void
-DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
+hist_write_hist (FILE * ofp, const char *filename)
 {
-  struct gmon_hist_hdr hdr;
-  unsigned char tag;
   UNIT count;
-  int i;
+  unsigned int i;
 
   /* Write header.  */
 
-  tag = GMON_TAG_TIME_HIST;
-  put_vma (core_bfd, s_lowpc, (bfd_byte *) hdr.low_pc);
-  put_vma (core_bfd, s_highpc, (bfd_byte *) hdr.high_pc);
-  bfd_put_32 (core_bfd, hist_num_bins, (bfd_byte *) hdr.hist_size);
-  bfd_put_32 (core_bfd, hz, (bfd_byte *) hdr.prof_rate);
-  strncpy (hdr.dimen, hist_dimension, sizeof (hdr.dimen));
-  hdr.dimen_abbrev = hist_dimension_abbrev;
-
-  if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
-      || fwrite (&hdr, sizeof (hdr), 1, ofp) != 1)
+  if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
+      || gmon_io_write_vma (ofp, s_lowpc)
+      || gmon_io_write_vma (ofp, s_highpc)
+      || gmon_io_write_32 (ofp, hist_num_bins)
+      || gmon_io_write_32 (ofp, hz)
+      || gmon_io_write (ofp, hist_dimension, 15)
+      || gmon_io_write (ofp, &hist_dimension_abbrev, 1))
     {
       perror (filename);
       done (1);
@@ -210,8 +177,8 @@ DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
 
   for (i = 0; i < hist_num_bins; ++i)
     {
-      bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
-      
+      bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i], (bfd_byte *) &count[0]);
+
       if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
        {
          perror (filename);
@@ -239,7 +206,8 @@ scale_and_align_entries ()
     {
       sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
       bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
-      bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale;
+      bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - lowpc)
+                    / hist_scale);
       if (bin_of_entry < bin_of_code)
        {
          DBG (SAMPLEDEBUG,
@@ -254,33 +222,33 @@ scale_and_align_entries ()
 
 
 /* Assign samples to the symbol to which they belong.
-  
+
    Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
    which may overlap one more symbol address ranges.  If a symbol
    overlaps with the bin's address range by O percent, then O percent
    of the bin's count is credited to that symbol.
-  
+
    There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
    with respect to the symbol's address range [SYM_LOW_PC,
    SYM_HIGH_PC) as shown in the following diagram.  OVERLAP computes
    the distance (in UNITs) between the arrows, the fraction of the
    sample that is to be credited to the symbol which starts at
    SYM_LOW_PC.
-  
-          sym_low_pc                                      sym_high_pc
-               |                                               |
-               v                                               v
-  
-               +-----------------------------------------------+
-               |                                               |
-          |  ->|    |<-         ->|         |<-         ->|    |<-  |
-          |         |             |         |             |         |
-          +---------+             +---------+             +---------+
-  
-          ^         ^             ^         ^             ^         ^
-          |         |             |         |             |         |
+
+         sym_low_pc                                      sym_high_pc
+              |                                               |
+              v                                               v
+
+              +-----------------------------------------------+
+              |                                               |
+         |  ->|    |<-         ->|         |<-         ->|    |<-  |
+         |         |             |         |             |         |
+         +---------+             +---------+             +---------+
+
+         ^         ^             ^         ^             ^         ^
+         |         |             |         |             |         |
      bin_low_pc bin_high_pc  bin_low_pc bin_high_pc  bin_low_pc bin_high_pc
-  
+
    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 call
    scale_and_align_entries() to adjust the entry points if the entry
@@ -291,13 +259,13 @@ scale_and_align_entries ()
    cases, above).  */
 
 void
-DEFUN_VOID (hist_assign_samples)
+hist_assign_samples ()
 {
   bfd_vma bin_low_pc, bin_high_pc;
   bfd_vma sym_low_pc, sym_high_pc;
   bfd_vma overlap, addr;
-  int bin_count, i;
-  unsigned int j;
+  unsigned int bin_count;
+  unsigned int i, j;
   double time, credit;
 
   /* Read samples and assign to symbols.  */
@@ -315,10 +283,10 @@ DEFUN_VOID (hist_assign_samples)
       bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
       bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
       time = bin_count;
-      
+
       DBG (SAMPLEDEBUG,
           printf (
-      "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
+      "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%u\n",
                    (unsigned long) (sizeof (UNIT) * bin_low_pc),
                    (unsigned long) (sizeof (UNIT) * bin_high_pc),
                    bin_count));
@@ -329,7 +297,7 @@ DEFUN_VOID (hist_assign_samples)
        {
          sym_low_pc = symtab.base[j].hist.scaled_addr;
          sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
-         
+
          /* If high end of bin is below entry address,
             go for next bin.  */
          if (bin_high_pc < sym_low_pc)
@@ -346,18 +314,18 @@ DEFUN_VOID (hist_assign_samples)
            {
              DBG (SAMPLEDEBUG,
                   printf (
-                           "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
-                           (unsigned long) symtab.base[j].addr,
-                           (unsigned long) (sizeof (UNIT) * sym_high_pc),
-                           symtab.base[j].name, overlap * time / hist_scale,
-                           (long) overlap));
-             
+              "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
+                          (unsigned long) symtab.base[j].addr,
+                          (unsigned long) (sizeof (UNIT) * sym_high_pc),
+                          symtab.base[j].name, overlap * time / hist_scale,
+                          (long) overlap));
+
              addr = symtab.base[j].addr;
              credit = overlap * time / hist_scale;
-             
+
              /* Credit symbol if it appears in INCL_FLAT or that
-                table is empty and it does not appear it in
-                EXCL_FLAT.  */
+                table is empty and it does not appear it in
+                EXCL_FLAT.  */
              if (sym_lookup (&syms[INCL_FLAT], addr)
                  || (syms[INCL_FLAT].len == 0
                      && !sym_lookup (&syms[EXCL_FLAT], addr)))
@@ -371,7 +339,7 @@ DEFUN_VOID (hist_assign_samples)
            }
        }
     }
-  
+
   DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
                            total_time));
 }
@@ -380,7 +348,7 @@ DEFUN_VOID (hist_assign_samples)
 /* Print header for flag histogram profile.  */
 
 static void
-DEFUN (print_header, (prefix), const char prefix)
+print_header (int prefix)
 {
   char unit[64];
 
@@ -404,13 +372,14 @@ DEFUN (print_header, (prefix), const char prefix)
   if (total_time <= 0.0)
     {
       printf (_(" no time accumulated\n\n"));
-      
+
       /* This doesn't hurt since all the numerators will be zero.  */
       total_time = 1.0;
     }
 
   printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
-         "%  ", _("cumulative"), _("self  "), "", _("self  "), _("total "), "");
+         "%  ", _("cumulative"), _("self  "), "", _("self  "), _("total "),
+         "");
   printf ("%5.5s %9.9s  %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
          _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
          _("name"));
@@ -418,13 +387,13 @@ DEFUN (print_header, (prefix), const char prefix)
 
 
 static void
-DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
+print_line (Sym *sym, double scale)
 {
   if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
     return;
 
   accum_time += sym->hist.time;
-  
+
   if (bsd_style_output)
     printf ("%5.1f %10.2f %8.2f",
            total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
@@ -433,14 +402,14 @@ DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
     printf ("%6.2f %9.2f %8.2f",
            total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
            accum_time / hz, sym->hist.time / hz);
-  
+
   if (sym->ncalls != 0)
     printf (" %8lu %8.2f %8.2f  ",
            sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
            scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
   else
     printf (" %8.8s %8.8s %8.8s  ", "", "", "");
-  
+
   if (bsd_style_output)
     print_name (sym);
   else
@@ -455,17 +424,17 @@ DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
    lexicographic order of the function names.  */
 
 static int
-DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
+cmp_time (const PTR lp, const PTR rp)
 {
   const Sym *left = *(const Sym **) lp;
   const Sym *right = *(const Sym **) rp;
   double time_diff;
 
   time_diff = right->hist.time - left->hist.time;
-  
+
   if (time_diff > 0.0)
     return 1;
-  
+
   if (time_diff < 0.0)
     return -1;
 
@@ -482,11 +451,11 @@ DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
 /* Print the flat histogram profile.  */
 
 void
-DEFUN_VOID (hist_print)
+hist_print ()
 {
   Sym **time_sorted_syms, *top_dog, *sym;
   unsigned int index;
-  int log_scale;
+  unsigned log_scale;
   double top_time, time;
   bfd_vma addr;
 
@@ -496,7 +465,7 @@ DEFUN_VOID (hist_print)
     printf ("\f\n");
 
   accum_time = 0.0;
-  
+
   if (bsd_style_output)
     {
       if (print_descriptions)
@@ -509,11 +478,11 @@ DEFUN_VOID (hist_print)
     {
       printf (_("Flat profile:\n"));
     }
-  
+
   /* Sort the symbol table by time (call-count and name as secondary
      and tertiary keys).  */
   time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
-  
+
   for (index = 0; index < symtab.len; ++index)
     time_sorted_syms[index] = &symtab.base[index];
 
@@ -530,15 +499,15 @@ DEFUN_VOID (hist_print)
       log_scale = 0;
       top_dog = 0;
       top_time = 0.0;
-      
+
       for (index = 0; index < symtab.len; ++index)
        {
          sym = time_sorted_syms[index];
-         
+
          if (sym->ncalls != 0)
            {
              time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
-             
+
              if (time > top_time)
                {
                  top_dog = sym;
@@ -546,16 +515,17 @@ DEFUN_VOID (hist_print)
                }
            }
        }
-      
+
       if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
        {
          top_time /= hz;
-         
-         while (SItab[log_scale].scale * top_time < 1000.0
-                && ((size_t) log_scale
-                    < sizeof (SItab) / sizeof (SItab[0]) - 1))
+
+         for (log_scale = 0; log_scale < ARRAY_SIZE (SItab); log_scale ++)
            {
-             ++log_scale;
+             double scaled_value = SItab[log_scale].scale * top_time;
+
+             if (scaled_value >= 1.0 && scaled_value < 1000.0) 
+               break;
            }
        }
     }
@@ -564,19 +534,19 @@ DEFUN_VOID (hist_print)
      may also want to support other (pseudo-)dimensions (such as
      I-cache misses etc.).  */
   print_header (SItab[log_scale].prefix);
-  
+
   for (index = 0; index < symtab.len; ++index)
     {
       addr = time_sorted_syms[index]->addr;
-      
+
       /* Print symbol if its in INCL_FLAT table or that table
-        is empty and the symbol is not in EXCL_FLAT.  */
+       is empty and the symbol is not in EXCL_FLAT.  */
       if (sym_lookup (&syms[INCL_FLAT], addr)
          || (syms[INCL_FLAT].len == 0
              && !sym_lookup (&syms[EXCL_FLAT], addr)))
        print_line (time_sorted_syms[index], SItab[log_scale].scale);
     }
-  
+
   free (time_sorted_syms);
 
   if (print_descriptions && !bsd_style_output)
This page took 0.070491 seconds and 4 git commands to generate.