gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gprof / hist.c
index a3f032907527e21c429c09ce8dfe526e7dabffe7..55dc2007c4a39be086d7e2b579b50c70ca90cd7a 100644 (file)
@@ -1,13 +1,12 @@
 /* hist.c  -  Histogram related operations.
 
 /* hist.c  -  Histogram related operations.
 
-   Copyright 1999, 2000, 2001, 2002, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1999-2020 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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
 \f
-#include "libiberty.h"
 #include "gprof.h"
 #include "gprof.h"
+#include "libiberty.h"
 #include "search_list.h"
 #include "source.h"
 #include "symtab.h"
 #include "search_list.h"
 #include "source.h"
 #include "symtab.h"
@@ -31,6 +30,9 @@
 #include "hist.h"
 #include "sym_ids.h"
 #include "utils.h"
 #include "hist.h"
 #include "sym_ids.h"
 #include "utils.h"
+#include "math.h"
+#include "stdio.h"
+#include "stdlib.h"
 
 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
 
 
 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
 
@@ -42,14 +44,14 @@ static int cmp_time (const PTR, const PTR);
 /* Declarations of automatically generated functions to output blurbs.  */
 extern void flat_blurb (FILE * fp);
 
 /* Declarations of automatically generated functions to output blurbs.  */
 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.  */
-unsigned int hist_num_bins = 0;        /* Number of histogram samples.  */
-int *hist_sample = 0;          /* Histogram samples (shorts in the file!).  */
+static histogram *find_histogram (bfd_vma lowpc, bfd_vma highpc);
+static histogram *find_histogram_for_pc (bfd_vma pc);
+
+histogram * histograms;
+unsigned num_histograms;
 double hist_scale;
 double hist_scale;
-char hist_dimension[16] = "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 total_time;      /* Total time for all routines.  */
 
 static double accum_time;      /* Accumulated time so far for print_line(). */
 static double total_time;      /* Total time for all routines.  */
@@ -76,23 +78,30 @@ SItab[] =
   { 'a', 1e+18 }                               /* ato */
 };
 
   { 'a', 1e+18 }                               /* ato */
 };
 
