2010-03-16 Segher Boessenkool <segher@kernel.crashing.org>
[deliverable/binutils-gdb.git] / gprof / hist.c
CommitLineData
ef368dac
NC
1/* hist.c - Histogram related operations.
2
c34f4fc6 3 Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2009
d6a39701 4 Free Software Foundation, Inc.
ef368dac
NC
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
651dbc76 10 the Free Software Foundation; either version 3 of the License, or
ef368dac
NC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
44eb1801
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
ef368dac 22\f
252b5132 23#include "gprof.h"
ecba005f 24#include "libiberty.h"
6d9c411a
AM
25#include "search_list.h"
26#include "source.h"
27#include "symtab.h"
252b5132
RH
28#include "corefile.h"
29#include "gmon_io.h"
30#include "gmon_out.h"
31#include "hist.h"
252b5132
RH
32#include "sym_ids.h"
33#include "utils.h"
b3296dc5
VP
34#include "math.h"
35#include "stdio.h"
36#include "stdlib.h"
252b5132
RH
37
38#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
39
3e8f6abf
BE
40static void scale_and_align_entries (void);
41static void print_header (int);
42static void print_line (Sym *, double);
43static int cmp_time (const PTR, const PTR);
252b5132 44
ef368dac 45/* Declarations of automatically generated functions to output blurbs. */
3e8f6abf 46extern void flat_blurb (FILE * fp);
252b5132 47
b3296dc5
VP
48static histogram *find_histogram (bfd_vma lowpc, bfd_vma highpc);
49static histogram *find_histogram_for_pc (bfd_vma pc);
50
c34f4fc6
NC
51histogram * histograms;
52unsigned num_histograms;
252b5132 53double hist_scale;
9e972ca0
BE
54static char hist_dimension[16] = "seconds";
55static char hist_dimension_abbrev = 's';
252b5132 56
0eee5820 57static double accum_time; /* Accumulated time so far for print_line(). */
ef368dac
NC
58static double total_time; /* Total time for all routines. */
59
60/* Table of SI prefixes for powers of 10 (used to automatically
61 scale some of the values in the flat profile). */
252b5132
RH
62const struct
63 {
64 char prefix;
65 double scale;
66 }
67SItab[] =
68{
0eee5820
AM
69 { 'T', 1e-12 }, /* tera */
70 { 'G', 1e-09 }, /* giga */
71 { 'M', 1e-06 }, /* mega */
72 { 'K', 1e-03 }, /* kilo */
73 { ' ', 1e-00 },
74 { 'm', 1e+03 }, /* milli */
75 { 'u', 1e+06 }, /* micro */
76 { 'n', 1e+09 }, /* nano */
77 { 'p', 1e+12 }, /* pico */
78 { 'f', 1e+15 }, /* femto */
79 { 'a', 1e+18 } /* ato */
252b5132
RH
80};
81
b3296dc5
VP
82/* Reads just the header part of histogram record into
83 *RECORD from IFP. FILENAME is the name of IFP and
84 is provided for formatting error messages only.
ef368dac 85
b3296dc5
VP
86 If FIRST is non-zero, sets global variables HZ, HIST_DIMENSION,
87 HIST_DIMENSION_ABBREV, HIST_SCALE. If FIRST is zero, checks
88 that the new histogram is compatible with already-set values
89 of those variables and emits an error if that's not so. */
90static void
91read_histogram_header (histogram *record,
92 FILE *ifp, const char *filename,
93 int first)
252b5132 94{
b3296dc5
VP
95 unsigned int profrate;
96 char n_hist_dimension[15];
97 char n_hist_dimension_abbrev;
98 double n_hist_scale;
99
100 if (gmon_io_read_vma (ifp, &record->lowpc)
101 || gmon_io_read_vma (ifp, &record->highpc)
102 || gmon_io_read_32 (ifp, &record->num_bins)
0eee5820 103 || gmon_io_read_32 (ifp, &profrate)
b3296dc5
VP
104 || gmon_io_read (ifp, n_hist_dimension, 15)
105 || gmon_io_read (ifp, &n_hist_dimension_abbrev, 1))
252b5132
RH
106 {
107 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
108 whoami, filename);
0eee5820 109
252b5132
RH
110 done (1);
111 }
112
b3296dc5
VP
113 n_hist_scale = (double)((record->highpc - record->lowpc) / sizeof (UNIT))
114 / record->num_bins;
115
116 if (first)
252b5132 117 {
b3296dc5
VP
118 /* We don't try to veryfy profrate is the same for all histogram
119 records. If we have two histogram records for the same
120 address range and profiling samples is done as often
121 as possible as opposed on timer, then the actual profrate will
122 be slightly different. Most of the time the difference does not
123 matter and insisting that profiling rate is exactly the same
124 will only create inconvenient. */
252b5132 125 hz = profrate;
b3296dc5
VP
126 memcpy (hist_dimension, n_hist_dimension, 15);
127 hist_dimension_abbrev = n_hist_dimension_abbrev;
128 hist_scale = n_hist_scale;
252b5132 129 }
b3296dc5 130 else
252b5132 131 {
b3296dc5
VP
132 if (strncmp (n_hist_dimension, hist_dimension, 15) != 0)
133 {
134 fprintf (stderr,
135 _("%s: dimension unit changed between histogram records\n"
136 "%s: from '%s'\n"
137 "%s: to '%s'\n"),
138 whoami, whoami, hist_dimension, whoami, n_hist_dimension);
139 done (1);
140 }
141
142 if (n_hist_dimension_abbrev != hist_dimension_abbrev)
143 {
144 fprintf (stderr,
145 _("%s: dimension abbreviation changed between histogram records\n"
146 "%s: from '%c'\n"
147 "%s: to '%c'\n"),
148 whoami, whoami, hist_dimension_abbrev, whoami, n_hist_dimension_abbrev);
149 done (1);
150 }
151
152 /* The only reason we require the same scale for histograms is that
153 there's code (notably printing code), that prints units,
154 and it would be very confusing to have one unit mean different
155 things for different functions. */
156 if (fabs (hist_scale - n_hist_scale) > 0.000001)
157 {
158 fprintf (stderr,
159 _("%s: different scales in histogram records"),
160 whoami);
161 done (1);
162 }
252b5132 163 }
b3296dc5 164}
252b5132 165
b3296dc5
VP
166/* Read the histogram from file IFP. FILENAME is the name of IFP and
167 is provided for formatting error messages only. */
168
169void
170hist_read_rec (FILE * ifp, const char *filename)
171{
172 bfd_vma lowpc, highpc;
173 histogram n_record;
174 histogram *record, *existing_record;
175 unsigned i;
176
177 /* 1. Read the header and see if there's existing record for the
178 same address range and that there are no overlapping records. */
179 read_histogram_header (&n_record, ifp, filename, num_histograms == 0);
180
181 existing_record = find_histogram (n_record.lowpc, n_record.highpc);
182 if (existing_record)
252b5132 183 {
b3296dc5
VP
184 record = existing_record;
185 }
186 else
187 {
188 /* If this record overlaps, but does not completely match an existing
189 record, it's an error. */
190 lowpc = n_record.lowpc;
191 highpc = n_record.highpc;
192 hist_clip_symbol_address (&lowpc, &highpc);
193 if (lowpc != highpc)
194 {
195 fprintf (stderr,
196 _("%s: overlapping histogram records\n"),
197 whoami);
198 done (1);
199 }
200
201 /* This is new record. Add it to global array and allocate space for
202 the samples. */
1e9cc1c2
NC
203 histograms = (struct histogram *)
204 xrealloc (histograms, sizeof (histogram) * (num_histograms + 1));
b3296dc5
VP
205 memcpy (histograms + num_histograms,
206 &n_record, sizeof (histogram));
207 record = &histograms[num_histograms];
208 ++num_histograms;
209
210 record->sample = (int *) xmalloc (record->num_bins
211 * sizeof (record->sample[0]));
212 memset (record->sample, 0, record->num_bins * sizeof (record->sample[0]));
252b5132
RH
213 }
214
b3296dc5
VP
215 /* 2. We have either a new record (with zeroed histogram data), or an existing
216 record with some data in the histogram already. Read new data into the
217 record, adding hit counts. */
218
219 DBG (SAMPLEDEBUG,
220 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %u\n",
221 (unsigned long) record->lowpc, (unsigned long) record->highpc,
222 record->num_bins));
223
224 for (i = 0; i < record->num_bins; ++i)
252b5132 225 {
b3296dc5 226 UNIT count;
252b5132
RH
227 if (fread (&count[0], sizeof (count), 1, ifp) != 1)
228 {
229 fprintf (stderr,
8c62e9e1 230 _("%s: %s: unexpected EOF after reading %u of %u samples\n"),
b3296dc5 231 whoami, filename, i, record->num_bins);
252b5132
RH
232 done (1);
233 }
b3296dc5 234 record->sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
0eee5820
AM
235 DBG (SAMPLEDEBUG,
236 printf ("[hist_read_rec] 0x%lx: %u\n",
b3296dc5
VP
237 (unsigned long) (record->lowpc
238 + i * (record->highpc - record->lowpc)
239 / record->num_bins),
240 record->sample[i]));
252b5132
RH
241 }
242}
243
244
b3296dc5 245/* Write all execution histograms file OFP. FILENAME is the name
ef368dac
NC
246 of OFP and is provided for formatting error-messages only. */
247
252b5132 248void
3e8f6abf 249hist_write_hist (FILE * ofp, const char *filename)
252b5132 250{
252b5132 251 UNIT count;
b3296dc5 252 unsigned int i, r;
252b5132 253
b3296dc5 254 for (r = 0; r < num_histograms; ++r)
252b5132 255 {
b3296dc5
VP
256 histogram *record = &histograms[r];
257
258 /* Write header. */
259
260 if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
261 || gmon_io_write_vma (ofp, record->lowpc)
262 || gmon_io_write_vma (ofp, record->highpc)
263 || gmon_io_write_32 (ofp, record->num_bins)
264 || gmon_io_write_32 (ofp, hz)
265 || gmon_io_write (ofp, hist_dimension, 15)
266 || gmon_io_write (ofp, &hist_dimension_abbrev, 1))
252b5132
RH
267 {
268 perror (filename);
269 done (1);
270 }
b3296dc5
VP
271
272 for (i = 0; i < record->num_bins; ++i)
273 {
274 bfd_put_16 (core_bfd, (bfd_vma) record->sample[i], (bfd_byte *) &count[0]);
275
276 if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
277 {
278 perror (filename);
279 done (1);
280 }
281 }
252b5132
RH
282 }
283}
284
ef368dac
NC
285/* Calculate scaled entry point addresses (to save time in
286 hist_assign_samples), and, on architectures that have procedure
287 entry masks at the start of a function, possibly push the scaled
288 entry points over the procedure entry mask, if it turns out that
289 the entry point is in one bin and the code for a routine is in the
290 next bin. */
291
252b5132
RH
292static void
293scale_and_align_entries ()
294{
295 Sym *sym;
296 bfd_vma bin_of_entry;
297 bfd_vma bin_of_code;
298
299 for (sym = symtab.base; sym < symtab.limit; sym++)
300 {
b3296dc5
VP
301 histogram *r = find_histogram_for_pc (sym->addr);
302
74bad5d4
L
303 sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
304
b3296dc5 305 if (r)
252b5132 306 {
b3296dc5
VP
307 bin_of_entry = (sym->hist.scaled_addr - r->lowpc) / hist_scale;
308 bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - r->lowpc)
309 / hist_scale);
310 if (bin_of_entry < bin_of_code)
311 {
312 DBG (SAMPLEDEBUG,
313 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
314 (unsigned long) sym->hist.scaled_addr,
315 (unsigned long) (sym->hist.scaled_addr
316 + UNITS_TO_CODE)));
317 sym->hist.scaled_addr += UNITS_TO_CODE;
318 }
252b5132
RH
319 }
320 }
321}
322
323
ef368dac 324/* Assign samples to the symbol to which they belong.
0eee5820 325
ef368dac
NC
326 Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
327 which may overlap one more symbol address ranges. If a symbol
328 overlaps with the bin's address range by O percent, then O percent
329 of the bin's count is credited to that symbol.
0eee5820 330
ef368dac
NC
331 There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
332 with respect to the symbol's address range [SYM_LOW_PC,
333 SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
334 the distance (in UNITs) between the arrows, the fraction of the
335 sample that is to be credited to the symbol which starts at
336 SYM_LOW_PC.
0eee5820
AM
337
338 sym_low_pc sym_high_pc
339 | |
340 v v
341
342 +-----------------------------------------------+
343 | |
344 | ->| |<- ->| |<- ->| |<- |
345 | | | | | |
346 +---------+ +---------+ +---------+
347
348 ^ ^ ^ ^ ^ ^
349 | | | | | |
ef368dac 350 bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
0eee5820 351
ef368dac
NC
352 For the VAX we assert that samples will never fall in the first two
353 bytes of any routine, since that is the entry mask, thus we call
354 scale_and_align_entries() to adjust the entry points if the entry
355 mask falls in one bin but the code for the routine doesn't start
356 until the next bin. In conjunction with the alignment of routine
357 addresses, this should allow us to have only one sample for every
358 four bytes of text space and never have any overlap (the two end
359 cases, above). */
360
b3296dc5
VP
361static void
362hist_assign_samples_1 (histogram *r)
252b5132
RH
363{
364 bfd_vma bin_low_pc, bin_high_pc;
365 bfd_vma sym_low_pc, sym_high_pc;
366 bfd_vma overlap, addr;
8c62e9e1
AM
367 unsigned int bin_count;
368 unsigned int i, j;
91d6fa6a 369 double count_time, credit;
252b5132 370
b3296dc5 371 bfd_vma lowpc = r->lowpc / sizeof (UNIT);
252b5132 372
ef368dac 373 /* Iterate over all sample bins. */
b3296dc5 374 for (i = 0, j = 1; i < r->num_bins; ++i)
252b5132 375 {
b3296dc5 376 bin_count = r->sample[i];
ef368dac
NC
377 if (! bin_count)
378 continue;
379
252b5132
RH
380 bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
381 bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
91d6fa6a 382 count_time = bin_count;
0eee5820 383
252b5132
RH
384 DBG (SAMPLEDEBUG,
385 printf (
8c62e9e1 386 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%u\n",
fdcf7d43
ILT
387 (unsigned long) (sizeof (UNIT) * bin_low_pc),
388 (unsigned long) (sizeof (UNIT) * bin_high_pc),
252b5132 389 bin_count));
91d6fa6a 390 total_time += count_time;
252b5132 391
ef368dac 392 /* Credit all symbols that are covered by bin I. */
252b5132
RH
393 for (j = j - 1; j < symtab.len; ++j)
394 {
395 sym_low_pc = symtab.base[j].hist.scaled_addr;
396 sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
0eee5820 397
ef368dac
NC
398 /* If high end of bin is below entry address,
399 go for next bin. */
252b5132 400 if (bin_high_pc < sym_low_pc)
ef368dac
NC
401 break;
402
403 /* If low end of bin is above high end of symbol,
404 go for next symbol. */
252b5132 405 if (bin_low_pc >= sym_high_pc)
ef368dac
NC
406 continue;
407
252b5132
RH
408 overlap =
409 MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
410 if (overlap > 0)
411 {
412 DBG (SAMPLEDEBUG,
413 printf (
0eee5820
AM
414 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
415 (unsigned long) symtab.base[j].addr,
416 (unsigned long) (sizeof (UNIT) * sym_high_pc),
91d6fa6a 417 symtab.base[j].name, overlap * count_time / hist_scale,
0eee5820
AM
418 (long) overlap));
419
252b5132 420 addr = symtab.base[j].addr;
91d6fa6a 421 credit = overlap * count_time / hist_scale;
0eee5820 422
ef368dac 423 /* Credit symbol if it appears in INCL_FLAT or that
0eee5820
AM
424 table is empty and it does not appear it in
425 EXCL_FLAT. */
252b5132
RH
426 if (sym_lookup (&syms[INCL_FLAT], addr)
427 || (syms[INCL_FLAT].len == 0
428 && !sym_lookup (&syms[EXCL_FLAT], addr)))
429 {
430 symtab.base[j].hist.time += credit;
431 }
432 else
433 {
434 total_time -= credit;
435 }
436 }
437 }
438 }
0eee5820 439
252b5132
RH
440 DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
441 total_time));
442}
443
b3296dc5
VP
444/* Calls 'hist_assign_sampes_1' for all histogram records read so far. */
445void
446hist_assign_samples ()
447{
448 unsigned i;
449
450 scale_and_align_entries ();
451
452 for (i = 0; i < num_histograms; ++i)
453 hist_assign_samples_1 (&histograms[i]);
454
455}
252b5132 456
ef368dac
NC
457/* Print header for flag histogram profile. */
458
252b5132 459static void
3e8f6abf 460print_header (int prefix)
252b5132
RH
461{
462 char unit[64];
463
464 sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
465
466 if (bsd_style_output)
467 {
468 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
d2df793a 469 (long) hist_scale * (long) sizeof (UNIT));
252b5132
RH
470 if (total_time > 0.0)
471 {
472 printf (_(" for %.2f%% of %.2f %s\n\n"),
473 100.0 / total_time, total_time / hz, hist_dimension);
474 }
475 }
476 else
477 {
478 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
479 }
480
481 if (total_time <= 0.0)
482 {
483 printf (_(" no time accumulated\n\n"));
0eee5820 484
ef368dac 485 /* This doesn't hurt since all the numerators will be zero. */
252b5132
RH
486 total_time = 1.0;
487 }
488
489 printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
0eee5820
AM
490 "% ", _("cumulative"), _("self "), "", _("self "), _("total "),
491 "");
252b5132
RH
492 printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
493 _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
494 _("name"));
495}
496
497
498static void
3e8f6abf 499print_line (Sym *sym, double scale)
252b5132
RH
500{
501 if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
ef368dac 502 return;
252b5132
RH
503
504 accum_time += sym->hist.time;
0eee5820 505
252b5132 506 if (bsd_style_output)
ef368dac
NC
507 printf ("%5.1f %10.2f %8.2f",
508 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
509 accum_time / hz, sym->hist.time / hz);
252b5132 510 else
ef368dac
NC
511 printf ("%6.2f %9.2f %8.2f",
512 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
513 accum_time / hz, sym->hist.time / hz);
0eee5820 514
252b5132 515 if (sym->ncalls != 0)
ef368dac
NC
516 printf (" %8lu %8.2f %8.2f ",
517 sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
518 scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
252b5132 519 else
ef368dac 520 printf (" %8.8s %8.8s %8.8s ", "", "", "");
0eee5820 521
252b5132 522 if (bsd_style_output)
ef368dac 523 print_name (sym);
252b5132 524 else
ef368dac
NC
525 print_name_only (sym);
526
252b5132
RH
527 printf ("\n");
528}
529
530
ef368dac
NC
531/* Compare LP and RP. The primary comparison key is execution time,
532 the secondary is number of invocation, and the tertiary is the
533 lexicographic order of the function names. */
534
252b5132 535static int
3e8f6abf 536cmp_time (const PTR lp, const PTR rp)
252b5132
RH
537{
538 const Sym *left = *(const Sym **) lp;
539 const Sym *right = *(const Sym **) rp;
540 double time_diff;
541
542 time_diff = right->hist.time - left->hist.time;
0eee5820 543
252b5132 544 if (time_diff > 0.0)
ef368dac 545 return 1;
0eee5820 546
252b5132 547 if (time_diff < 0.0)
ef368dac 548 return -1;
252b5132
RH
549
550 if (right->ncalls > left->ncalls)
ef368dac
NC
551 return 1;
552
252b5132 553 if (right->ncalls < left->ncalls)
ef368dac 554 return -1;
252b5132
RH
555
556 return strcmp (left->name, right->name);
557}
558
559
ef368dac
NC
560/* Print the flat histogram profile. */
561
252b5132 562void
1355568a 563hist_print ()
252b5132
RH
564{
565 Sym **time_sorted_syms, *top_dog, *sym;
91d6fa6a 566 unsigned int sym_index;
be5523fb 567 unsigned log_scale;
91d6fa6a 568 double top_time;
252b5132
RH
569 bfd_vma addr;
570
571 if (first_output)
b34976b6 572 first_output = FALSE;
252b5132 573 else
ef368dac 574 printf ("\f\n");
252b5132
RH
575
576 accum_time = 0.0;
0eee5820 577
252b5132
RH
578 if (bsd_style_output)
579 {
580 if (print_descriptions)
581 {
582 printf (_("\n\n\nflat profile:\n"));
583 flat_blurb (stdout);
584 }
585 }
586 else
587 {
588 printf (_("Flat profile:\n"));
589 }
0eee5820 590
ef368dac
NC
591 /* Sort the symbol table by time (call-count and name as secondary
592 and tertiary keys). */
252b5132 593 time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
0eee5820 594
91d6fa6a
NC
595 for (sym_index = 0; sym_index < symtab.len; ++sym_index)
596 time_sorted_syms[sym_index] = &symtab.base[sym_index];
ef368dac 597
252b5132
RH
598 qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
599
600 if (bsd_style_output)
601 {
ef368dac 602 log_scale = 5; /* Milli-seconds is BSD-default. */
252b5132
RH
603 }
604 else
605 {
ef368dac
NC
606 /* Search for symbol with highest per-call
607 execution time and scale accordingly. */
252b5132
RH
608 log_scale = 0;
609 top_dog = 0;
610 top_time = 0.0;
0eee5820 611
91d6fa6a 612 for (sym_index = 0; sym_index < symtab.len; ++sym_index)
252b5132 613 {
91d6fa6a 614 sym = time_sorted_syms[sym_index];
0eee5820 615
252b5132
RH
616 if (sym->ncalls != 0)
617 {
91d6fa6a 618 double call_time;
0eee5820 619
91d6fa6a
NC
620 call_time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
621
622 if (call_time > top_time)
252b5132
RH
623 {
624 top_dog = sym;
91d6fa6a 625 top_time = call_time;
252b5132
RH
626 }
627 }
628 }
0eee5820 629
252b5132
RH
630 if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
631 {
632 top_time /= hz;
0eee5820 633
be5523fb 634 for (log_scale = 0; log_scale < ARRAY_SIZE (SItab); log_scale ++)
252b5132 635 {
be5523fb
FCE
636 double scaled_value = SItab[log_scale].scale * top_time;
637
638 if (scaled_value >= 1.0 && scaled_value < 1000.0)
639 break;
252b5132
RH
640 }
641 }
642 }
643
ef368dac
NC
644 /* For now, the dimension is always seconds. In the future, we
645 may also want to support other (pseudo-)dimensions (such as
646 I-cache misses etc.). */
252b5132 647 print_header (SItab[log_scale].prefix);
0eee5820 648
91d6fa6a 649 for (sym_index = 0; sym_index < symtab.len; ++sym_index)
252b5132 650 {
91d6fa6a 651 addr = time_sorted_syms[sym_index]->addr;
0eee5820 652
ef368dac 653 /* Print symbol if its in INCL_FLAT table or that table
0eee5820 654 is empty and the symbol is not in EXCL_FLAT. */
252b5132
RH
655 if (sym_lookup (&syms[INCL_FLAT], addr)
656 || (syms[INCL_FLAT].len == 0
657 && !sym_lookup (&syms[EXCL_FLAT], addr)))
91d6fa6a 658 print_line (time_sorted_syms[sym_index], SItab[log_scale].scale);
252b5132 659 }
0eee5820 660
252b5132
RH
661 free (time_sorted_syms);
662
663 if (print_descriptions && !bsd_style_output)
ef368dac 664 flat_blurb (stdout);
252b5132 665}
b3296dc5
VP
666
667int
668hist_check_address (unsigned address)
669{
670 unsigned i;
671
672 for (i = 0; i < num_histograms; ++i)
673 if (histograms[i].lowpc <= address && address < histograms[i].highpc)
674 return 1;
675
676 return 0;
677}
678
679#if ! defined(min)
680#define min(a,b) (((a)<(b)) ? (a) : (b))
681#endif
682#if ! defined(max)
683#define max(a,b) (((a)>(b)) ? (a) : (b))
684#endif
685
686void
687hist_clip_symbol_address (bfd_vma *p_lowpc, bfd_vma *p_highpc)
688{
689 unsigned i;
690 int found = 0;
691
692 if (num_histograms == 0)
693 {
694 *p_highpc = *p_lowpc;
695 return;
696 }
697
698 for (i = 0; i < num_histograms; ++i)
699 {
700 bfd_vma common_low, common_high;
701 common_low = max (histograms[i].lowpc, *p_lowpc);
702 common_high = min (histograms[i].highpc, *p_highpc);
703
704 if (common_low < common_high)
705 {
706 if (found)
707 {
708 fprintf (stderr,
709 _("%s: found a symbol that covers "
e701ca86 710 "several histogram records"),
b3296dc5
VP
711 whoami);
712 done (1);
713 }
714
715 found = 1;
716 *p_lowpc = common_low;
717 *p_highpc = common_high;
718 }
719 }
720
721 if (!found)
722 *p_highpc = *p_lowpc;
723}
724
725/* Find and return exising histogram record having the same lowpc and
726 highpc as passed via the parameters. Return NULL if nothing is found.
727 The return value is valid until any new histogram is read. */
728static histogram *
729find_histogram (bfd_vma lowpc, bfd_vma highpc)
730{
731 unsigned i;
732 for (i = 0; i < num_histograms; ++i)
733 {
734 if (histograms[i].lowpc == lowpc && histograms[i].highpc == highpc)
735 return &histograms[i];
736 }
737 return 0;
738}
739
740/* Given a PC, return histogram record which address range include this PC.
741 Return NULL if there's no such record. */
742static histogram *
743find_histogram_for_pc (bfd_vma pc)
744{
745 unsigned i;
746 for (i = 0; i < num_histograms; ++i)
747 {
748 if (histograms[i].lowpc <= pc && pc < histograms[i].highpc)
749 return &histograms[i];
750 }
751 return 0;
752}
This page took 0.540021 seconds and 4 git commands to generate.