~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/gprof/gmon_io.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gmon_io.c - Input and output from/to gmon.out files.
 
2
 
 
3
   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
 
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 "binary-io.h"
 
25
#include "search_list.h"
 
26
#include "source.h"
 
27
#include "symtab.h"
 
28
#include "cg_arcs.h"
 
29
#include "basic_blocks.h"
 
30
#include "corefile.h"
 
31
#include "call_graph.h"
 
32
#include "gmon_io.h"
 
33
#include "gmon_out.h"
 
34
#include "gmon.h"               /* Fetch header for old format.  */
 
35
#include "hertz.h"
 
36
#include "hist.h"
 
37
#include "libiberty.h"
 
38
 
 
39
enum gmon_ptr_size {
 
40
  ptr_32bit,
 
41
  ptr_64bit
 
42
};
 
43
 
 
44
enum gmon_ptr_signedness {
 
45
  ptr_signed,
 
46
  ptr_unsigned
 
47
};
 
48
 
 
49
static enum gmon_ptr_size gmon_get_ptr_size (void);
 
50
static enum gmon_ptr_signedness gmon_get_ptr_signedness (void);
 
51
 
 
52
#ifdef BFD_HOST_U_64_BIT
 
53
static int gmon_io_read_64 (FILE *, BFD_HOST_U_64_BIT *);
 
54
static int gmon_io_write_64 (FILE *, BFD_HOST_U_64_BIT);
 
55
#endif
 
56
static int gmon_read_raw_arc
 
57
  (FILE *, bfd_vma *, bfd_vma *, unsigned long *);
 
58
static int gmon_write_raw_arc
 
59
  (FILE *, bfd_vma, bfd_vma, unsigned long);
 
60
 
 
61
int gmon_input = 0;
 
62
int gmon_file_version = 0;      /* 0 == old (non-versioned) file format.  */
 
63
 
 
64
static enum gmon_ptr_size
 
65
gmon_get_ptr_size ()
 
66
{
 
67
  int size;
 
68
 
 
69
  /* Pick best size for pointers.  Start with the ELF size, and if not
 
70
     elf go with the architecture's address size.  */
 
71
  size = bfd_get_arch_size (core_bfd);
 
72
  if (size == -1)
 
73
    size = bfd_arch_bits_per_address (core_bfd);
 
74
 
 
75
  switch (size)
 
76
    {
 
77
    case 32:
 
78
      return ptr_32bit;
 
79
 
 
80
    case 64:
 
81
      return ptr_64bit;
 
82
 
 
83
    default:
 
84
      fprintf (stderr, _("%s: address size has unexpected value of %u\n"),
 
85
               whoami, size);
 
86
      done (1);
 
87
    }
 
88
}
 
89
 
 
90
static enum gmon_ptr_signedness
 
91
gmon_get_ptr_signedness ()
 
92
{
 
93
  int sext;
 
94
 
 
95
  /* Figure out whether to sign extend.  If BFD doesn't know, assume no.  */
 
96
  sext = bfd_get_sign_extend_vma (core_bfd);
 
97
  if (sext == -1)
 
98
    return ptr_unsigned;
 
99
  return (sext ? ptr_signed : ptr_unsigned);
 
100
}
 
101
 
 
102
int
 
103
gmon_io_read_32 (FILE *ifp, unsigned int *valp)
 
104
{
 
105
  char buf[4];
 
106
 
 
107
  if (fread (buf, 1, 4, ifp) != 4)
 
108
    return 1;
 
109
  *valp = bfd_get_32 (core_bfd, buf);
 
110
  return 0;
 
111
}
 
112
 
 
113
#ifdef BFD_HOST_U_64_BIT
 
114
static int
 
115
gmon_io_read_64 (FILE *ifp, BFD_HOST_U_64_BIT *valp)
 