+/* Reads just the header part of histogram record into
+   *RECORD from IFP.  FILENAME is the name of IFP and
+   is provided for formatting error messages only.
 
 
-/* Read the histogram from file IFP.  FILENAME is the name of IFP and
-   is provided for formatting error messages only.  */
-
-void
-hist_read_rec (FILE * ifp, const char *filename)
+   If FIRST is non-zero, sets global variables HZ, HIST_DIMENSION,
+   HIST_DIMENSION_ABBREV, HIST_SCALE.  If FIRST is zero, checks
+   that the new histogram is compatible with already-set values
+   of those variables and emits an error if that's not so.  */
+static void
+read_histogram_header (histogram *record,
+                      FILE *ifp, const char *filename,
+                      int first)
 {
 {
-  bfd_vma n_lowpc, n_highpc;
-  unsigned int i, ncnt, profrate;
-  UNIT count;
-
-  if (gmon_io_read_vma (ifp, &n_lowpc)
-      || gmon_io_read_vma (ifp, &n_highpc)
-      || gmon_io_read_32 (ifp, &ncnt)
+  unsigned int profrate;
+  char n_hist_dimension[15];
+  char n_hist_dimension_abbrev;
+  double n_hist_scale;
+
+  if (gmon_io_read_vma (ifp, &record->lowpc)
+      || gmon_io_read_vma (ifp, &record->highpc)
+      || gmon_io_read_32 (ifp, &record->num_bins)
       || gmon_io_read_32 (ifp, &profrate)
       || gmon_io_read_32 (ifp, &profrate)
-      || gmon_io_read (ifp, hist_dimension, 15)
-      || gmon_io_read (ifp, &hist_dimension_abbrev, 1))
+      || gmon_io_read (ifp, n_hist_dimension, 15)
+      || gmon_io_read (ifp, &n_hist_dimension_abbrev, 1))
     {
       fprintf (stderr, _("%s: %s: unexpected end of file\n"),
               whoami, filename);
     {
       fprintf (stderr, _("%s: %s: unexpected end of file\n"),
               whoami, filename);
@@ -100,94 +109,178 @@ hist_read_rec (FILE * ifp, const char *filename)
       done (1);
     }
 
       done (1);
     }
 
-  if (!s_highpc)
+  n_hist_scale = (double)((record->highpc - record->lowpc) / sizeof (UNIT))
+    / record->num_bins;
+
+  if (first)
     {
     {
-      /* This is the first histogram record.  */
-      s_lowpc = n_lowpc;
-      s_highpc = n_highpc;
-      lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
-      highpc = (bfd_vma) n_highpc / sizeof (UNIT);
-      hist_num_bins = ncnt;
+      /* We don't try to veryfy profrate is the same for all histogram
+        records.  If we have two histogram records for the same
+        address range and profiling samples is done as often
+        as possible as opposed on timer, then the actual profrate will
+        be slightly different.  Most of the time the difference does not
+        matter and insisting that profiling rate is exactly the same
+        will only create inconvenient.  */
       hz = profrate;
       hz = profrate;
+      memcpy (hist_dimension, n_hist_dimension, 15);
+      hist_dimension_abbrev = n_hist_dimension_abbrev;
+      hist_scale = n_hist_scale;
     }
     }
-
-  DBG (SAMPLEDEBUG,
-       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 %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 != (int) profrate)
+  else
     {
     {
-      fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
-              whoami, filename);
-      done (1);
+      if (strncmp (n_hist_dimension, hist_dimension, 15) != 0)
+       {
+         fprintf (stderr,
+                  _("%s: dimension unit changed between histogram records\n"
+                    "%s: from '%s'\n"
+                    "%s: to '%s'\n"),
+                  whoami, whoami, hist_dimension, whoami, n_hist_dimension);
+         done (1);
+       }
+
+      if (n_hist_dimension_abbrev != hist_dimension_abbrev)
+       {
+         fprintf (stderr,
+                  _("%s: dimension abbreviation changed between histogram records\n"
+                    "%s: from '%c'\n"
+                    "%s: to '%c'\n"),
+                  whoami, whoami, hist_dimension_abbrev, whoami, n_hist_dimension_abbrev);
+         done (1);
+       }
+
+      /* The only reason we require the same scale for histograms is that
+        there's code (notably printing code), that prints units,
+        and it would be very confusing to have one unit mean different
+        things for different functions.  */
+      if (fabs (hist_scale - n_hist_scale) > 0.000001)
+       {
+         fprintf (stderr,
+                  _("%s: different scales in histogram records"),
+                  whoami);
+         done (1);
+       }
     }
     }
+}
 
 
-  if (!hist_sample)
+/* Read the histogram from file IFP.  FILENAME is the name of IFP and
+   is provided for formatting error messages only.  */
+
+void
+hist_read_rec (FILE * ifp, const char *filename)
+{
+  bfd_vma lowpc, highpc;
+  histogram n_record;
+  histogram *record, *existing_record;
+  unsigned i;
+
+  /* 1. Read the header and see if there's existing record for the
+     same address range and that there are no overlapping records.  */
+  read_histogram_header (&n_record, ifp, filename, num_histograms == 0);
+
+  existing_record = find_histogram (n_record.lowpc, n_record.highpc);
+  if (existing_record)
     {
     {
-      hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
-      memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
+      record = existing_record;
     }
     }
+  else
+    {
+      /* If this record overlaps, but does not completely match an existing
+        record, it's an error.  */
+      lowpc = n_record.lowpc;
+      highpc = n_record.highpc;
+      hist_clip_symbol_address (&lowpc, &highpc);
+      if (lowpc != highpc)
+       {
+         fprintf (stderr,
+                  _("%s: overlapping histogram records\n"),
+                  whoami);
+         done (1);
+       }
+
+      /* This is new record.  Add it to global array and allocate space for
+        the samples.  */
+      histograms = (struct histogram *)
+          xrealloc (histograms, sizeof (histogram) * (num_histograms + 1));
+      memcpy (histograms + num_histograms,
+             &n_record, sizeof (histogram));
+      record = &histograms[num_histograms];
+      ++num_histograms;
+
+      record->sample = (int *) xmalloc (record->num_bins
+                                       * sizeof (record->sample[0]));
+      memset (record->sample, 0, record->num_bins * sizeof (record->sample[0]));
+    }
+
+  /* 2. We have either a new record (with zeroed histogram data), or an existing
+     record with some data in the histogram already.  Read new data into the
+     record, adding hit counts.  */
+
+  DBG (SAMPLEDEBUG,
+       printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %u\n",
+              (unsigned long) record->lowpc, (unsigned long) record->highpc,
+               record->num_bins));
 
 
-  for (i = 0; i < hist_num_bins; ++i)
+  for (i = 0; i < record->num_bins; ++i)
     {
     {
+      UNIT count;
       if (fread (&count[0], sizeof (count), 1, ifp) != 1)
        {
          fprintf (stderr,
                  _("%s: %s: unexpected EOF after reading %u of %u samples\n"),
       if (fread (&count[0], sizeof (count), 1, ifp) != 1)
        {
          fprintf (stderr,
                  _("%s: %s: unexpected EOF after reading %u of %u samples\n"),
-                  whoami, filename, i, hist_num_bins);
+                  whoami, filename, i, record->num_bins);
          done (1);
        }
          done (1);
        }
-      hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
+      record->sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
       DBG (SAMPLEDEBUG,
           printf ("[hist_read_rec] 0x%lx: %u\n",
       DBG (SAMPLEDEBUG,
           printf ("[hist_read_rec] 0x%lx: %u\n",
-                  (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt),
-                  hist_sample[i]));
+                  (unsigned long) (record->lowpc
+                                    + i * (record->highpc - record->lowpc)
+                                    / record->num_bins),
+                  record->sample[i]));
     }
 }
 
 
     }
 }
 
 
