Merge branch 'vendor/OPENSSL'
[dragonfly.git] / contrib / binutils-2.24 / 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, k;
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, k = 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
394          PR gprof/13325: Make sure that K does not get decremented
395          and J will never be less than 0.  */
396       for (j = k - 1; j < symtab.len; k = ++j)
397         {
398           sym_low_pc = symtab.base[j].hist.scaled_addr;
399           sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
400
401           /* If high end of bin is below entry address,
402              go for next bin.  */
403           if (bin_high_pc < sym_low_pc)
404             break;
405
406           /* If low end of bin is above high end of symbol,
407              go for next symbol.  */
408           if (bin_low_pc >= sym_high_pc)
409             continue;
410
411           overlap =
412             MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
413           if (overlap > 0)
414             {
415               DBG (SAMPLEDEBUG,
416                    printf (
417                "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
418                            (unsigned long) symtab.base[j].addr,
419                            (unsigned long) (sizeof (UNIT) * sym_high_pc),
420                            symtab.base[j].name, overlap * count_time / hist_scale,
421                            (long) overlap));
422
423               addr = symtab.base[j].addr;
424               credit = overlap * count_time / hist_scale;
425
426               /* Credit symbol if it appears in INCL_FLAT or that
427                  table is empty and it does not appear it in
428                  EXCL_FLAT.  */
429               if (sym_lookup (&syms[INCL_FLAT], addr)
430                   || (syms[INCL_FLAT].len == 0
431                       && !sym_lookup (&syms[EXCL_FLAT], addr)))
432                 {
433                   symtab.base[j].hist.time += credit;
434                 }
435               else
436                 {
437                   total_time -= credit;
438                 }
439             }
440         }
441     }
442
443   DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
444                             total_time));
445 }
446
447 /* Calls 'hist_assign_sampes_1' for all histogram records read so far. */
448 void
449 hist_assign_samples ()
450 {
451   unsigned i;
452
453   scale_and_align_entries ();
454
455   for (i = 0; i < num_histograms; ++i)
456     hist_assign_samples_1 (&histograms[i]);
457   
458 }
459
460 /* Print header for flag histogram profile.  */
461
462 static void
463 print_header (int prefix)
464 {
465   char unit[64];
466
467   sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
468
469   if (bsd_style_output)
470     {
471       printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
472               (long) hist_scale * (long) sizeof (UNIT));
473       if (total_time > 0.0)
474         {
475           printf (_(" for %.2f%% of %.2f %s\n\n"),
476                   100.0 / total_time, total_time / hz, hist_dimension);
477         }
478     }
479   else
480     {
481       printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
482     }
483
484   if (total_time <= 0.0)
485     {
486       printf (_(" no time accumulated\n\n"));
487
488       /* This doesn't hurt since all the numerators will be zero.  */
489       total_time = 1.0;
490     }
491
492   printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
493           "%  ", _("cumulative"), _("self  "), "", _("self  "), _("total "),
494           "");
495   printf ("%5.5s %9.9s  %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
496           _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
497           _("name"));
498 }
499
500
501 static void
502 print_line (Sym *sym, double scale)
503 {
504   if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
505     return;
506
507   accum_time += sym->hist.time;
508
509   if (bsd_style_output)
510     printf ("%5.1f %10.2f %8.2f",
511             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
512             accum_time / hz, sym->hist.time / hz);
513   else
514     printf ("%6.2f %9.2f %8.2f",
515             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
516             accum_time / hz, sym->hist.time / hz);
517
518   if (sym->ncalls != 0)
519     printf (" %8lu %8.2f %8.2f  ",
520             sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
521             scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
522   else
523     printf (" %8.8s %8.8s %8.8s  ", "", "", "");
524
525   if (bsd_style_output)
526     print_name (sym);
527   else
528     print_name_only (sym);
529
530   printf ("\n");
531 }
532
533
534 /* Compare LP and RP.  The primary comparison key is execution time,
535    the secondary is number of invocation, and the tertiary is the
536    lexicographic order of the function names.  */
537
538 static int
539 cmp_time (const PTR lp, const PTR rp)
540 {
541   const Sym *left = *(const Sym **) lp;
542   const Sym *right = *(const Sym **) rp;
543   double time_diff;
544
545   time_diff = right->hist.time - left->hist.time;
546
547   if (time_diff > 0.0)
548     return 1;
549
550   if (time_diff < 0.0)
551     return -1;
552
553   if (right->ncalls > left->ncalls)
554     return 1;
555
556   if (right->ncalls < left->ncalls)
557     return -1;
558
559   return strcmp (left->name, right->name);
560 }
561
562
563 /* Print the flat histogram profile.  */
564
565 void
566 hist_print ()
567 {
568   Sym **time_sorted_syms, *top_dog, *sym;
569   unsigned int sym_index;
570   unsigned log_scale;
571   double top_time;
572   bfd_vma addr;
573
574   if (first_output)
575     first_output = FALSE;
576   else
577     printf ("\f\n");
578
579   accum_time = 0.0;
580
581   if (bsd_style_output)
582     {
583       if (print_descriptions)
584         {
585           printf (_("\n\n\nflat profile:\n"));
586           flat_blurb (stdout);
587         }
588     }
589   else
590     {
591       printf (_("Flat profile:\n"));
592     }
593
594   /* Sort the symbol table by time (call-count and name as secondary
595      and tertiary keys).  */
596   time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
597
598   for (sym_index = 0; sym_index < symtab.len; ++sym_index)
599     time_sorted_syms[sym_index] = &symtab.base[sym_index];
600
601   qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
602
603   if (bsd_style_output)
604     {
605       log_scale = 5;            /* Milli-seconds is BSD-default.  */
606     }
607   else
608     {
609       /* Search for symbol with highest per-call
610          execution time and scale accordingly.  */
611       log_scale = 0;
612       top_dog = 0;
613       top_time = 0.0;
614
615       for (sym_index = 0; sym_index < symtab.len; ++sym_index)
616         {
617           sym = time_sorted_syms[sym_index];
618
619           if (sym->ncalls != 0)
620             {
621               double call_time;
622
623               call_time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
624
625               if (call_time > top_time)
626                 {
627                   top_dog = sym;
628                   top_time = call_time;
629                 }
630             }
631         }
632
633       if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
634         {
635           top_time /= hz;
636
637           for (log_scale = 0; log_scale < ARRAY_SIZE (SItab); log_scale ++)
638             {
639               double scaled_value = SItab[log_scale].scale * top_time;
640
641               if (scaled_value >= 1.0 && scaled_value < 1000.0) 
642                 break;
643             }
644         }
645     }
646
647   /* For now, the dimension is always seconds.  In the future, we
648      may also want to support other (pseudo-)dimensions (such as
649      I-cache misses etc.).  */
650   print_header (SItab[log_scale].prefix);
651
652   for (sym_index = 0; sym_index < symtab.len; ++sym_index)
653     {
654       addr = time_sorted_syms[sym_index]->addr;
655
656       /* Print symbol if its in INCL_FLAT table or that table
657         is empty and the symbol is not in EXCL_FLAT.  */
658       if (sym_lookup (&syms[INCL_FLAT], addr)
659           || (syms[INCL_FLAT].len == 0
660               && !sym_lookup (&syms[EXCL_FLAT], addr)))
661         print_line (time_sorted_syms[sym_index], SItab[log_scale].scale);
662     }
663
664   free (time_sorted_syms);
665
666   if (print_descriptions && !bsd_style_output)
667     flat_blurb (stdout);
668 }
669
670 int
671 hist_check_address (unsigned address)
672 {
673   unsigned i;
674
675   for (i = 0; i < num_histograms; ++i)
676     if (histograms[i].lowpc <= address && address < histograms[i].highpc)
677       return 1;
678
679   return 0;        
680 }
681
682 #if ! defined(min)
683 #define min(a,b) (((a)<(b)) ? (a) : (b))
684 #endif
685 #if ! defined(max)
686 #define max(a,b) (((a)>(b)) ? (a) : (b))
687 #endif
688
689 void
690 hist_clip_symbol_address (bfd_vma *p_lowpc, bfd_vma *p_highpc)
691 {
692   unsigned i;
693   int found = 0;
694
695   if (num_histograms == 0)
696     {
697       *p_highpc = *p_lowpc;
698       return;
699     }
700
701   for (i = 0; i < num_histograms; ++i)
702     {
703       bfd_vma common_low, common_high;
704       common_low = max (histograms[i].lowpc, *p_lowpc);
705       common_high = min (histograms[i].highpc, *p_highpc);
706
707       if (common_low < common_high)
708         {
709           if (found)
710             {
711               fprintf (stderr,
712                        _("%s: found a symbol that covers "
713                          "several histogram records"),
714                          whoami);
715               done (1);
716             }
717
718           found = 1;
719           *p_lowpc = common_low;
720           *p_highpc = common_high;
721         }
722     }
723
724   if (!found)
725     *p_highpc = *p_lowpc;
726 }
727
728 /* Find and return exising histogram record having the same lowpc and
729    highpc as passed via the parameters.  Return NULL if nothing is found.
730    The return value is valid until any new histogram is read.  */
731 static histogram *
732 find_histogram (bfd_vma lowpc, bfd_vma highpc)
733 {
734   unsigned i;
735   for (i = 0; i < num_histograms; ++i)
736     {
737       if (histograms[i].lowpc == lowpc && histograms[i].highpc == highpc)
738         return &histograms[i];
739     }
740   return 0;
741 }
742
743 /* Given a PC, return histogram record which address range include this PC.
744    Return NULL if there's no such record.  */
745 static histogram *
746 find_histogram_for_pc (bfd_vma pc)
747 {
748   unsigned i;
749   for (i = 0; i < num_histograms; ++i)
750     {
751       if (histograms[i].lowpc <= pc && pc < histograms[i].highpc)
752         return &histograms[i];
753     }
754   return 0;  
755 }