2010-05-06 Michael Snyder <msnyder@vmware.com>
[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 fclose (ifp);
555
556 if (hz == HZ_WRONG)
557 {
ef368dac
NC
558 /* How many ticks per second? If we can't tell, report
559 time in ticks. */
252b5132 560 hz = hertz ();
0eee5820 561
252b5132
RH
562 if (hz == HZ_WRONG)
563 {
564 hz = 1;
565 fprintf (stderr, _("time is in ticks, not seconds\n"));
566 }
567 }
568 }
569 else
570 {
571 fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
572 whoami, file_format);
573 done (1);
574 }
575
d9097b0b
SB
576 if (ifp != stdin)
577 fclose (ifp);
578
252b5132
RH
579 if (output_style & STYLE_GMON_INFO)
580 {
581 printf (_("File `%s' (version %d) contains:\n"),
582 filename, gmon_file_version);
741247bf
NC
583 printf (nhist == 1 ?
584 _("\t%d histogram record\n") :
585 _("\t%d histogram records\n"), nhist);
586 printf (narcs == 1 ?
587 _("\t%d call-graph record\n") :
588 _("\t%d call-graph records\n"), narcs);
589 printf (nbbs == 1 ?
590 _("\t%d basic-block count record\n") :
591 _("\t%d basic-block count records\n"), nbbs);
b34976b6 592 first_output = FALSE;
252b5132
RH
593 }
594}
595
596
597void
3e8f6abf 598gmon_out_write (const char *filename)
252b5132
RH
599{
600 FILE *ofp;
601 struct gmon_hdr ghdr;
602
603 ofp = fopen (filename, FOPEN_WB);
604 if (!ofp)
605 {
606 perror (filename);
607 done (1);
608 }
609
610 if (file_format == FF_AUTO || file_format == FF_MAGIC)
611 {
ef368dac 612 /* Write gmon header. */
252b5132
RH
613
614 memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
1355568a 615 bfd_put_32 (core_bfd, (bfd_vma) GMON_VERSION, (bfd_byte *) ghdr.version);
0eee5820 616
252b5132
RH
617 if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
618 {
619 perror (filename);
620 done (1);
621 }
622
ef368dac 623 /* Write execution time histogram if we have one. */
252b5132 624 if (gmon_input & INPUT_HISTOGRAM)
ef368dac 625 hist_write_hist (ofp, filename);
252b5132 626
ef368dac 627 /* Write call graph arcs if we have any. */
252b5132 628 if (gmon_input & INPUT_CALL_GRAPH)
ef368dac 629 cg_write_arcs (ofp, filename);
252b5132 630
ef368dac 631 /* Write basic-block info if we have it. */
252b5132 632 if (gmon_input & INPUT_BB_COUNTS)
ef368dac 633 bb_write_blocks (ofp, filename);
252b5132
RH
634 }
635 else if (file_format == FF_BSD || file_format == FF_BSD44)
636 {
252b5132 637 UNIT raw_bin_count;
8c62e9e1 638 unsigned int i, hdrsize;
e7e2dd92
NC
639 unsigned padsize;
640 char pad[3*4];
252b5132
RH
641 Arc *arc;
642 Sym *sym;
643
e7e2dd92 644 memset (pad, 0, sizeof (pad));
252b5132 645
e7e2dd92
NC
646 hdrsize = 0;
647 /* Decide how large the header will be. Use the 4.4BSD format
648 header if explicitly specified, or if the profiling rate is
649 non-standard. Otherwise, use the old BSD format. */
252b5132 650 if (file_format == FF_BSD44
e7e2dd92 651 || hz != hertz())
252b5132 652 {
e7e2dd92 653 padsize = 3*4;
9844bab2 654 switch (gmon_get_ptr_size ())
252b5132 655 {
9844bab2 656 case ptr_32bit:
e7e2dd92
NC
657 hdrsize = GMON_HDRSIZE_BSD44_32;
658 break;
659
9844bab2 660 case ptr_64bit:
e7e2dd92
NC
661 hdrsize = GMON_HDRSIZE_BSD44_64;
662 break;
252b5132
RH
663 }
664 }
665 else
666 {
e7e2dd92 667 padsize = 0;
9844bab2 668 switch (gmon_get_ptr_size ())
e7e2dd92 669 {
9844bab2 670 case ptr_32bit:
e7e2dd92
NC
671 hdrsize = GMON_HDRSIZE_OLDBSD_32;
672 break;
673
9844bab2 674 case ptr_64bit:
e7e2dd92
NC
675 hdrsize = GMON_HDRSIZE_OLDBSD_64;
676 /* FIXME: Checking host compiler defines here means that we can't
677 use a cross gprof alpha OSF. */
678#if defined(__alpha__) && defined (__osf__)
679 padsize = 4;
680#endif
681 break;
e7e2dd92
NC
682 }
683 }
684
685 /* Write the parts of the headers that are common to both the
686 old BSD and 4.4BSD formats. */
b3296dc5
VP
687 if (gmon_io_write_vma (ofp, histograms->lowpc)
688 || gmon_io_write_vma (ofp, histograms->highpc)
689 || gmon_io_write_32 (ofp, histograms->num_bins
690 * sizeof (UNIT) + hdrsize))
e7e2dd92
NC
691 {
692 perror (filename);
693 done (1);
694 }
695
696 /* Write out the 4.4BSD header bits, if that's what we're using. */
697 if (file_format == FF_BSD44
698 || hz != hertz())
699 {
700 if (gmon_io_write_32 (ofp, GMONVERSION)
1355568a 701 || gmon_io_write_32 (ofp, (unsigned int) hz))
252b5132
RH
702 {
703 perror (filename);
704 done (1);
705 }
706 }
707
e7e2dd92
NC
708 /* Now write out any necessary padding after the meaningful
709 header bits. */
710 if (padsize != 0
711 && fwrite (pad, 1, padsize, ofp) != padsize)
712 {
713 perror (filename);
714 done (1);
715 }
716
ef368dac 717 /* Dump the samples. */
b3296dc5 718 for (i = 0; i < histograms->num_bins; ++i)
252b5132 719 {
b3296dc5 720 bfd_put_16 (core_bfd, (bfd_vma) histograms->sample[i],
1355568a 721 (bfd_byte *) &raw_bin_count[0]);
252b5132
RH
722 if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
723 {
724 perror (filename);
725 done (1);
726 }
727 }
728
ef368dac 729 /* Dump the normalized raw arc information. */
252b5132
RH
730 for (sym = symtab.base; sym < symtab.limit; ++sym)
731 {
732 for (arc = sym->cg.children; arc; arc = arc->next_child)
733 {
e7e2dd92
NC
734 if (gmon_write_raw_arc (ofp, arc->parent->addr,
735 arc->child->addr, arc->count))
252b5132
RH
736 {
737 perror (filename);
738 done (1);
739 }
740 DBG (SAMPLEDEBUG,
741 printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
fdcf7d43
ILT
742 (unsigned long) arc->parent->addr,
743 (unsigned long) arc->child->addr, arc->count));
252b5132
RH
744 }
745 }
0eee5820 746
252b5132
RH
747 fclose (ofp);
748 }
749 else
750 {
751 fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
752 whoami, file_format);
753 done (1);
754 }
755}
This page took 0.480384 seconds and 4 git commands to generate.