-/* Write execution histogram to file OFP.  FILENAME is the name
+/* Write all execution histograms file OFP.  FILENAME is the name
    of OFP and is provided for formatting error-messages only.  */
 
 void
 hist_write_hist (FILE * ofp, const char *filename)
 {
   UNIT count;
    of OFP and is provided for formatting error-messages only.  */
 
 void
 hist_write_hist (FILE * ofp, const char *filename)
 {
   UNIT count;
-  unsigned int i;
+  unsigned int i, r;
 
 
-  /* Write header.  */
-
-  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))
+  for (r = 0; r < num_histograms; ++r)
     {
     {
-      perror (filename);
-      done (1);
-    }
+      histogram *record = &histograms[r];
 
 
-  for (i = 0; i < hist_num_bins; ++i)
-    {
-      bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i], (bfd_byte *) &count[0]);
+      /* Write header.  */
 
 
-      if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
+      if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
+         || gmon_io_write_vma (ofp, record->lowpc)
+         || gmon_io_write_vma (ofp, record->highpc)
+         || gmon_io_write_32 (ofp, record->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);
        }
        {
          perror (filename);
          done (1);
        }
+
+      for (i = 0; i < record->num_bins; ++i)
+       {
+         bfd_put_16 (core_bfd, (bfd_vma) record->sample[i], (bfd_byte *) &count[0]);
+
+         if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
     }
 }
 
     }
 }
 
-
 /* Calculate scaled entry point addresses (to save time in
    hist_assign_samples), and, on architectures that have procedure
    entry masks at the start of a function, possibly push the scaled
 /* Calculate scaled entry point addresses (to save time in
    hist_assign_samples), and, on architectures that have procedure
    entry masks at the start of a function, possibly push the scaled
@@ -196,7 +289,7 @@ hist_write_hist (FILE * ofp, const char *filename)
    next bin.  */
 
 static void
    next bin.  */
 
 static void