116
{
 
117
  char buf[8];
 
118
 
 
119
  if (fread (buf, 1, 8, ifp) != 8)
 
120
    return 1;
 
121
  *valp = bfd_get_64 (core_bfd, buf);
 
122
  return 0;
 
123
}
 
124
#endif
 
125
 
 
126
int
 
127
gmon_io_read_vma (FILE *ifp, bfd_vma *valp)
 
128
{
 
129
  unsigned int val32;
 
130
#ifdef BFD_HOST_U_64_BIT
 
131
  BFD_HOST_U_64_BIT val64;
 
132
#endif
 
133
 
 
134
  switch (gmon_get_ptr_size ())
 
135
    {
 
136
    case ptr_32bit:
 
137
      if (gmon_io_read_32 (ifp, &val32))
 
138
        return 1;
 
139
      if (gmon_get_ptr_signedness () == ptr_signed)
 
140
        *valp = (int) val32;
 
141
      else
 
142
        *valp = val32;
 
143
      break;
 
144
 
 
145
#ifdef BFD_HOST_U_64_BIT
 
146
    case ptr_64bit:
 
147
      if (gmon_io_read_64 (ifp, &val64))
 
148
        return 1;
 
149
#ifdef BFD_HOST_64_BIT
 
150
      if (gmon_get_ptr_signedness () == ptr_signed)
 
151
        *valp = (BFD_HOST_64_BIT) val64;
 
152
      else
 
153
#endif
 
154
        *valp = val64;
 
155
      break;
 
156
#endif
 
157
    }
 
158
  return 0;
 
159
}
 
160
 
 
161
int
 
162
gmon_io_read (FILE *ifp, char *buf, size_t n)
 
163
{
 
164
  if (fread (buf, 1, n, ifp) != n)
 
165
    return 1;
 
166
  return 0;
 
167
}
 
168
 
 
169
int
 
170
gmon_io_write_32 (FILE *ofp, unsigned int val)
 
171
{
 
172
  char buf[4];
 
173
 
 
174
  bfd_put_32 (core_bfd, (bfd_vma) val, buf);
 
175
  if (fwrite (buf, 1, 4, ofp) != 4)
 
176
    return 1;
 
177
  return 0;
 
178
}
 
179
 
 
180
#ifdef BFD_HOST_U_64_BIT
 
181
static int
 
182
gmon_io_write_64 (FILE *ofp, BFD_HOST_U_64_BIT val)
 
183
{
 
184
  char buf[8];
 
185
 
 
186
  bfd_put_64 (core_bfd, (bfd_vma) val, buf);
 
187
  if (fwrite (buf, 1, 8, ofp) != 8)
 
188
    return 1;
 
189
  return 0;
 
190
}
 
191
#endif
 
192
 
 
193
int
 
194
gmon_io_write_vma (FILE *ofp, bfd_vma val)
 
195
{
 
196
 
 
197
  switch (gmon_get_ptr_size ())
 
198
    {
 
199
    case ptr_32bit:
 
200
      if (gmon_io_write_32 (ofp, (unsigned int) val))
 
201
        return 1;
 
202
      break;
 
203
 
 
204
#ifdef BFD_HOST_U_64_BIT
 
205
    case ptr_64bit:
 
206
      if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) val))
 
207
        return 1;
 
208
      break;
 
209
#endif
 
210
    }
 
211
  return 0;
 
212
}
 
213
 
 
214
int
 
215
gmon_io_write_8 (FILE *ofp, unsigned int val)
 
216
{
 
217
  char buf[1];
 
218
 
 
219
  bfd_put_8 (core_bfd, val, buf);
 
220
  if (fwrite (buf, 1, 1, ofp) != 1)
 
221
    return 1;
 
222
  return 0;
 
223
}
 
224
 
 
225
int
 
226
gmon_io_write (FILE *ofp, char *buf, size_t n)
 
227
{
 
228
  if (fwrite (buf, 1, n, ofp) != n)
 
229
    return 1;
 
230
  return 0;
 
231
}
 
232
 
 
233
static int
 
