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