-scale_and_align_entries ()
+scale_and_align_entries (void)
 {
   Sym *sym;
   bfd_vma bin_of_entry;
 {
   Sym *sym;
   bfd_vma bin_of_entry;
@@ -204,18 +297,24 @@ scale_and_align_entries ()
 
   for (sym = symtab.base; sym < symtab.limit; sym++)
     {
 
   for (sym = symtab.base; sym < symtab.limit; sym++)
     {
+      histogram *r = find_histogram_for_pc (sym->addr);
+
       sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
       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);
-      if (bin_of_entry < bin_of_code)
+
+      if (r)
        {
        {
-         DBG (SAMPLEDEBUG,
-              printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
-                      (unsigned long) sym->hist.scaled_addr,
-                      (unsigned long) (sym->hist.scaled_addr
-                                       + UNITS_TO_CODE)));
-         sym->hist.scaled_addr += UNITS_TO_CODE;
+         bin_of_entry = (sym->hist.scaled_addr - r->lowpc) / hist_scale;
+         bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - r->lowpc)
+                    / hist_scale);
+         if (bin_of_entry < bin_of_code)
+           {
+             DBG (SAMPLEDEBUG,
+                  printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
+                          (unsigned long) sym->hist.scaled_addr,
+                          (unsigned long) (sym->hist.scaled_addr
+                                           + UNITS_TO_CODE)));
+             sym->hist.scaled_addr += UNITS_TO_CODE;
+           }
        }
     }
 }
        }
     }
 }
@@ -258,31 +357,28 @@ scale_and_align_entries ()
    four bytes of text space and never have any overlap (the two end
    cases, above).  */
 
    four bytes of text space and never have any overlap (the two end
    cases, above).  */
 
