OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gprof/] [hist.c] - Blame information for rev 298

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* hist.c  -  Histogram related operations.
2
 
3
   Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2007
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
 
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
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 = (struct histogram *)
202
          xrealloc (histograms, 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
      histogram *r = find_histogram_for_pc (sym->addr);
300
 
301
      sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
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 * (long) 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.