/* hist.c - Histogram related operations.
- Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
This file is part of GNU Binutils.
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
\f
-#include "libiberty.h"
#include "gprof.h"
+#include "libiberty.h"
#include "search_list.h"
#include "source.h"
#include "symtab.h"
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;
static char hist_dimension[16] = "seconds";
static char hist_dimension_abbrev = 's';
/* 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.
+ is provided for formatting error messages only.
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,
+read_histogram_header (histogram *record,
FILE *ifp, const char *filename,
int first)
{
done (1);
}
- n_hist_scale = (double)((record->highpc - record->lowpc) / sizeof (UNIT))
+ n_hist_scale = (double)((record->highpc - record->lowpc) / sizeof (UNIT))
/ record->num_bins;
if (first)
hz = profrate;
memcpy (hist_dimension, n_hist_dimension, 15);
hist_dimension_abbrev = n_hist_dimension_abbrev;
- hist_scale = n_hist_scale;
+ hist_scale = n_hist_scale;
}
else
{
if (strncmp (n_hist_dimension, hist_dimension, 15) != 0)
{
- fprintf (stderr,
+ fprintf (stderr,
_("%s: dimension unit changed between histogram records\n"
"%s: from '%s'\n"
"%s: to '%s'\n"),
if (n_hist_dimension_abbrev != hist_dimension_abbrev)
{
- fprintf (stderr,
+ 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);
+ done (1);
}
/* The only reason we require the same scale for histograms is that
things for different functions. */
if (fabs (hist_scale - n_hist_scale) > 0.000001)
{
- fprintf (stderr,
+ fprintf (stderr,
_("%s: different scales in histogram records"),
whoami);
- done (1);
+ done (1);
}
}
}
hist_clip_symbol_address (&lowpc, &highpc);
if (lowpc != highpc)
{
- fprintf (stderr,
+ fprintf (stderr,
_("%s: overlapping histogram records\n"),
whoami);
- done (1);
+ done (1);
}
/* This is new record. Add it to global array and allocate space for
the samples. */
- histograms = xrealloc (histograms,
- sizeof (histogram) * (num_histograms + 1));
+ histograms = (struct histogram *)
+ xrealloc (histograms, sizeof (histogram) * (num_histograms + 1));
memcpy (histograms + num_histograms,
&n_record, sizeof (histogram));
- record = &histograms[num_histograms];
+ record = &histograms[num_histograms];
++num_histograms;
- record->sample = (int *) xmalloc (record->num_bins
+ record->sample = (int *) xmalloc (record->num_bins
* sizeof (record->sample[0]));
memset (record->sample, 0, record->num_bins * sizeof (record->sample[0]));
}
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,
+ (unsigned long) record->lowpc, (unsigned long) record->highpc,
record->num_bins));
-
+
for (i = 0; i < record->num_bins; ++i)
{
UNIT count;
record->sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
DBG (SAMPLEDEBUG,
printf ("[hist_read_rec] 0x%lx: %u\n",
- (unsigned long) (record->lowpc
- + i * (record->highpc - record->lowpc)
+ (unsigned long) (record->lowpc
+ + i * (record->highpc - record->lowpc)
/ record->num_bins),
record->sample[i]));
}
histogram *record = &histograms[r];
/* Write header. */
-
+
if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
|| gmon_io_write_vma (ofp, record->lowpc)
|| gmon_io_write_vma (ofp, record->highpc)
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);
next bin. */
static void
-scale_and_align_entries ()
+scale_and_align_entries (void)
{
Sym *sym;
bfd_vma bin_of_entry;
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;
bfd_vma lowpc = r->lowpc / sizeof (UNIT);
/* Iterate over all sample bins. */
- for (i = 0, j = 1; i < r->num_bins; ++i)
+ for (i = 0, k = 1; i < r->num_bins; ++i)
{
bin_count = r->sample[i];
if (! bin_count)
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 (
(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;
"[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;
- 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
/* Calls 'hist_assign_sampes_1' for all histogram records read so far. */
void
-hist_assign_samples ()
+hist_assign_samples (void)
{
unsigned i;
for (i = 0; i < num_histograms; ++i)
hist_assign_samples_1 (&histograms[i]);
-
+
}
/* Print header for flag histogram profile. */
/* Print the flat histogram profile. */
void
-hist_print ()
+hist_print (void)
{
Sym **time_sorted_syms, *top_dog, *sym;
- unsigned int index;
+ unsigned int sym_index;
unsigned log_scale;
- double top_time, time;
+ double top_time;
bfd_vma addr;
if (first_output)
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);
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)
{
- time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
+ double call_time;
+
+ call_time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
- if (time > top_time)
+ if (call_time > top_time)
{
top_dog = sym;
- top_time = time;
+ top_time = call_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;
}
}
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_line (time_sorted_syms[index], SItab[log_scale].scale);
+ print_line (time_sorted_syms[sym_index], SItab[log_scale].scale);
}
free (time_sorted_syms);
if (histograms[i].lowpc <= address && address < histograms[i].highpc)
return 1;
- return 0;
+ return 0;
}
#if ! defined(min)
if (histograms[i].lowpc <= pc && pc < histograms[i].highpc)
return &histograms[i];
}
- return 0;
+ return 0;
}