-void
-hist_assign_samples ()
+static void
+hist_assign_samples_1 (histogram *r)
 {
   bfd_vma bin_low_pc, bin_high_pc;
   bfd_vma sym_low_pc, sym_high_pc;
   bfd_vma overlap, addr;
   unsigned int bin_count;
 {
   bfd_vma bin_low_pc, bin_high_pc;
   bfd_vma sym_low_pc, sym_high_pc;
   bfd_vma overlap, addr;
   unsigned int bin_count;
-  unsigned int i, j;
-  double time, credit;
+  unsigned int i, j, k;
+  double count_time, credit;
 
 
-  /* Read samples and assign to symbols.  */
-  hist_scale = highpc - lowpc;
-  hist_scale /= hist_num_bins;
-  scale_and_align_entries ();
+  bfd_vma lowpc = r->lowpc / sizeof (UNIT);
 
   /* Iterate over all sample bins.  */
 
   /* Iterate over all sample bins.  */
-  for (i = 0, j = 1; i < hist_num_bins; ++i)
+  for (i = 0, k = 1; i < r->num_bins; ++i)
     {
     {
-      bin_count = hist_sample[i];
+      bin_count = r->sample[i];
       if (! bin_count)
        continue;
 
       bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
       bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
       if (! bin_count)
        continue;
 
       bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
       bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
-      time = bin_count;
+      count_time = bin_count;
 
       DBG (SAMPLEDEBUG,
           printf (
 
       DBG (SAMPLEDEBUG,
           printf (
@@ -290,10 +386,13 @@ hist_assign_samples ()
                    (unsigned long) (sizeof (UNIT) * bin_low_pc),
                    (unsigned long) (sizeof (UNIT) * bin_high_pc),
                    bin_count));
                    (unsigned long) (sizeof (UNIT) * bin_low_pc),
                    (unsigned long) (sizeof (UNIT) * bin_high_pc),
                    bin_count));
-      total_time += time;
+      total_time += count_time;
+
+      /* Credit all symbols that are covered by bin I.
 
 
-      /* Credit all symbols that are covered by bin I.  */
-      for (j = j - 1; j < symtab.len; ++j)
+         PR gprof/13325: Make sure that K does not get decremented
+        and J will never be less than 0.  */
+      for (j = k - 1; j < symtab.len; k = ++j)
        {
          sym_low_pc = symtab.base[j].hist.scaled_addr;
          sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
        {
          sym_low_pc = symtab.base[j].hist.scaled_addr;
          sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
@@ -317,11 +416,11 @@ hist_assign_samples ()
               "[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),
               "[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,
+                          symtab.base[j].name, overlap * count_time / hist_scale,
                           (long) overlap));
 
              addr = symtab.base[j].addr;
                           (long) overlap));
 
              addr = symtab.base[j].addr;
-             credit = overlap * time / hist_scale;
+             credit = overlap * count_time / hist_scale;
 
              /* Credit symbol if it appears in INCL_FLAT or that
                 table is empty and it does not appear it in
 
              /* Credit symbol if it appears in INCL_FLAT or that
                 table is empty and it does not appear it in
@@ -344,6 +443,18 @@ hist_assign_samples ()
                            total_time));
 }
 
                            total_time));
 }
 
+/* Calls 'hist_assign_sampes_1' for all histogram records read so far. */
+void
+hist_assign_samples (void)
+{
+  unsigned i;
+
+  scale_and_align_entries ();
+
+  for (i = 0; i < num_histograms; ++i)
+    hist_assign_samples_1 (&histograms[i]);
+
+}
 
 /* Print header for flag histogram profile.  */
 
 
 /* Print header for flag histogram profile.  */
 
@@ -357,7 +468,7 @@ print_header (int prefix)
   if (bsd_style_output)
     {
       printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
   if (bsd_style_output)
     {
       printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
-             (long) hist_scale * sizeof (UNIT));
+             (long) hist_scale * (long) sizeof (UNIT));
       if (total_time > 0.0)
        {
          printf (_(" for %.2f%% of %.2f %s\n\n"),
       if (total_time > 0.0)
        {
          printf (_(" for %.2f%% of %.2f %s\n\n"),
@@ -451,12 +562,12 @@ cmp_time (const PTR lp, const PTR rp)
 /* Print the flat histogram profile.  */
 
 void
 /* Print the flat histogram profile.  */
 
 void
-hist_print ()
+hist_print (void)
 {
   Sym **time_sorted_syms, *top_dog, *sym;
 {
   Sym **time_sorted_syms, *top_dog, *sym;
-  unsigned int index;
+  unsigned int sym_index;
   unsigned log_scale;
   unsigned log_scale;
-  double top_time, time;
+  double top_time;
   bfd_vma addr;
 
   if (first_output)
   bfd_vma addr;
 
   if (first_output)
@@ -483,8 +594,8 @@ hist_print ()
      and tertiary keys).  */
   time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
 
      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];
+  for (sym_index = 0; sym_index < symtab.len; ++sym_index)
+    time_sorted_syms[sym_index] = &symtab.base[sym_index];
 
   qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
 
 
   qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
 
@@ -500,18 +611,20 @@ hist_print ()
       top_dog = 0;
       top_time = 0.0;
 
       top_dog = 0;
       top_time = 0.0;
 
-      for (index = 0; index < symtab.len; ++index)
+      for (sym_index = 0; sym_index < symtab.len; ++sym_index)
        {
        {
-         sym = time_sorted_syms[index];
+         sym = time_sorted_syms[sym_index];
 
          if (sym->ncalls != 0)
            {
 
          if (sym->ncalls != 0)
            {
-             time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
+             double call_time;
 
 
-             if (time > top_time)
+             call_time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
+
+             if (call_time > top_time)
                {
                  top_dog = sym;
                {
                  top_dog = sym;
-                 top_time = time;
+                 top_time = call_time;
                }
            }
        }
                }
            }
        }
@@ -524,7 +637,7 @@ hist_print ()
            {
              double scaled_value = SItab[log_scale].scale * top_time;
 
            {
              double scaled_value = SItab[log_scale].scale * top_time;
 
-             if (scaled_value >= 1.0 && scaled_value < 1000.0) 
+             if (scaled_value >= 1.0 && scaled_value < 1000.0)
                break;
            }
        }
                break;
            }
        }
@@ -535,16 +648,16 @@ hist_print ()
      I-cache misses etc.).  */
   print_header (SItab[log_scale].prefix);
 
      I-cache misses etc.).  */
   print_header (SItab[log_scale].prefix);
 
-  for (index = 0; index < symtab.len; ++index)
+  for (sym_index = 0; sym_index < symtab.len; ++sym_index)
     {
     {
-      addr = time_sorted_syms[index]->addr;
+      addr = time_sorted_syms[sym_index]->addr;
 
       /* Print symbol if its in INCL_FLAT table or that table
        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 symbol if its in INCL_FLAT table or that table
        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);
+       print_line (time_sorted_syms[sym_index], SItab[log_scale].scale);
     }
 
   free (time_sorted_syms);
     }
 
   free (time_sorted_syms);
@@ -552,3 +665,90 @@ hist_print ()
   if (print_descriptions && !bsd_style_output)
     flat_blurb (stdout);
 }
   if (print_descriptions && !bsd_style_output)
     flat_blurb (stdout);
 }
+
+int
+hist_check_address (unsigned address)
+{
+  unsigned i;
+
+  for (i = 0; i < num_histograms; ++i)
+    if (histograms[i].lowpc <= address && address < histograms[i].highpc)
+      return 1;
+
+  return 0;
+}
+
+#if ! defined(min)
+#define min(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+#if ! defined(max)
+#define max(a,b) (((a)>(b)) ? (a) : (b))
+#endif
+
+void
+hist_clip_symbol_address (bfd_vma *p_lowpc, bfd_vma *p_highpc)
+{
+  unsigned i;
+  int found = 0;
+
+  if (num_histograms == 0)
+    {
+      *p_highpc = *p_lowpc;
+      return;
+    }
+
+  for (i = 0; i < num_histograms; ++i)
+    {
+      bfd_vma common_low, common_high;
+      common_low = max (histograms[i].lowpc, *p_lowpc);
+      common_high = min (histograms[i].highpc, *p_highpc);
+
+      if (common_low < common_high)
+       {
+         if (found)
+           {
+             fprintf (stderr,
+                      _("%s: found a symbol that covers "
+                        "several histogram records"),
+                        whoami);
+             done (1);
+           }
+
+         found = 1;
+         *p_lowpc = common_low;
+         *p_highpc = common_high;
+       }
+    }
+
+  if (!found)
+    *p_highpc = *p_lowpc;
+}
+
+/* Find and return exising histogram record having the same lowpc and
+   highpc as passed via the parameters.  Return NULL if nothing is found.
+   The return value is valid until any new histogram is read.  */
+static histogram *
+find_histogram (bfd_vma lowpc, bfd_vma highpc)
+{
+  unsigned i;
+  for (i = 0; i < num_histograms; ++i)
+    {
+      if (histograms[i].lowpc == lowpc && histograms[i].highpc == highpc)
+       return &histograms[i];
+    }
+  return 0;
+}
+
+/* Given a PC, return histogram record which address range include this PC.
+   Return NULL if there's no such record.  */
+static histogram *
+find_histogram_for_pc (bfd_vma pc)
+{
+  unsigned i;
+  for (i = 0; i < num_histograms; ++i)
+    {
+      if (histograms[i].lowpc <= pc && pc < histograms[i].highpc)
+       return &histograms[i];
+    }
+  return 0;
+}
This page took 0.031187 seconds and 4 git commands to generate.