234
gmon_read_raw_arc (FILE *ifp, bfd_vma *fpc, bfd_vma *spc, unsigned long *cnt)
 
235
{
 
236
#ifdef BFD_HOST_U_64_BIT
 
237
  BFD_HOST_U_64_BIT cnt64;
 
238
#endif
 
239
  unsigned int cnt32;
 
240
 
 
241
  if (gmon_io_read_vma (ifp, fpc)
 
242
      || gmon_io_read_vma (ifp, spc))
 
243
    return 1;
 
244
 
 
245
  switch (gmon_get_ptr_size ())
 
246
    {
 
247
    case ptr_32bit:
 
248
      if (gmon_io_read_32 (ifp, &cnt32))
 
249
        return 1;
 
250
      *cnt = cnt32;
 
251
      break;
 
252
 
 
253
#ifdef BFD_HOST_U_64_BIT
 
254
    case ptr_64bit:
 
255
      if (gmon_io_read_64 (ifp, &cnt64))
 
256
        return 1;
 
257
      *cnt = cnt64;
 
258
      break;
 
259
#endif
 
260
 
 
261
    default:
 
262
      return 1;
 
263
    }
 
264
  return 0;
 
265
}
 
266
 
 
267
static int
 
268
gmon_write_raw_arc (FILE *ofp, bfd_vma fpc, bfd_vma spc, unsigned long cnt)
 
269
{
 
270
 
 
271
  if (gmon_io_write_vma (ofp, fpc)
 
272
      || gmon_io_write_vma (ofp, spc))
 
273
    return 1;
 
274
 
 
275
  switch (gmon_get_ptr_size ())
 
276
    {
 
277
    case ptr_32bit:
 
278
      if (gmon_io_write_32 (ofp, (unsigned int) cnt))
 
279
        return 1;
 
280
      break;
 
281
 
 
282
#ifdef BFD_HOST_U_64_BIT
 
283
    case ptr_64bit:
 
284
      if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) cnt))
 
285
        return 1;
 
286
      break;
 
287
#endif
 
288
    }
 
289
  return 0;
 
290
}
 
291
 
 
292
void
 
293
gmon_out_read (const char *filename)
 
294
{
 
295
  FILE *ifp;
 
296
  struct gmon_hdr ghdr;
 
297
  unsigned char tag;
 
298
  int nhist = 0, narcs = 0, nbbs = 0;
 
299
 
 
300
  /* Open gmon.out file.  */
 
301
  if (strcmp (filename, "-") == 0)
 
302
    {
 
303
      ifp = stdin;
 
304
      SET_BINARY (fileno (stdin));
 
305
    }
 
306
  else
 
307
    {
 
308
      ifp = fopen (filename, FOPEN_RB);
 
309
 
 
310
      if (!ifp)
 
311
        {
 
312
          perror (filename);
 
313
          done (1);
 
314
        }
 
315
    }
 
316
 
 
317
  if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1)
 
318
    {
 
319
      fprintf (stderr, _("%s: file too short to be a gmon file\n"),
 
320
               filename);
 
321
      done (1);
 
322
    }
 
323
 
 
324
  if ((file_format == FF_MAGIC)
 
325
      || (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)))
 
326
    {
 
327
      if (file_format == FF_MAGIC && strncmp (&ghdr.cookie[0], GMON_MAGIC, 4))
 
328
        {
 
329
          fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
 
330
                   whoami, filename);
 
331
          done (1);
 
332
        }
 
333
 
 
334
      /* Right magic, so it's probably really a new gmon.out file.  */
 
335
      gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
 
336
 
 
337
      if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
 
338
        {
 
339
          fprintf (stderr,
 
340
                   _("%s: file `%s' has unsupported version %d\n"),
 
341
                   whoami, filename, gmon_file_version);
 
342
          done (1);
 
343
        }
 
344
 
 
345
      /* Read in all the records.  */
 
