* alpha.c, basic_blocks.c, basic_blocks.h, bb_exit_func.c,
[deliverable/binutils-gdb.git] / gprof / hist.c
CommitLineData
ef368dac
NC
1/* hist.c - Histogram related operations.
2
1355568a 3 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
ef368dac
NC
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21\f
252b5132
RH
22#include "libiberty.h"
23#include "gprof.h"
6d9c411a
AM
24#include "search_list.h"
25#include "source.h"
26#include "symtab.h"
252b5132
RH
27#include "corefile.h"
28#include "gmon_io.h"
29#include "gmon_out.h"
30#include "hist.h"
252b5132
RH
31#include "sym_ids.h"
32#include "utils.h"
33
34#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
35
3e8f6abf
BE
36static void scale_and_align_entries (void);
37static void print_header (int);
38static void print_line (Sym *, double);
39static int cmp_time (const PTR, const PTR);
252b5132 40
ef368dac 41/* Declarations of automatically generated functions to output blurbs. */
3e8f6abf 42extern void flat_blurb (FILE * fp);
252b5132 43
ef368dac
NC
44bfd_vma s_lowpc; /* Lowest address in .text. */
45bfd_vma s_highpc = 0; /* Highest address in .text. */
46bfd_vma lowpc, highpc; /* Same, but expressed in UNITs. */
47int hist_num_bins = 0; /* Number of histogram samples. */
48int *hist_sample = 0; /* Histogram samples (shorts in the file!). */
252b5132 49double hist_scale;
0eee5820 50char hist_dimension[16] = "seconds";
252b5132
RH
51char hist_dimension_abbrev = 's';
52
0eee5820 53static double accum_time; /* Accumulated time so far for print_line(). */
ef368dac
NC
54static double total_time; /* Total time for all routines. */
55
56/* Table of SI prefixes for powers of 10 (used to automatically
57 scale some of the values in the flat profile). */
252b5132
RH
58const struct
59 {
60 char prefix;
61 double scale;
62 }
63SItab[] =
64{
0eee5820
AM
65 { 'T', 1e-12 }, /* tera */
66 { 'G', 1e-09 }, /* giga */
67 { 'M', 1e-06 }, /* mega */
68 { 'K', 1e-03 }, /* kilo */
69 { ' ', 1e-00 },
70 { 'm', 1e+03 }, /* milli */
71 { 'u', 1e+06 }, /* micro */
72 { 'n', 1e+09 }, /* nano */
73 { 'p', 1e+12 }, /* pico */
74 { 'f', 1e+15 }, /* femto */
75 { 'a', 1e+18 } /* ato */
252b5132
RH
76};
77
ef368dac
NC
78
79/* Read the histogram from file IFP. FILENAME is the name of IFP and
80 is provided for formatting error messages only. */
81
252b5132 82void
3e8f6abf 83hist_read_rec (FILE * ifp, const char *filename)
252b5132 84{
252b5132
RH
85 bfd_vma n_lowpc, n_highpc;
86 int i, ncnt, profrate;
87 UNIT count;
88
0eee5820
AM
89 if (gmon_io_read_vma (ifp, &n_lowpc)
90 || gmon_io_read_vma (ifp, &n_highpc)
91 || gmon_io_read_32 (ifp, &ncnt)
92 || gmon_io_read_32 (ifp, &profrate)
93 || gmon_io_read (ifp, hist_dimension, 15)
94 || gmon_io_read (ifp, &hist_dimension_abbrev, 1))
252b5132
RH
95 {
96 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
97 whoami, filename);
0eee5820 98
252b5132
RH
99 done (1);
100 }
101
252b5132
RH
102 if (!s_highpc)
103 {
ef368dac 104 /* This is the first histogram record. */
252b5132
RH
105 s_lowpc = n_lowpc;
106 s_highpc = n_highpc;
107 lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
108 highpc = (bfd_vma) n_highpc / sizeof (UNIT);
109 hist_num_bins = ncnt;
110 hz = profrate;
111 }
112
113 DBG (SAMPLEDEBUG,
114 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
fdcf7d43 115 (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
252b5132 116 printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
fdcf7d43
ILT
117 (unsigned long) s_lowpc, (unsigned long) s_highpc,
118 hist_num_bins);
252b5132 119 printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n",
fdcf7d43 120 (unsigned long) lowpc, (unsigned long) highpc));
252b5132
RH
121
122 if (n_lowpc != s_lowpc || n_highpc != s_highpc
123 || ncnt != hist_num_bins || hz != profrate)
124 {
125 fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
126 whoami, filename);
127 done (1);
128 }
129
130 if (!hist_sample)
131 {
132 hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
133 memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
134 }
135
136 for (i = 0; i < hist_num_bins; ++i)
137 {
138 if (fread (&count[0], sizeof (count), 1, ifp) != 1)
139 {
140 fprintf (stderr,
0eee5820 141 _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
252b5132
RH
142 whoami, filename, i, hist_num_bins);
143 done (1);
144 }
145 hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
0eee5820
AM
146 DBG (SAMPLEDEBUG,
147 printf ("[hist_read_rec] 0x%lx: %u\n",
148 (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt),
149 hist_sample[i]));
252b5132
RH
150 }
151}
152
153
ef368dac
NC
154/* Write execution histogram to file OFP. FILENAME is the name
155 of OFP and is provided for formatting error-messages only. */
156
252b5132 157void
3e8f6abf 158hist_write_hist (FILE * ofp, const char *filename)
252b5132 159{
252b5132
RH
160 UNIT count;
161 int i;
162
ef368dac 163 /* Write header. */
252b5132 164
0eee5820
AM
165 if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
166 || gmon_io_write_vma (ofp, s_lowpc)
167 || gmon_io_write_vma (ofp, s_highpc)
168 || gmon_io_write_32 (ofp, hist_num_bins)
169 || gmon_io_write_32 (ofp, hz)
170 || gmon_io_write (ofp, hist_dimension, 15)
171 || gmon_io_write (ofp, &hist_dimension_abbrev, 1))
252b5132
RH
172 {
173 perror (filename);
174 done (1);
175 }
176
177 for (i = 0; i < hist_num_bins; ++i)
178 {
1355568a 179 bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i], (bfd_byte *) &count[0]);
0eee5820 180
252b5132
RH
181 if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
182 {
183 perror (filename);
184 done (1);
185 }
186 }
187}
188
189
ef368dac
NC
190/* Calculate scaled entry point addresses (to save time in
191 hist_assign_samples), and, on architectures that have procedure
192 entry masks at the start of a function, possibly push the scaled
193 entry points over the procedure entry mask, if it turns out that
194 the entry point is in one bin and the code for a routine is in the
195 next bin. */
196
252b5132
RH
197static void
198scale_and_align_entries ()
199{
200 Sym *sym;
201 bfd_vma bin_of_entry;
202 bfd_vma bin_of_code;
203
204 for (sym = symtab.base; sym < symtab.limit; sym++)
205 {
206 sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
207 bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
0eee5820
AM
208 bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - lowpc)
209 / hist_scale);
252b5132
RH
210 if (bin_of_entry < bin_of_code)
211 {
212 DBG (SAMPLEDEBUG,
213 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
fdcf7d43
ILT
214 (unsigned long) sym->hist.scaled_addr,
215 (unsigned long) (sym->hist.scaled_addr
216 + UNITS_TO_CODE)));
252b5132
RH
217 sym->hist.scaled_addr += UNITS_TO_CODE;
218 }
219 }
220}
221
222
ef368dac 223/* Assign samples to the symbol to which they belong.
0eee5820 224
ef368dac
NC
225 Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
226 which may overlap one more symbol address ranges. If a symbol
227 overlaps with the bin's address range by O percent, then O percent
228 of the bin's count is credited to that symbol.
0eee5820 229
ef368dac
NC
230 There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
231 with respect to the symbol's address range [SYM_LOW_PC,
232 SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
233 the distance (in UNITs) between the arrows, the fraction of the
234 sample that is to be credited to the symbol which starts at
235 SYM_LOW_PC.
0eee5820
AM
236
237 sym_low_pc sym_high_pc
238 | |
239 v v
240
241 +-----------------------------------------------+
242 | |
243 | ->| |<- ->| |<- ->| |<- |
244 | | | | | |
245 +---------+ +---------+ +---------+
246
247 ^ ^ ^ ^ ^ ^
248 | | | | | |
ef368dac 249 bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
0eee5820 250
ef368dac
NC
251 For the VAX we assert that samples will never fall in the first two
252 bytes of any routine, since that is the entry mask, thus we call
253 scale_and_align_entries() to adjust the entry points if the entry
254 mask falls in one bin but the code for the routine doesn't start
255 until the next bin. In conjunction with the alignment of routine
256 addresses, this should allow us to have only one sample for every
257 four bytes of text space and never have any overlap (the two end
258 cases, above). */
259
252b5132 260void
1355568a 261hist_assign_samples ()
252b5132
RH
262{
263 bfd_vma bin_low_pc, bin_high_pc;
264 bfd_vma sym_low_pc, sym_high_pc;
265 bfd_vma overlap, addr;
266 int bin_count, i;
267 unsigned int j;
268 double time, credit;
269
ef368dac 270 /* Read samples and assign to symbols. */
252b5132
RH
271 hist_scale = highpc - lowpc;
272 hist_scale /= hist_num_bins;
273 scale_and_align_entries ();
274
ef368dac 275 /* Iterate over all sample bins. */
252b5132
RH
276 for (i = 0, j = 1; i < hist_num_bins; ++i)
277 {
278 bin_count = hist_sample[i];
ef368dac
NC
279 if (! bin_count)
280 continue;
281
252b5132
RH
282 bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
283 bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
284 time = bin_count;
0eee5820 285
252b5132
RH
286 DBG (SAMPLEDEBUG,
287 printf (
288 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
fdcf7d43
ILT
289 (unsigned long) (sizeof (UNIT) * bin_low_pc),
290 (unsigned long) (sizeof (UNIT) * bin_high_pc),
252b5132
RH
291 bin_count));
292 total_time += time;
293
ef368dac 294 /* Credit all symbols that are covered by bin I. */
252b5132
RH
295 for (j = j - 1; j < symtab.len; ++j)
296 {
297 sym_low_pc = symtab.base[j].hist.scaled_addr;
298 sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
0eee5820 299
ef368dac
NC
300 /* If high end of bin is below entry address,
301 go for next bin. */
252b5132 302 if (bin_high_pc < sym_low_pc)
ef368dac
NC
303 break;
304
305 /* If low end of bin is above high end of symbol,
306 go for next symbol. */
252b5132 307 if (bin_low_pc >= sym_high_pc)
ef368dac
NC
308 continue;
309
252b5132
RH
310 overlap =
311 MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
312 if (overlap > 0)
313 {
314 DBG (SAMPLEDEBUG,
315 printf (
0eee5820
AM
316 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
317 (unsigned long) symtab.base[j].addr,
318 (unsigned long) (sizeof (UNIT) * sym_high_pc),
319 symtab.base[j].name, overlap * time / hist_scale,
320 (long) overlap));
321
252b5132
RH
322 addr = symtab.base[j].addr;
323 credit = overlap * time / hist_scale;
0eee5820 324
ef368dac 325 /* Credit symbol if it appears in INCL_FLAT or that
0eee5820
AM
326 table is empty and it does not appear it in
327 EXCL_FLAT. */
252b5132
RH
328 if (sym_lookup (&syms[INCL_FLAT], addr)
329 || (syms[INCL_FLAT].len == 0
330 && !sym_lookup (&syms[EXCL_FLAT], addr)))
331 {
332 symtab.base[j].hist.time += credit;
333 }
334 else
335 {
336 total_time -= credit;
337 }
338 }
339 }
340 }
0eee5820 341
252b5132
RH
342 DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
343 total_time));
344}
345
346
ef368dac
NC
347/* Print header for flag histogram profile. */
348
252b5132 349static void
3e8f6abf 350print_header (int prefix)
252b5132
RH
351{
352 char unit[64];
353
354 sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
355
356 if (bsd_style_output)
357 {
358 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
359 (long) hist_scale * sizeof (UNIT));
360 if (total_time > 0.0)
361 {
362 printf (_(" for %.2f%% of %.2f %s\n\n"),
363 100.0 / total_time, total_time / hz, hist_dimension);
364 }
365 }
366 else
367 {
368 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
369 }
370
371 if (total_time <= 0.0)
372 {
373 printf (_(" no time accumulated\n\n"));
0eee5820 374
ef368dac 375 /* This doesn't hurt since all the numerators will be zero. */
252b5132
RH
376 total_time = 1.0;
377 }
378
379 printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
0eee5820
AM
380 "% ", _("cumulative"), _("self "), "", _("self "), _("total "),
381 "");
252b5132
RH
382 printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
383 _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
384 _("name"));
385}
386
387
388static void
3e8f6abf 389print_line (Sym *sym, double scale)
252b5132
RH
390{
391 if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
ef368dac 392 return;
252b5132
RH
393
394 accum_time += sym->hist.time;
0eee5820 395
252b5132 396 if (bsd_style_output)
ef368dac
NC
397 printf ("%5.1f %10.2f %8.2f",
398 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
399 accum_time / hz, sym->hist.time / hz);
252b5132 400 else
ef368dac
NC
401 printf ("%6.2f %9.2f %8.2f",
402 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
403 accum_time / hz, sym->hist.time / hz);
0eee5820 404
252b5132 405 if (sym->ncalls != 0)
ef368dac
NC
406 printf (" %8lu %8.2f %8.2f ",
407 sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
408 scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
252b5132 409 else
ef368dac 410 printf (" %8.8s %8.8s %8.8s ", "", "", "");
0eee5820 411
252b5132 412 if (bsd_style_output)
ef368dac 413 print_name (sym);
252b5132 414 else
ef368dac
NC
415 print_name_only (sym);
416
252b5132
RH
417 printf ("\n");
418}
419
420
ef368dac
NC
421/* Compare LP and RP. The primary comparison key is execution time,
422 the secondary is number of invocation, and the tertiary is the
423 lexicographic order of the function names. */
424
252b5132 425static int
3e8f6abf 426cmp_time (const PTR lp, const PTR rp)
252b5132
RH
427{
428 const Sym *left = *(const Sym **) lp;
429 const Sym *right = *(const Sym **) rp;
430 double time_diff;
431
432 time_diff = right->hist.time - left->hist.time;
0eee5820 433
252b5132 434 if (time_diff > 0.0)
ef368dac 435 return 1;
0eee5820 436
252b5132 437 if (time_diff < 0.0)
ef368dac 438 return -1;
252b5132
RH
439
440 if (right->ncalls > left->ncalls)
ef368dac
NC
441 return 1;
442
252b5132 443 if (right->ncalls < left->ncalls)
ef368dac 444 return -1;
252b5132
RH
445
446 return strcmp (left->name, right->name);
447}
448
449
ef368dac
NC
450/* Print the flat histogram profile. */
451
252b5132 452void
1355568a 453hist_print ()
252b5132
RH
454{
455 Sym **time_sorted_syms, *top_dog, *sym;
456 unsigned int index;
be5523fb 457 unsigned log_scale;
252b5132
RH
458 double top_time, time;
459 bfd_vma addr;
460
461 if (first_output)
b34976b6 462 first_output = FALSE;
252b5132 463 else
ef368dac 464 printf ("\f\n");
252b5132
RH
465
466 accum_time = 0.0;
0eee5820 467
252b5132
RH
468 if (bsd_style_output)
469 {
470 if (print_descriptions)
471 {
472 printf (_("\n\n\nflat profile:\n"));
473 flat_blurb (stdout);
474 }
475 }
476 else
477 {
478 printf (_("Flat profile:\n"));
479 }
0eee5820 480
ef368dac
NC
481 /* Sort the symbol table by time (call-count and name as secondary
482 and tertiary keys). */
252b5132 483 time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
0eee5820 484
252b5132 485 for (index = 0; index < symtab.len; ++index)
ef368dac
NC
486 time_sorted_syms[index] = &symtab.base[index];
487
252b5132
RH
488 qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
489
490 if (bsd_style_output)
491 {
ef368dac 492 log_scale = 5; /* Milli-seconds is BSD-default. */
252b5132
RH
493 }
494 else
495 {
ef368dac
NC
496 /* Search for symbol with highest per-call
497 execution time and scale accordingly. */
252b5132
RH
498 log_scale = 0;
499 top_dog = 0;
500 top_time = 0.0;
0eee5820 501
252b5132
RH
502 for (index = 0; index < symtab.len; ++index)
503 {
504 sym = time_sorted_syms[index];
0eee5820 505
252b5132
RH
506 if (sym->ncalls != 0)
507 {
508 time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
0eee5820 509
252b5132
RH
510 if (time > top_time)
511 {
512 top_dog = sym;
513 top_time = time;
514 }
515 }
516 }
0eee5820 517
252b5132
RH
518 if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
519 {
520 top_time /= hz;
0eee5820 521
be5523fb 522 for (log_scale = 0; log_scale < ARRAY_SIZE (SItab); log_scale ++)
252b5132 523 {
be5523fb
FCE
524 double scaled_value = SItab[log_scale].scale * top_time;
525
526 if (scaled_value >= 1.0 && scaled_value < 1000.0)
527 break;
252b5132
RH
528 }
529 }
530 }
531
ef368dac
NC
532 /* For now, the dimension is always seconds. In the future, we
533 may also want to support other (pseudo-)dimensions (such as
534 I-cache misses etc.). */
252b5132 535 print_header (SItab[log_scale].prefix);
0eee5820 536
252b5132
RH
537 for (index = 0; index < symtab.len; ++index)
538 {
539 addr = time_sorted_syms[index]->addr;
0eee5820 540
ef368dac 541 /* Print symbol if its in INCL_FLAT table or that table
0eee5820 542 is empty and the symbol is not in EXCL_FLAT. */
252b5132
RH
543 if (sym_lookup (&syms[INCL_FLAT], addr)
544 || (syms[INCL_FLAT].len == 0
545 && !sym_lookup (&syms[EXCL_FLAT], addr)))
ef368dac 546 print_line (time_sorted_syms[index], SItab[log_scale].scale);
252b5132 547 }
0eee5820 548
252b5132
RH
549 free (time_sorted_syms);
550
551 if (print_descriptions && !bsd_style_output)
ef368dac 552 flat_blurb (stdout);
252b5132 553}
This page took 0.225298 seconds and 4 git commands to generate.