gdb/
[deliverable/binutils-gdb.git] / gprof / gmon_io.c
CommitLineData
ef368dac
NC
1/* gmon_io.c - Input and output from/to gmon.out files.
2
81e80dda 3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
d6a39701 4 Free Software Foundation, Inc.
ef368dac
NC
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
651dbc76 10 the Free Software Foundation; either version 3 of the License, or
ef368dac
NC
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
44eb1801
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
ef368dac 22\f
6d9c411a 23#include "gprof.h"
81e80dda 24#include "binary-io.h"
6d9c411a
AM
25#include "search_list.h"
26#include "source.h"
27#include "symtab.h"
252b5132
RH
28#include "cg_arcs.h"
29#include "basic_blocks.h"
252b5132
RH
30#include "corefile.h"
31#include "call_graph.h"
32#include "gmon_io.h"
33#include "gmon_out.h"
ef368dac 34#include "gmon.h" /* Fetch header for old format. */
252b5132
RH
35#include "hertz.h"
36#include "hist.h"
37#include "libiberty.h"
38
9844bab2
CD
39enum gmon_ptr_size {
40 ptr_32bit,
41 ptr_64bit
42};
43
44enum gmon_ptr_signedness {
45 ptr_signed,
46 ptr_unsigned
47};
48
3e8f6abf
BE
49static enum gmon_ptr_size gmon_get_ptr_size (void);
50static enum gmon_ptr_signedness gmon_get_ptr_signedness (void);
9844bab2 51
e4c79bb2 52#ifdef BFD_HOST_U_64_BIT
3e8f6abf
BE
53static int gmon_io_read_64 (FILE *, BFD_HOST_U_64_BIT *);
54static int gmon_io_write_64 (FILE *, BFD_HOST_U_64_BIT);
e4c79bb2 55#endif
1355568a 56static int gmon_read_raw_arc
3e8f6abf 57 (FILE *, bfd_vma *, bfd_vma *, unsigned long *);
1355568a 58static int gmon_write_raw_arc
3e8f6abf 59 (FILE *, bfd_vma, bfd_vma, unsigned long);
1355568a 60
252b5132 61int gmon_input = 0;
ef368dac
NC
62int gmon_file_version = 0; /* 0 == old (non-versioned) file format. */
63
9844bab2
CD
64static enum gmon_ptr_size
65gmon_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
90static enum gmon_ptr_signedness
91gmon_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
0eee5820 102int
3e8f6abf 103gmon_io_read_32 (FILE *ifp, unsigned int *valp)
e7e2dd92
NC
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
e4c79bb2 113#ifdef BFD_HOST_U_64_BIT
1355568a 114static int
3e8f6abf 115gmon_io_read_64 (FILE *ifp, BFD_HOST_U_64_BIT *valp)
0eee5820
AM
116{
117 char buf[8];
0eee5820 118
e7e2dd92
NC
119 if (fread (buf, 1, 8, ifp) != 8)
120 return 1;
121 *valp = bfd_get_64 (core_bfd, buf);
122 return 0;
123}
e4c79bb2 124#endif
e7e2dd92
NC
125
126int
3e8f6abf 127gmon_io_read_vma (FILE *ifp, bfd_vma *valp)
e7e2dd92
NC
128{
129 unsigned int val32;
e4c79bb2 130#ifdef BFD_HOST_U_64_BIT
e7e2dd92 131 BFD_HOST_U_64_BIT val64;
e4c79bb2 132#endif
e7e2dd92 133
9844bab2 134 switch (gmon_get_ptr_size ())
0eee5820 135 {
9844bab2 136 case ptr_32bit:
e7e2dd92 137 if (gmon_io_read_32 (ifp, &val32))
0eee5820 138 return 1;
9844bab2
CD
139 if (gmon_get_ptr_signedness () == ptr_signed)
140 *valp = (int) val32;
141 else
142 *valp = val32;
0eee5820
AM
143 break;
144
e4c79bb2 145#ifdef BFD_HOST_U_64_BIT
9844bab2 146 case ptr_64bit:
e7e2dd92 147 if (gmon_io_read_64 (ifp, &val64))
0eee5820 148 return 1;
9844bab2
CD
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;
0eee5820 155 break;
e4c79bb2 156#endif
0eee5820 157 }
0eee5820
AM
158 return 0;
159}
252b5132 160
0eee5820 161int
3e8f6abf 162gmon_io_read (FILE *ifp, char *buf, size_t n)
e7e2dd92
NC
163{
164 if (fread (buf, 1, n, ifp) != n)
165 return 1;
166 return 0;
167}
168
169int
3e8f6abf 170gmon_io_write_32 (FILE *ofp, unsigned int val)
0eee5820
AM
171{
172 char buf[4];
173
1355568a 174 bfd_put_32 (core_bfd, (bfd_vma) val, buf);
e7e2dd92 175 if (fwrite (buf, 1, 4, ofp) != 4)
0eee5820 176 return 1;
0eee5820
AM
177 return 0;
178}
179
e4c79bb2 180#ifdef BFD_HOST_U_64_BIT
1355568a 181static int
3e8f6abf 182gmon_io_write_64 (FILE *ofp, BFD_HOST_U_64_BIT val)
0eee5820 183{
e7e2dd92
NC
184 char buf[8];
185
1355568a 186 bfd_put_64 (core_bfd, (bfd_vma) val, buf);
e7e2dd92 187 if (fwrite (buf, 1, 8, ofp) != 8)
0eee5820
AM
188 return 1;
189 return 0;
190}
e4c79bb2 191#endif
0eee5820
AM
192
193int
3e8f6abf 194gmon_io_write_vma (FILE *ofp, bfd_vma val)
0eee5820 195{
0eee5820 196
9844bab2 197 switch (gmon_get_ptr_size ())
0eee5820 198 {
9844bab2 199 case ptr_32bit:
e7e2dd92 200 if (gmon_io_write_32 (ofp, (unsigned int) val))
0eee5820
AM
201 return 1;
202 break;
203
e4c79bb2 204#ifdef BFD_HOST_U_64_BIT
9844bab2 205 case ptr_64bit:
e7e2dd92 206 if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) val))
0eee5820
AM
207 return 1;
208 break;
e4c79bb2 209#endif
0eee5820
AM
210 }
211 return 0;
212}
213
0eee5820 214int
3e8f6abf 215gmon_io_write_8 (FILE *ofp, unsigned int val)
0eee5820
AM
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
225int
3e8f6abf 226gmon_io_write (FILE *ofp, char *buf, size_t n)
0eee5820
AM
227{
228 if (fwrite (buf, 1, n, ofp) != n)
229 return 1;
230 return 0;
231}
232
1355568a 233static int
3e8f6abf 234gmon_read_raw_arc (FILE *ifp, bfd_vma *fpc, bfd_vma *spc, unsigned long *cnt)
252b5132 235{
e4c79bb2 236#ifdef BFD_HOST_U_64_BIT
e7e2dd92 237 BFD_HOST_U_64_BIT cnt64;
e4c79bb2 238#endif
e7e2dd92
NC
239 unsigned int cnt32;
240
241 if (gmon_io_read_vma (ifp, fpc)
242 || gmon_io_read_vma (ifp, spc))
243 return 1;
244
9844bab2 245 switch (gmon_get_ptr_size ())
252b5132 246 {
9844bab2 247 case ptr_32bit:
e7e2dd92
NC
248 if (gmon_io_read_32 (ifp, &cnt32))
249 return 1;
250 *cnt = cnt32;
251 break;
252
e4c79bb2 253#ifdef BFD_HOST_U_64_BIT
9844bab2 254 case ptr_64bit:
e7e2dd92
NC
255 if (gmon_io_read_64 (ifp, &cnt64))
256 return 1;
257 *cnt = cnt64;
258 break;
e4c79bb2 259#endif
5ef6bac7
AM
260
261 default:
262 return 1;
252b5132 263 }
e7e2dd92 264 return 0;
252b5132
RH
265}
266
1355568a 267static int
3e8f6abf 268gmon_write_raw_arc (FILE *ofp, bfd_vma fpc, bfd_vma spc, unsigned long cnt)
252b5132 269{
e7e2dd92
NC
270
271 if (gmon_io_write_vma (ofp, fpc)
272 || gmon_io_write_vma (ofp, spc))
273 return 1;
274
9844bab2 275 switch (gmon_get_ptr_size ())
252b5132 276 {
9844bab2 277 case ptr_32bit:
e7e2dd92
NC
278 if (gmon_io_write_32 (ofp, (unsigned int) cnt))
279 return 1;
252b5132 280 break;
e7e2dd92 281
e4c79bb2 282#ifdef BFD_HOST_U_64_BIT
9844bab2 283 case ptr_64bit:
e7e2dd92
NC
284 if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) cnt))
285 return 1;
252b5132 286 break;
e4c79bb2 287#endif
252b5132 288 }
e7e2dd92 289 return 0;
252b5132
RH
290}
291
252b5132 292void
3e8f6abf 293gmon_out_read (const char *filename)
252b5132
RH
294{
295 FILE *ifp;
296 struct gmon_hdr ghdr;
297 unsigned char tag;
298 int nhist = 0, narcs = 0, nbbs = 0;
299
ef368dac 300 /* Open gmon.out file. */
252b5132
RH
301 if (strcmp (filename, "-") == 0)
302 {
303 ifp = stdin;
5af11cab 304 SET_BINARY (fileno (stdin));
252b5132
RH
305 }
306 else
307 {
308 ifp = fopen (filename, FOPEN_RB);
0eee5820 309
252b5132
RH
310 if (!ifp)
311 {
312 perror (filename);
313 done (1);
314 }
315 }
0eee5820 316
252b5132
RH
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
0eee5820
AM
324 if ((file_format == FF_MAGIC)
325 || (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)))
252b5132
RH
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
ef368dac 334 /* Right magic, so it's probably really a new gmon.out file. */
252b5132 335 gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
0eee5820 336
252b5132
RH
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
ef368dac 345 /* Read in all the records. */
252b5132
RH
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;
8c62e9e1 384 unsigned int ncnt;
252b5132 385 };
8c62e9e1
AM
386 unsigned int i;
387 int samp_bytes, header_size = 0;
252b5132
RH
388 unsigned long count;
389 bfd_vma from_pc, self_pc;
252b5132
RH
390 UNIT raw_bin_count;
391 struct hdr tmp;
8c62e9e1 392 unsigned int version;
b3296dc5 393 unsigned int hist_num_bins;
252b5132 394
ef368dac 395 /* Information from a gmon.out file is in two parts: an array of
0eee5820 396 sampling hits within pc ranges, and the arcs. */
252b5132
RH
397 gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
398
ef368dac 399 /* This fseek() ought to work even on stdin as long as it's
0eee5820
AM
400 not an interactive device (heck, is there anybody who would
401 want to type in a gmon.out at the terminal?). */
252b5132
RH
402 if (fseek (ifp, 0, SEEK_SET) < 0)
403 {
404 perror (filename);
405 done (1);
406 }
0eee5820 407
e7e2dd92
NC
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))
252b5132 413 {
e7e2dd92
NC
414 bad_gmon_file:
415 fprintf (stderr, _("%s: file too short to be a gmon file\n"),
252b5132
RH
416 filename);
417 done (1);
418 }
0eee5820 419
e7e2dd92
NC
420 /* Check to see if this a 4.4BSD-style header. */
421 if (gmon_io_read_32 (ifp, &version))
422 goto bad_gmon_file;
252b5132 423
e7e2dd92 424 if (version == GMONVERSION)
252b5132 425 {
8c62e9e1 426 unsigned int profrate;
252b5132
RH
427
428 /* 4.4BSD format header. */
e7e2dd92
NC
429 if (gmon_io_read_32 (ifp, &profrate))
430 goto bad_gmon_file;
0eee5820 431
b3296dc5 432 if (!histograms)
252b5132 433 hz = profrate;
8c62e9e1 434 else if (hz != (int) profrate)
252b5132
RH
435 {
436 fprintf (stderr,
437 _("%s: profiling rate incompatible with first gmon file\n"),
438 filename);
439 done (1);
440 }
441
9844bab2 442 switch (gmon_get_ptr_size ())
e7e2dd92 443 {
9844bab2 444 case ptr_32bit:
e7e2dd92
NC
445 header_size = GMON_HDRSIZE_BSD44_32;
446 break;
447
9844bab2 448 case ptr_64bit:
e7e2dd92
NC
449 header_size = GMON_HDRSIZE_BSD44_64;
450 break;
e7e2dd92 451 }
252b5132
RH
452 }
453 else
454 {
ef368dac 455 /* Old style BSD format. */
252b5132
RH
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
9844bab2 463 switch (gmon_get_ptr_size ())
252b5132 464 {
9844bab2 465 case ptr_32bit:
e7e2dd92
NC
466 header_size = GMON_HDRSIZE_OLDBSD_32;
467 break;
468
9844bab2 469 case ptr_64bit:
e7e2dd92
NC
470 header_size = GMON_HDRSIZE_OLDBSD_64;
471 break;
252b5132 472 }
e7e2dd92 473 }
252b5132 474
e7e2dd92
NC
475 /* Position the file to after the header. */
476 if (fseek (ifp, header_size, SEEK_SET) < 0)
477 {
478 perror (filename);
479 done (1);
252b5132
RH
480 }
481
b3296dc5
VP
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)))
252b5132
RH
487 {
488 fprintf (stderr, _("%s: incompatible with first gmon file\n"),
489 filename);
490 done (1);
491 }
0eee5820 492
b3296dc5
VP
493 if (!histograms)
494 {
4094fdc2 495 num_histograms = 1;
1e9cc1c2 496 histograms = (struct histogram *) xmalloc (sizeof (struct histogram));
b3296dc5
VP
497 histograms->lowpc = tmp.low_pc;
498 histograms->highpc = tmp.high_pc;
499 histograms->num_bins = hist_num_bins;
4094fdc2
BD
500 hist_scale = (double)((tmp.high_pc - tmp.low_pc) / sizeof (UNIT))
501 / hist_num_bins;
1e9cc1c2 502 histograms->sample = (int *) xmalloc (hist_num_bins * sizeof (int));
b3296dc5
VP
503 memset (histograms->sample, 0,
504 hist_num_bins * sizeof (int));
505 }
0eee5820 506
252b5132
RH
507 DBG (SAMPLEDEBUG,
508 printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
b3296dc5
VP
509 (unsigned long) tmp.low_pc, (unsigned long) tmp.high_pc,
510 tmp.ncnt);
252b5132
RH
511 printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
512 samp_bytes, hist_num_bins));
513
2d35e9f6 514 /* Make sure that we have sensible values. */
b3296dc5 515 if (samp_bytes < 0 || histograms->lowpc > histograms->highpc)
0eee5820
AM
516 {
517 fprintf (stderr,
2d35e9f6
NC
518 _("%s: file '%s' does not appear to be in gmon.out format\n"),
519 whoami, filename);
0eee5820
AM
520 done (1);
521 }
2d35e9f6 522
252b5132 523 if (hist_num_bins)
ef368dac 524 ++nhist;
252b5132 525
252b5132
RH
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 }
0eee5820 535
b3296dc5
VP
536 histograms->sample[i]
537 += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
252b5132
RH
538 }
539
ef368dac
NC
540 /* The rest of the file consists of a bunch of
541 <from,self,count> tuples. */
e7e2dd92 542 while (gmon_read_raw_arc (ifp, &from_pc, &self_pc, &count) == 0)
252b5132
RH
543 {
544 ++narcs;
0eee5820 545
252b5132
RH
546 DBG (SAMPLEDEBUG,
547 printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
fdcf7d43 548 (unsigned long) from_pc, (unsigned long) self_pc, count));
0eee5820 549
ef368dac 550 /* Add this arc. */
252b5132
RH
551 cg_tally (from_pc, self_pc, count);
552 }
0eee5820 553
252b5132
RH
554 if (hz == HZ_WRONG)
555 {
ef368dac
NC
556 /* How many ticks per second? If we can't tell, report
557 time in ticks. */
252b5132 558 hz = hertz ();
0eee5820 559
252b5132
RH
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
d9097b0b
SB
574 if (ifp != stdin)
575 fclose (ifp);
576
252b5132
RH
577 if (output_style & STYLE_GMON_INFO)
578 {
579 printf (_("File `%s' (version %d) contains:\n"),
580 filename, gmon_file_version);
741247bf
NC
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);
b34976b6 590 first_output = FALSE;
252b5132
RH
591 }
592}
593
594
595void
3e8f6abf 596gmon_out_write (const char *filename)
252b5132
RH
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 {
ef368dac 610 /* Write gmon header. */
252b5132
RH
611
612 memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
1355568a 613 bfd_put_32 (core_bfd, (bfd_vma) GMON_VERSION, (bfd_byte *) ghdr.version);
0eee5820 614
252b5132
RH
615 if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
616 {
617 perror (filename);
618 done (1);
619 }
620
ef368dac 621 /* Write execution time histogram if we have one. */
252b5132 622 if (gmon_input & INPUT_HISTOGRAM)
ef368dac 623 hist_write_hist (ofp, filename);
252b5132 624
ef368dac 625 /* Write call graph arcs if we have any. */
252b5132 626 if (gmon_input & INPUT_CALL_GRAPH)
ef368dac 627 cg_write_arcs (ofp, filename);
252b5132 628
ef368dac 629 /* Write basic-block info if we have it. */
252b5132 630 if (gmon_input & INPUT_BB_COUNTS)
ef368dac 631 bb_write_blocks (ofp, filename);
252b5132
RH
632 }
633 else if (file_format == FF_BSD || file_format == FF_BSD44)
634 {
252b5132 635 UNIT raw_bin_count;
8c62e9e1 636 unsigned int i, hdrsize;
e7e2dd92
NC
637 unsigned padsize;
638 char pad[3*4];
252b5132
RH
639 Arc *arc;
640 Sym *sym;
641
e7e2dd92 642 memset (pad, 0, sizeof (pad));
252b5132 643
e7e2dd92
NC
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. */
252b5132 648 if (file_format == FF_BSD44
e7e2dd92 649 || hz != hertz())
252b5132 650 {
e7e2dd92 651 padsize = 3*4;
9844bab2 652 switch (gmon_get_ptr_size ())
252b5132 653 {
9844bab2 654 case ptr_32bit:
e7e2dd92
NC
655 hdrsize = GMON_HDRSIZE_BSD44_32;
656 break;
657
9844bab2 658 case ptr_64bit:
e7e2dd92
NC
659 hdrsize = GMON_HDRSIZE_BSD44_64;
660 break;
252b5132
RH
661 }
662 }
663 else
664 {
e7e2dd92 665 padsize = 0;
9844bab2 666 switch (gmon_get_ptr_size ())
e7e2dd92 667 {
9844bab2 668 case ptr_32bit:
e7e2dd92
NC
669 hdrsize = GMON_HDRSIZE_OLDBSD_32;
670 break;
671
9844bab2 672 case ptr_64bit:
e7e2dd92
NC
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;
e7e2dd92
NC
680 }
681 }
682
683 /* Write the parts of the headers that are common to both the
684 old BSD and 4.4BSD formats. */
b3296dc5
VP
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))
e7e2dd92
NC
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)
1355568a 699 || gmon_io_write_32 (ofp, (unsigned int) hz))
252b5132
RH
700 {
701 perror (filename);
702 done (1);
703 }
704 }
705
e7e2dd92
NC
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
ef368dac 715 /* Dump the samples. */
b3296dc5 716 for (i = 0; i < histograms->num_bins; ++i)
252b5132 717 {
b3296dc5 718 bfd_put_16 (core_bfd, (bfd_vma) histograms->sample[i],
1355568a 719 (bfd_byte *) &raw_bin_count[0]);
252b5132
RH
720 if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
721 {
722 perror (filename);
723 done (1);
724 }
725 }
726
ef368dac 727 /* Dump the normalized raw arc information. */
252b5132
RH
728 for (sym = symtab.base; sym < symtab.limit; ++sym)
729 {
730 for (arc = sym->cg.children; arc; arc = arc->next_child)
731 {
e7e2dd92
NC
732 if (gmon_write_raw_arc (ofp, arc->parent->addr,
733 arc->child->addr, arc->count))
252b5132
RH
734 {
735 perror (filename);
736 done (1);
737 }
738 DBG (SAMPLEDEBUG,
739 printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
fdcf7d43
ILT
740 (unsigned long) arc->parent->addr,
741 (unsigned long) arc->child->addr, arc->count));
252b5132
RH
742 }
743 }
0eee5820 744
252b5132
RH
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}
This page took 0.64703 seconds and 4 git commands to generate.