346
      while (fread (&tag, sizeof (tag), 1, ifp) == 1)
 
347
        {
 
348
          switch (tag)
 
349
            {
 
350
            case GMON_TAG_TIME_HIST:
 
351
              ++nhist;
 
352
              gmon_input |= INPUT_HISTOGRAM;
 
353
              hist_read_rec (ifp, filename);
 
354
              break;
 
355
 
 
356
            case GMON_TAG_CG_ARC:
 
357
              ++narcs;
 
358
              gmon_input |= INPUT_CALL_GRAPH;
 
359
              cg_read_rec (ifp, filename);
 
360
              break;
 
361
 
 
362
            case GMON_TAG_BB_COUNT:
 
363
              ++nbbs;
 
364
              gmon_input |= INPUT_BB_COUNTS;
 
365
              bb_read_rec (ifp, filename);
 
366
              break;
 
367
 
 
368
            default:
 
369
              fprintf (stderr,
 
370
                       _("%s: %s: found bad tag %d (file corrupted?)\n"),
 
371
                       whoami, filename, tag);
 
372
              done (1);
 
373
            }
 
374
        }
 
375
    }
 
376
  else if (file_format == FF_AUTO
 
377
           || file_format == FF_BSD
 
378
           || file_format == FF_BSD44)
 
379
    {
 
380
      struct hdr
 
381
      {
 
382
        bfd_vma low_pc;
 
383
        bfd_vma high_pc;
 
384
        unsigned int ncnt;
 
385
      };
 
386
      unsigned int i;
 
387
      int samp_bytes, header_size = 0;
 
388
      unsigned long count;
 
389
      bfd_vma from_pc, self_pc;
 
390
      UNIT raw_bin_count;
 
391
      struct hdr tmp;
 
392
      unsigned int version;
 
393
      unsigned int hist_num_bins;
 
394
 
 
395
      /* Information from a gmon.out file is in two parts: an array of
 
396
         sampling hits within pc ranges, and the arcs.  */
 
397
      gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
 
398
 
 
399
      /* This fseek() ought to work even on stdin as long as it's
 
400
         not an interactive device (heck, is there anybody who would
 
401
         want to type in a gmon.out at the terminal?).  */
 
402
      if (fseek (ifp, 0, SEEK_SET) < 0)
 
403
        {
 
404
          perror (filename);
 
405
          done (1);
 
406
        }
 
407
 
 
408
      /* The beginning of the old BSD header and the 4.4BSD header
 
409
         are the same: lowpc, highpc, ncnt  */
 
410
      if (gmon_io_read_vma (ifp, &tmp.low_pc)
 
411
          || gmon_io_read_vma (ifp, &tmp.high_pc)
 
412
          || gmon_io_read_32 (ifp, &tmp.ncnt))
 
413
        {
 
414
 bad_gmon_file:
 
415
          fprintf (stderr, _("%s: file too short to be a gmon file\n"),
 
416
                   filename);
 
417
          done (1);
 
418
        }
 
419
 
 
420
      /* Check to see if this a 4.4BSD-style header.  */
 
421
      if (gmon_io_read_32 (ifp, &version))
 
422
        goto bad_gmon_file;
 
423
 
 
424
      if (version == GMONVERSION)
 
425
        {
 
426
          unsigned int profrate;
 
427
 
 
428
          /* 4.4BSD format header.  */
 
429
          if (gmon_io_read_32 (ifp, &profrate))
 
430
            goto bad_gmon_file;
 
431
 
 
432
          if (!histograms)
 
433
            hz = profrate;
 
434
          else if (hz != (int) profrate)
 
435
            {
 
436
              fprintf (stderr,
 
437
                       _("%s: profiling rate incompatible with first gmon file\n"),
 
438
                       filename);
 
439
              done (1);
 
440
            }
 
441
 
 
442
          switch (gmon_get_ptr_size ())
 
443
            {
 
444
            case ptr_32bit:
 
445
              header_size = GMON_HDRSIZE_BSD44_32;
 
446
              break;
 
447
 
 
448
            case ptr_64bit:
 
449
              header_size = GMON_HDRSIZE_BSD44_64;
 
450
              break;
 
451
            }
 
452
        }
 
453
      else
 
454
        {
 
455
          /* Old style BSD format.  */
 
456
          if (file_format == FF_BSD44)
 
457
            {
 
458
              fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
 
459
                       whoami, filename);
 
460
              done (1);
 
461
            }
 
462
 
 
463
          switch (gmon_get_ptr_size ())
 
464
            {
 
465
            case ptr_32bit:
 
466
              header_size = GMON_HDRSIZE_OLDBSD_32;
 
467
              break;
 
468
 
 
469
            case ptr_64bit:
 
470
              header_size = GMON_HDRSIZE_OLDBSD_64;
 
471
              break;
 
472
            }
 
473
        }
 
