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