PR gprof/13325
[external/binutils.git] / gprof / hist.c
1 /* hist.c  -  Histogram related operations.
2
3    Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2009
4    Free Software Foundation, Inc.
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
10    the Free Software Foundation; either version 3 of the License, or
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
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22 \f
23 #include "gprof.h"
24 #include "libiberty.h"
25 #include "search_list.h"
26 #include "source.h"
27 #include "symtab.h"
28 #include "corefile.h"
29 #include "gmon_io.h"
30 #include "gmon_out.h"
31 #include "hist.h"
32 #include "sym_ids.h"
33 #include "utils.h"
34 #include "math.h"
35 #include "stdio.h"
36 #include "stdlib.h"
37
38 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
39
40 static void scale_and_align_entries (void);
41 static void print_header (int);
42 static void print_line (Sym *, double);
43 static int cmp_time (const PTR, const PTR);
44
45 /* Declarations of automatically generated functions to output blurbs.  */
46 extern void flat_blurb (FILE * fp);
47
48 static histogram *find_histogram (bfd_vma lowpc, bfd_vma highpc);
49 static histogram *find_histogram_for_pc (bfd_vma pc);
50
51 histogram * histograms;
52 unsigned num_histograms;
53 double hist_scale;
54 static char hist_dimension[16] = "seconds";
55 static char hist_dimension_abbrev = 's';
56
57 static double accum_time;       /* Accumulated time so far for print_line(). */
58 static 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).  */
62 const struct
63   {
64     char prefix;
65     double scale;
66   }
67 SItab[] =
68 {
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 */
80 };
81
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.  
85
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.  */
90 static void
91 read_histogram_header (histogram *record, 
92                        FILE *ifp, const char *filename,
93                        int first)
94 {
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)
103       || gmon_io_read_32 (ifp, &profrate)
104       || gmon_io_read (ifp, n_hist_dimension, 15)
105       || gmon_io_read (ifp, &n_hist_dimension_abbrev, 1))
106     {
107       fprintf (stderr, _("%s: %s: unexpected end of file\n"),
108                whoami, filename);
109
110       done (1);
111     }
112
113   n_hist_scale = (double)((record->highpc - record->lowpc) / sizeof (UNIT)) 
114     / record->num_bins;
115
116   if (first)
117     {
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.  */
125       hz = profrate;
126       memcpy (hist_dimension, n_hist_dimension, 15);
127       hist_dimension_abbrev = n_hist_dimension_abbrev;
128       hist_scale = n_hist_scale;      
129     }
130   else
131     {
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         }
163     }
164 }
165
166 /* Read the histogram from file IFP.  FILENAME is the name of IFP and
167    is provided for formatting error messages only.  */
168
169 void
170 hist_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)
183     {
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.  */
203       histograms = (struct histogram *)
204           xrealloc (histograms, sizeof (histogram) * (num_histograms + 1));
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]));
213     }
214
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)
225     {
226       UNIT count;
227       if (fread (&count[0], sizeof (count), 1, ifp) != 1)
228         {
229           fprintf (stderr,
230                   _("%s: %s: unexpected EOF after reading %u of %u samples\n"),
231                    whoami, filename, i, record->num_bins);
232           done (1);
233         }
234       record->sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
235       DBG (SAMPLEDEBUG,
236            printf ("[hist_read_rec] 0x%lx: %u\n",
237                    (unsigned long) (record->lowpc 
238                                     + i * (record->highpc - record->lowpc) 
239                                     / record->num_bins),
240                    record->sample[i]));
241     }
242 }
243
244
245 /* Write all execution histograms file OFP.  FILENAME is the name
246    of OFP and is provided for formatting error-messages only.  */
247
248 void
249 hist_write_hist (FILE * ofp, const char *filename)
250 {
251   UNIT count;
252   unsigned int i, r;
253
254   for (r = 0; r < num_histograms; ++r)
255     {
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))
267         {
268           perror (filename);
269           done (1);
270         }
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         }
282     }
283 }
284
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
292 static void
293 scale_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     {
301       histogram *r = find_histogram_for_pc (sym->addr);
302
303       sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
304
305       if (r)
306         {
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             }
319         }
320     }
321 }
322
323
324 /* Assign samples to the symbol to which they belong.
325
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.
330
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.
337
338           sym_low_pc                                      sym_high_pc
339                |                                               |
340                v                                               v
341
342                +-----------------------------------------------+
343                |                                               |
344           |  ->|    |<-         ->|         |<-         ->|    |<-  |
345           |         |             |         |             |         |
346           +---------+             +---------+             +---------+
347
348           ^         ^             ^         ^             ^         ^
349           |         |             |         |             |         |
350      bin_low_pc bin_high_pc  bin_low_pc bin_high_pc  bin_low_pc bin_high_pc
351
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
361 static void
362 hist_assign_samples_1 (histogram *r)
363 {
364   bfd_vma bin_low_pc, bin_high_pc;
365   bfd_vma sym_low_pc, sym_high_pc;
366   bfd_vma overlap, addr;
367   unsigned int bin_count;
368   unsigned int i, j;
369   double count_time, credit;
370
371   bfd_vma lowpc = r->lowpc / sizeof (UNIT);
372
373   /* Iterate over all sample bins.  */
374   for (i = 0, j = 1; i < r->num_bins; ++i)
375     {
376       bin_count = r->sample[i];
377       if (! bin_count)
378         continue;
379
380       bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
381       bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
382       count_time = bin_count;
383
384       DBG (SAMPLEDEBUG,
385            printf (
386       "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%u\n",
387                     (unsigned long) (sizeof (UNIT) * bin_low_pc),
388                     (unsigned long) (sizeof (UNIT) * bin_high_pc),
389                     bin_count));
390       total_time += count_time;
391
392       /* Credit all symbols that are covered by bin I.  */
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;
397
398           /* If high end of bin is below entry address,
399              go for next bin.  */
400           if (bin_high_pc < sym_low_pc)
401             {
402               /* PR gprof/13325: Make sure that j does not go below 1.  */
403               if (j < 1)
404                 j = 1;
405               break;
406             }
407
408           /* If low end of bin is above high end of symbol,
409              go for next symbol.  */
410           if (bin_low_pc >= sym_high_pc)
411             continue;
412
413           overlap =
414             MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
415           if (overlap > 0)
416             {
417               DBG (SAMPLEDEBUG,
418                    printf (
419                "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
420                            (unsigned long) symtab.base[j].addr,
421                            (unsigned long) (sizeof (UNIT) * sym_high_pc),
422                            symtab.base[j].name, overlap * count_time / hist_scale,
423                            (long) overlap));
424
425               addr = symtab.base[j].addr;
426               credit = overlap * count_time / hist_scale;
427
428               /* Credit symbol if it appears in INCL_FLAT or that
429                  table is empty and it does not appear it in
430                  EXCL_FLAT.  */
431               if (sym_lookup (&syms[INCL_FLAT], addr)
432                   || (syms[INCL_FLAT].len == 0
433                       && !sym_lookup (&syms[EXCL_FLAT], addr)))
434                 {
435                   symtab.base[j].hist.time += credit;
436                 }
437               else
438                 {
439                   total_time -= credit;
440                 }
441             }
442         }
443     }
444
445   DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
446                             total_time));
447 }
448
449 /* Calls 'hist_assign_sampes_1' for all histogram records read so far. */
450 void
451 hist_assign_samples ()
452 {
453   unsigned i;
454
455   scale_and_align_entries ();
456
457   for (i = 0; i < num_histograms; ++i)
458     hist_assign_samples_1 (&histograms[i]);
459   
460 }
461
462 /* Print header for flag histogram profile.  */
463
464 static void
465 print_header (int prefix)
466 {
467   char unit[64];
468
469   sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
470
471   if (bsd_style_output)
472     {
473       printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
474               (long) hist_scale * (long) sizeof (UNIT));
475       if (total_time > 0.0)
476         {
477           printf (_(" for %.2f%% of %.2f %s\n\n"),
478                   100.0 / total_time, total_time / hz, hist_dimension);
479         }
480     }
481   else
482     {
483       printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
484     }
485
486   if (total_time <= 0.0)
487     {
488       printf (_(" no time accumulated\n\n"));
489
490       /* This doesn't hurt since all the numerators will be zero.  */
491       total_time = 1.0;
492     }
493
494   printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
495           "%  ", _("cumulative"), _("self  "), "", _("self  "), _("total "),
496           "");
497   printf ("%5.5s %9.9s  %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
498           _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
499           _("name"));
500 }
501
502
503 static void
504 print_line (Sym *sym, double scale)
505 {
506   if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
507     return;
508
509   accum_time += sym->hist.time;
510
511   if (bsd_style_output)
512     printf ("%5.1f %10.2f %8.2f",
513             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
514             accum_time / hz, sym->hist.time / hz);
515   else
516     printf ("%6.2f %9.2f %8.2f",
517             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
518             accum_time / hz, sym->hist.time / hz);
519
520   if (sym->ncalls != 0)
521     printf (" %8lu %8.2f %8.2f  ",
522             sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
523             scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
524   else
525     printf (" %8.8s %8.8s %8.8s  ", "", "", "");
526
527   if (bsd_style_output)
528     print_name (sym);
529   else
530     print_name_only (sym);
531
532   printf ("\n");
533 }
534
535
536 /* Compare LP and RP.  The primary comparison key is execution time,
537    the secondary is number of invocation, and the tertiary is the
538    lexicographic order of the function names.  */
539
540 static int
541 cmp_time (const PTR lp, const PTR rp)
542 {
543   const Sym *left = *(const Sym **) lp;
544   const Sym *right = *(const Sym **) rp;
545   double time_diff;
546
547   time_diff = right->hist.time - left->hist.time;
548
549   if (time_diff > 0.0)
550     return 1;
551
552   if (time_diff < 0.0)
553     return -1;
554
555   if (right->ncalls > left->ncalls)
556     return 1;
557
558   if (right->ncalls < left->ncalls)
559     return -1;
560
561   return strcmp (left->name, right->name);
562 }
563
564
565 /* Print the flat histogram profile.  */
566
567 void
568 hist_print ()
569 {
570   Sym **time_sorted_syms, *top_dog, *sym;
571   unsigned int sym_index;
572   unsigned log_scale;
573   double top_time;
574   bfd_vma addr;
575
576   if (first_output)
577     first_output = FALSE;
578   else
579     printf ("\f\n");
580
581   accum_time = 0.0;
582
583   if (bsd_style_output)
584     {
585       if (print_descriptions)
586         {
587           printf (_("\n\n\nflat profile:\n"));
588           flat_blurb (stdout);
589         }
590     }
591   else
592     {
593       printf (_("Flat profile:\n"));
594     }
595
596   /* Sort the symbol table by time (call-count and name as secondary
597      and tertiary keys).  */
598   time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
599
600   for (sym_index = 0; sym_index < symtab.len; ++sym_index)
601     time_sorted_syms[sym_index] = &symtab.base[sym_index];
602
603   qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
604
605   if (bsd_style_output)
606     {
607       log_scale = 5;            /* Milli-seconds is BSD-default.  */
608     }
609   else
610     {
611       /* Search for symbol with highest per-call
612          execution time and scale accordingly.  */
613       log_scale = 0;
614       top_dog = 0;
615       top_time = 0.0;
616
617       for (sym_index = 0; sym_index < symtab.len; ++sym_index)
618         {
619           sym = time_sorted_syms[sym_index];
620
621           if (sym->ncalls != 0)
622             {
623               double call_time;
624
625               call_time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
626
627               if (call_time > top_time)
628                 {
629                   top_dog = sym;
630                   top_time = call_time;
631                 }
632             }
633         }
634
635       if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
636         {
637           top_time /= hz;
638
639           for (log_scale = 0; log_scale < ARRAY_SIZE (SItab); log_scale ++)
640             {
641               double scaled_value = SItab[log_scale].scale * top_time;
642
643               if (scaled_value >= 1.0 && scaled_value < 1000.0) 
644                 break;
645             }
646         }
647     }
648
649   /* For now, the dimension is always seconds.  In the future, we
650      may also want to support other (pseudo-)dimensions (such as
651      I-cache misses etc.).  */
652   print_header (SItab[log_scale].prefix);
653
654   for (sym_index = 0; sym_index < symtab.len; ++sym_index)
655     {
656       addr = time_sorted_syms[sym_index]->addr;
657
658       /* Print symbol if its in INCL_FLAT table or that table
659         is empty and the symbol is not in EXCL_FLAT.  */
660       if (sym_lookup (&syms[INCL_FLAT], addr)
661           || (syms[INCL_FLAT].len == 0
662               && !sym_lookup (&syms[EXCL_FLAT], addr)))
663         print_line (time_sorted_syms[sym_index], SItab[log_scale].scale);
664     }
665
666   free (time_sorted_syms);
667
668   if (print_descriptions && !bsd_style_output)
669     flat_blurb (stdout);
670 }
671
672 int
673 hist_check_address (unsigned address)
674 {
675   unsigned i;
676
677   for (i = 0; i < num_histograms; ++i)
678     if (histograms[i].lowpc <= address && address < histograms[i].highpc)
679       return 1;
680
681   return 0;        
682 }
683
684 #if ! defined(min)
685 #define min(a,b) (((a)<(b)) ? (a) : (b))
686 #endif
687 #if ! defined(max)
688 #define max(a,b) (((a)>(b)) ? (a) : (b))
689 #endif
690
691 void
692 hist_clip_symbol_address (bfd_vma *p_lowpc, bfd_vma *p_highpc)
693 {
694   unsigned i;
695   int found = 0;
696
697   if (num_histograms == 0)
698     {
699       *p_highpc = *p_lowpc;
700       return;
701     }
702
703   for (i = 0; i < num_histograms; ++i)
704     {
705       bfd_vma common_low, common_high;
706       common_low = max (histograms[i].lowpc, *p_lowpc);
707       common_high = min (histograms[i].highpc, *p_highpc);
708
709       if (common_low < common_high)
710         {
711           if (found)
712             {
713               fprintf (stderr,
714                        _("%s: found a symbol that covers "
715                          "several histogram records"),
716                          whoami);
717               done (1);
718             }
719
720           found = 1;
721           *p_lowpc = common_low;
722           *p_highpc = common_high;
723         }
724     }
725
726   if (!found)
727     *p_highpc = *p_lowpc;
728 }
729
730 /* Find and return exising histogram record having the same lowpc and
731    highpc as passed via the parameters.  Return NULL if nothing is found.
732    The return value is valid until any new histogram is read.  */
733 static histogram *
734 find_histogram (bfd_vma lowpc, bfd_vma highpc)
735 {
736   unsigned i;
737   for (i = 0; i < num_histograms; ++i)
738     {
739       if (histograms[i].lowpc == lowpc && histograms[i].highpc == highpc)
740         return &histograms[i];
741     }
742   return 0;
743 }
744
745 /* Given a PC, return histogram record which address range include this PC.
746    Return NULL if there's no such record.  */
747 static histogram *
748 find_histogram_for_pc (bfd_vma pc)
749 {
750   unsigned i;
751   for (i = 0; i < num_histograms; ++i)
752     {
753       if (histograms[i].lowpc <= pc && pc < histograms[i].highpc)
754         return &histograms[i];
755     }
756   return 0;  
757 }