474
 
 
475
      /* Position the file to after the header.  */
 
476
      if (fseek (ifp, header_size, SEEK_SET) < 0)
 
477
        {
 
478
          perror (filename);
 
479
          done (1);
 
480
        }
 
481
 
 
482
      samp_bytes = tmp.ncnt - header_size;
 
483
      hist_num_bins = samp_bytes / sizeof (UNIT);
 
484
      if (histograms && (tmp.low_pc != histograms->lowpc
 
485
                         || tmp.high_pc != histograms->highpc
 
486
                         || (hist_num_bins != histograms->num_bins)))
 
487
        {
 
488
          fprintf (stderr, _("%s: incompatible with first gmon file\n"),
 
489
                   filename);
 
490
          done (1);
 
491
        }
 
492
 
 
493
      if (!histograms)
 
494
        {
 
495
          num_histograms = 1;
 
496
          histograms = (struct histogram *) xmalloc (sizeof (struct histogram));
 
497
          histograms->lowpc = tmp.low_pc;
 
498
          histograms->highpc = tmp.high_pc;
 
499
          histograms->num_bins = hist_num_bins;
 
500
          hist_scale = (double)((tmp.high_pc - tmp.low_pc) / sizeof (UNIT))
 
501
            / hist_num_bins;
 
502
          histograms->sample = (int *) xmalloc (hist_num_bins * sizeof (int));
 
503
          memset (histograms->sample, 0, 
 
504
                  hist_num_bins * sizeof (int));
 
505
        }
 
506
 
 
507
      DBG (SAMPLEDEBUG,
 
508
           printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
 
509
                   (unsigned long) tmp.low_pc, (unsigned long) tmp.high_pc,
 
510
                   tmp.ncnt);
 
511
           printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
 
512
                   samp_bytes, hist_num_bins));
 
513
 
 
514
      /* Make sure that we have sensible values.  */
 
515
      if (samp_bytes < 0 || histograms->lowpc > histograms->highpc)
 
516
        {
 
517
          fprintf (stderr,
 
518
            _("%s: file '%s' does not appear to be in gmon.out format\n"),
 
519
            whoami, filename);
 
520
          done (1);
 
521
        }
 
522
 
 
523
      if (hist_num_bins)
 
524
        ++nhist;
 
525
 
 
526
      for (i = 0; i < hist_num_bins; ++i)
 
527
        {
 
528
          if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
 
529
            {
 
530
              fprintf (stderr,
 
531
                       _("%s: unexpected EOF after reading %d/%d bins\n"),
 
532
                       whoami, --i, hist_num_bins);
 
533
              done (1);
 
534
            }
 
535
 
 
536
          histograms->sample[i] 
 
537
            += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
 
538
        }
 
539
 
 
540
      /* The rest of the file consists of a bunch of
 
541
         <from,self,count> tuples.  */
 
542
      while (gmon_read_raw_arc (ifp, &from_pc, &self_pc, &count) == 0)
 
543
        {
 
544
          ++narcs;
 
545
 
 
546
          DBG (SAMPLEDEBUG,
 
547
             printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
 
548
                     (unsigned long) from_pc, (unsigned long) self_pc, count));
 
549
 
 
550
          /* Add this arc.  */
 
551
          cg_tally (from_pc, self_pc, count);
 
552
        }
 
553
 
 
554
      if (hz == HZ_WRONG)
 
555
        {
 
556
          /* How many ticks per second?  If we can't tell, report
 
557
             time in ticks.  */
 
558
          hz = hertz ();
 
559
 
 
560
          if (hz == HZ_WRONG)
 
561
            {
 
562
              hz = 1;
 
563
              fprintf (stderr, _("time is in ticks, not seconds\n"));
 
564
            }
 
565
        }
 
566
    }
 
567
  else
 
568
    {
 
569
      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
 
570
               whoami, file_format);
 
571
      done (1);
 
572
    }
 
573
 
 
574
  if (ifp != stdin)
 
575
    fclose (ifp);
 
576
 
 
577
  if (output_style & STYLE_GMON_INFO)
 
578
    {
 
579
      printf (_("File `%s' (version %d) contains:\n"),
 
580
              filename, gmon_file_version);
 
581
      printf (nhist == 1 ?
 
582
              _("\t%d histogram record\n") :
 
583
              _("\t%d histogram records\n"), nhist);
 
584
      printf (narcs == 1 ?
 
585
              _("\t%d call-graph record\n") :
 
586
              _("\t%d call-graph records\n"), narcs);
 
587
      printf (nbbs == 1 ?
 
588
              _("\t%d basic-block count record\n") :
 
589
              _("\t%d basic-block count records\n"), nbbs);
 
590
      first_output = FALSE;
 
591
    }
 
592
}
 
593
 
 
594
 
 
595
void
 
596
gmon_out_write (const char *filename)
 
597
{
 
598
  FILE *ofp;
 
599
  struct gmon_hdr ghdr;
 
600
 
 
601
  ofp = fopen (filename, FOPEN_WB);
 
602
  if (!ofp)
 
603
    {
 
604
      perror (filename);
 
605
      done (1);
 
606
    }
 
607
 
 
608
  if (file_format == FF_AUTO || file_format == FF_MAGIC)
 
609
    {
 
610
      /* Write gmon header.  */
 
611
 
 
612
      memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
 
613
      bfd_put_32 (core_bfd, (bfd_vma) GMON_VERSION, (bfd_byte *) ghdr.version);
 
614
 
 
615
      if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
 
616
        {
 
617
          perror (filename);
 
618
          done (1);
 
619
        }
 
620
 
 
621
      /* Write execution time histogram if we have one.  */
 
622
      if (gmon_input & INPUT_HISTOGRAM)
 
623
        hist_write_hist (ofp, filename);
 
624
 
 
625
      /* Write call graph arcs if we have any.  */
 
626
      if (gmon_input & INPUT_CALL_GRAPH)
 
627
        cg_write_arcs (ofp, filename);
 
628
 
 
629
      /* Write basic-block info if we have it.  */
 
630
      if (gmon_input & INPUT_BB_COUNTS)
 
631
        bb_write_blocks (ofp, filename);
 
632
    }
 
633
  else if (file_format == FF_BSD || file_format == FF_BSD44)
 
634
    {
 
635
      UNIT raw_bin_count;
 
636
      unsigned int i, hdrsize;
 
637
      unsigned padsize;
 
638
      char pad[3*4];
 
639
      Arc *arc;
 
640
      Sym *sym;
 
641
 
 
642
      memset (pad, 0, sizeof (pad));
 
643
 
 
644
      hdrsize = 0;
 
645
      /* Decide how large the header will be.  Use the 4.4BSD format
 
646
         header if explicitly specified, or if the profiling rate is
 
647
         non-standard.  Otherwise, use the old BSD format.  */
 
648
      if (file_format == FF_BSD44
 
649
          || hz != hertz())
 
650
        {
 
651
          padsize = 3*4;
 
652
          switch (gmon_get_ptr_size ())
 
653
            {
 
654
            case ptr_32bit:
 
655
              hdrsize = GMON_HDRSIZE_BSD44_32;
 
656
              break;
 
657
 
 
658
            case ptr_64bit:
 
659
              hdrsize = GMON_HDRSIZE_BSD44_64;
 
660
              break;
 
661
            }
 
662
        }
 
663
      else
 
664
        {
 
665
          padsize = 0;
 
666
          switch (gmon_get_ptr_size ())
 
667
            {
 
668
            case ptr_32bit:
 
669
              hdrsize = GMON_HDRSIZE_OLDBSD_32;
 
670
              break;
 
671
 
 
672
            case ptr_64bit:
 
673
              hdrsize = GMON_HDRSIZE_OLDBSD_64;
 
674
              /* FIXME: Checking host compiler defines here means that we can't
 
675
                 use a cross gprof alpha OSF.  */ 
 
676
#if defined(__alpha__) && defined (__osf__)
 
677
              padsize = 4;
 
678
#endif
 
679
              break;
 
680
            }
 
681
        }
 
682
 
 
683
      /* Write the parts of the headers that are common to both the
 
684
         old BSD and 4.4BSD formats.  */
 
685
      if (gmon_io_write_vma (ofp, histograms->lowpc)
 
686
          || gmon_io_write_vma (ofp, histograms->highpc)
 
687
          || gmon_io_write_32 (ofp, histograms->num_bins 
 
688
                               * sizeof (UNIT) + hdrsize))
 
689
        {
 
690
          perror (filename);
 
691
          done (1);
 
692
        }
 
693
 
 
694
      /* Write out the 4.4BSD header bits, if that's what we're using.  */
 
695
      if (file_format == FF_BSD44
 
696
          || hz != hertz())
 
697
        {
 
698
          if (gmon_io_write_32 (ofp, GMONVERSION)
 
699
              || gmon_io_write_32 (ofp, (unsigned int) hz))
 
700
            {
 
701
              perror (filename);
 
702
              done (1);
 
703
            }
 
704
        }
 
705
 
 
706
      /* Now write out any necessary padding after the meaningful
 
707
         header bits.  */
 
708
      if (padsize != 0
 
709
          && fwrite (pad, 1, padsize, ofp) != padsize)
 
710
        {
 
711
          perror (filename);
 
712
          done (1);
 
713
        }
 
714
 
 
715
      /* Dump the samples.  */
 
716
      for (i = 0; i < histograms->num_bins; ++i)
 
717
        {
 
718
          bfd_put_16 (core_bfd, (bfd_vma) histograms->sample[i],
 
719
                      (bfd_byte *) &raw_bin_count[0]);
 
720
          if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
 
721
            {
 
722
              perror (filename);
 
723
              done (1);
 
724
            }
 
725
        }
 
726
 
 
727
      /* Dump the normalized raw arc information.  */
 
728
      for (sym = symtab.base; sym < symtab.limit; ++sym)
 
729
        {
 
730
          for (arc = sym->cg.children; arc; arc = arc->next_child)
 
731
            {
 
732
              if (gmon_write_raw_arc (ofp, arc->parent->addr,
 
733
                                      arc->child->addr, arc->count))
 
734
                {
 
735
                  perror (filename);
 
736
                  done (1);
 
737
                }
 
738
              DBG (SAMPLEDEBUG,
 
739
                   printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
 
740
                           (unsigned long) arc->parent->addr,
 
741
                           (unsigned long) arc->child->addr, arc->count));
 
742
            }
 
743
        }
 
744
 
 
745
      fclose (ofp);
 
746
    }
 
747
  else
 
748
    {
 
749
      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
 
750
               whoami, file_format);
 
751
      done (1);
 
752
    }
 
753
}