Blame gprof/gmon_io.c

Packit bbfece
/* gmon_io.c - Input and output from/to gmon.out files.
Packit bbfece
Packit bbfece
   Copyright (C) 1999-2018 Free Software Foundation, Inc.
Packit bbfece
Packit bbfece
   This file is part of GNU Binutils.
Packit bbfece
Packit bbfece
   This program is free software; you can redistribute it and/or modify
Packit bbfece
   it under the terms of the GNU General Public License as published by
Packit bbfece
   the Free Software Foundation; either version 3 of the License, or
Packit bbfece
   (at your option) any later version.
Packit bbfece
Packit bbfece
   This program is distributed in the hope that it will be useful,
Packit bbfece
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bbfece
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bbfece
   GNU General Public License for more details.
Packit bbfece
Packit bbfece
   You should have received a copy of the GNU General Public License
Packit bbfece
   along with this program; if not, write to the Free Software
Packit bbfece
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
Packit bbfece
   02110-1301, USA.  */
Packit bbfece

Packit bbfece
#include "gprof.h"
Packit bbfece
#include "binary-io.h"
Packit bbfece
#include "search_list.h"
Packit bbfece
#include "source.h"
Packit bbfece
#include "symtab.h"
Packit bbfece
#include "cg_arcs.h"
Packit bbfece
#include "basic_blocks.h"
Packit bbfece
#include "corefile.h"
Packit bbfece
#include "call_graph.h"
Packit bbfece
#include "gmon_io.h"
Packit bbfece
#include "gmon_out.h"
Packit bbfece
#include "gmon.h"		/* Fetch header for old format.  */
Packit bbfece
#include "hertz.h"
Packit bbfece
#include "hist.h"
Packit bbfece
#include "libiberty.h"
Packit bbfece
Packit bbfece
enum gmon_ptr_size {
Packit bbfece
  ptr_32bit,
Packit bbfece
  ptr_64bit
Packit bbfece
};
Packit bbfece
Packit bbfece
enum gmon_ptr_signedness {
Packit bbfece
  ptr_signed,
Packit bbfece
  ptr_unsigned
Packit bbfece
};
Packit bbfece
Packit bbfece
static enum gmon_ptr_size gmon_get_ptr_size (void);
Packit bbfece
static enum gmon_ptr_signedness gmon_get_ptr_signedness (void);
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
static int gmon_io_read_64 (FILE *, BFD_HOST_U_64_BIT *);
Packit bbfece
static int gmon_io_write_64 (FILE *, BFD_HOST_U_64_BIT);
Packit bbfece
#endif
Packit bbfece
static int gmon_read_raw_arc
Packit bbfece
  (FILE *, bfd_vma *, bfd_vma *, unsigned long *);
Packit bbfece
static int gmon_write_raw_arc
Packit bbfece
  (FILE *, bfd_vma, bfd_vma, unsigned long);
Packit bbfece
Packit bbfece
int gmon_input = 0;
Packit bbfece
int gmon_file_version = 0;	/* 0 == old (non-versioned) file format.  */
Packit bbfece
Packit bbfece
static enum gmon_ptr_size
Packit bbfece
gmon_get_ptr_size (void)
Packit bbfece
{
Packit bbfece
  int size;
Packit bbfece
Packit bbfece
  /* Pick best size for pointers.  Start with the ELF size, and if not
Packit bbfece
     elf go with the architecture's address size.  */
Packit bbfece
  size = bfd_get_arch_size (core_bfd);
Packit bbfece
  if (size == -1)
Packit bbfece
    size = bfd_arch_bits_per_address (core_bfd);
Packit bbfece
Packit bbfece
  switch (size)
Packit bbfece
    {
Packit bbfece
    case 32:
Packit bbfece
      return ptr_32bit;
Packit bbfece
Packit bbfece
    case 64:
Packit bbfece
      return ptr_64bit;
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      fprintf (stderr, _("%s: address size has unexpected value of %u\n"),
Packit bbfece
	       whoami, size);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
static enum gmon_ptr_signedness
Packit bbfece
gmon_get_ptr_signedness (void)
Packit bbfece
{
Packit bbfece
  int sext;
Packit bbfece
Packit bbfece
  /* Figure out whether to sign extend.  If BFD doesn't know, assume no.  */
Packit bbfece
  sext = bfd_get_sign_extend_vma (core_bfd);
Packit bbfece
  if (sext == -1)
Packit bbfece
    return ptr_unsigned;
Packit bbfece
  return (sext ? ptr_signed : ptr_unsigned);
Packit bbfece
}
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_read_32 (FILE *ifp, unsigned int *valp)
Packit bbfece
{
Packit bbfece
  char buf[4];
Packit bbfece
Packit bbfece
  if (fread (buf, 1, 4, ifp) != 4)
Packit bbfece
    return 1;
Packit bbfece
  *valp = bfd_get_32 (core_bfd, buf);
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
static int
Packit bbfece
gmon_io_read_64 (FILE *ifp, BFD_HOST_U_64_BIT *valp)
Packit bbfece
{
Packit bbfece
  char buf[8];
Packit bbfece
Packit bbfece
  if (fread (buf, 1, 8, ifp) != 8)
Packit bbfece
    return 1;
Packit bbfece
  *valp = bfd_get_64 (core_bfd, buf);
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
#endif
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_read_vma (FILE *ifp, bfd_vma *valp)
Packit bbfece
{
Packit bbfece
  unsigned int val32;
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
  BFD_HOST_U_64_BIT val64;
Packit bbfece
#endif
Packit bbfece
Packit bbfece
  switch (gmon_get_ptr_size ())
Packit bbfece
    {
Packit bbfece
    case ptr_32bit:
Packit bbfece
      if (gmon_io_read_32 (ifp, &val32))
Packit bbfece
	return 1;
Packit bbfece
      if (gmon_get_ptr_signedness () == ptr_signed)
Packit bbfece
        *valp = (int) val32;
Packit bbfece
      else
Packit bbfece
        *valp = val32;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
    case ptr_64bit:
Packit bbfece
      if (gmon_io_read_64 (ifp, &val64))
Packit bbfece
	return 1;
Packit bbfece
#ifdef BFD_HOST_64_BIT
Packit bbfece
      if (gmon_get_ptr_signedness () == ptr_signed)
Packit bbfece
        *valp = (BFD_HOST_64_BIT) val64;
Packit bbfece
      else
Packit bbfece
#endif
Packit bbfece
        *valp = val64;
Packit bbfece
      break;
Packit bbfece
#endif
Packit bbfece
    }
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_read (FILE *ifp, char *buf, size_t n)
Packit bbfece
{
Packit bbfece
  if (fread (buf, 1, n, ifp) != n)
Packit bbfece
    return 1;
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_write_32 (FILE *ofp, unsigned int val)
Packit bbfece
{
Packit bbfece
  char buf[4];
Packit bbfece
Packit bbfece
  bfd_put_32 (core_bfd, (bfd_vma) val, buf);
Packit bbfece
  if (fwrite (buf, 1, 4, ofp) != 4)
Packit bbfece
    return 1;
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
static int
Packit bbfece
gmon_io_write_64 (FILE *ofp, BFD_HOST_U_64_BIT val)
Packit bbfece
{
Packit bbfece
  char buf[8];
Packit bbfece
Packit bbfece
  bfd_put_64 (core_bfd, (bfd_vma) val, buf);
Packit bbfece
  if (fwrite (buf, 1, 8, ofp) != 8)
Packit bbfece
    return 1;
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
#endif
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_write_vma (FILE *ofp, bfd_vma val)
Packit bbfece
{
Packit bbfece
Packit bbfece
  switch (gmon_get_ptr_size ())
Packit bbfece
    {
Packit bbfece
    case ptr_32bit:
Packit bbfece
      if (gmon_io_write_32 (ofp, (unsigned int) val))
Packit bbfece
	return 1;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
    case ptr_64bit:
Packit bbfece
      if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) val))
Packit bbfece
	return 1;
Packit bbfece
      break;
Packit bbfece
#endif
Packit bbfece
    }
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_write_8 (FILE *ofp, unsigned int val)
Packit bbfece
{
Packit bbfece
  char buf[1];
Packit bbfece
Packit bbfece
  bfd_put_8 (core_bfd, val, buf);
Packit bbfece
  if (fwrite (buf, 1, 1, ofp) != 1)
Packit bbfece
    return 1;
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
int
Packit bbfece
gmon_io_write (FILE *ofp, char *buf, size_t n)
Packit bbfece
{
Packit bbfece
  if (fwrite (buf, 1, n, ofp) != n)
Packit bbfece
    return 1;
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
static int
Packit bbfece
gmon_read_raw_arc (FILE *ifp, bfd_vma *fpc, bfd_vma *spc, unsigned long *cnt)
Packit bbfece
{
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
  BFD_HOST_U_64_BIT cnt64;
Packit bbfece
#endif
Packit bbfece
  unsigned int cnt32;
Packit bbfece
Packit bbfece
  if (gmon_io_read_vma (ifp, fpc)
Packit bbfece
      || gmon_io_read_vma (ifp, spc))
Packit bbfece
    return 1;
Packit bbfece
Packit bbfece
  switch (gmon_get_ptr_size ())
Packit bbfece
    {
Packit bbfece
    case ptr_32bit:
Packit bbfece
      if (gmon_io_read_32 (ifp, &cnt32))
Packit bbfece
	return 1;
Packit bbfece
      *cnt = cnt32;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
    case ptr_64bit:
Packit bbfece
      if (gmon_io_read_64 (ifp, &cnt64))
Packit bbfece
	return 1;
Packit bbfece
      *cnt = cnt64;
Packit bbfece
      break;
Packit bbfece
#endif
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      return 1;
Packit bbfece
    }
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
static int
Packit bbfece
gmon_write_raw_arc (FILE *ofp, bfd_vma fpc, bfd_vma spc, unsigned long cnt)
Packit bbfece
{
Packit bbfece
Packit bbfece
  if (gmon_io_write_vma (ofp, fpc)
Packit bbfece
      || gmon_io_write_vma (ofp, spc))
Packit bbfece
    return 1;
Packit bbfece
Packit bbfece
  switch (gmon_get_ptr_size ())
Packit bbfece
    {
Packit bbfece
    case ptr_32bit:
Packit bbfece
      if (gmon_io_write_32 (ofp, (unsigned int) cnt))
Packit bbfece
	return 1;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
#ifdef BFD_HOST_U_64_BIT
Packit bbfece
    case ptr_64bit:
Packit bbfece
      if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) cnt))
Packit bbfece
	return 1;
Packit bbfece
      break;
Packit bbfece
#endif
Packit bbfece
    }
Packit bbfece
  return 0;
Packit bbfece
}
Packit bbfece
Packit bbfece
void
Packit bbfece
gmon_out_read (const char *filename)
Packit bbfece
{
Packit bbfece
  FILE *ifp;
Packit bbfece
  struct gmon_hdr ghdr;
Packit bbfece
  unsigned char tag;
Packit bbfece
  int nhist = 0, narcs = 0, nbbs = 0;
Packit bbfece
Packit bbfece
  /* Open gmon.out file.  */
Packit bbfece
  if (strcmp (filename, "-") == 0)
Packit bbfece
    {
Packit bbfece
      ifp = stdin;
Packit bbfece
      SET_BINARY (fileno (stdin));
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      ifp = fopen (filename, FOPEN_RB);
Packit bbfece
Packit bbfece
      if (!ifp)
Packit bbfece
	{
Packit bbfece
	  perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: file too short to be a gmon file\n"),
Packit bbfece
	       filename);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if ((file_format == FF_MAGIC)
Packit bbfece
      || (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)))
Packit bbfece
    {
Packit bbfece
      if (file_format == FF_MAGIC && strncmp (&ghdr.cookie[0], GMON_MAGIC, 4))
Packit bbfece
	{
Packit bbfece
	  fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
Packit bbfece
		   whoami, filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Right magic, so it's probably really a new gmon.out file.  */
Packit bbfece
      gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
Packit bbfece
Packit bbfece
      if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
Packit bbfece
	{
Packit bbfece
	  fprintf (stderr,
Packit bbfece
		   _("%s: file `%s' has unsupported version %d\n"),
Packit bbfece
		   whoami, filename, gmon_file_version);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Read in all the records.  */
Packit bbfece
      while (fread (&tag, sizeof (tag), 1, ifp) == 1)
Packit bbfece
	{
Packit bbfece
	  switch (tag)
Packit bbfece
	    {
Packit bbfece
	    case GMON_TAG_TIME_HIST:
Packit bbfece
	      ++nhist;
Packit bbfece
	      gmon_input |= INPUT_HISTOGRAM;
Packit bbfece
	      hist_read_rec (ifp, filename);
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case GMON_TAG_CG_ARC:
Packit bbfece
	      ++narcs;
Packit bbfece
	      gmon_input |= INPUT_CALL_GRAPH;
Packit bbfece
	      cg_read_rec (ifp, filename);
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case GMON_TAG_BB_COUNT:
Packit bbfece
	      ++nbbs;
Packit bbfece
	      gmon_input |= INPUT_BB_COUNTS;
Packit bbfece
	      bb_read_rec (ifp, filename);
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    default:
Packit bbfece
	      fprintf (stderr,
Packit bbfece
		       _("%s: %s: found bad tag %d (file corrupted?)\n"),
Packit bbfece
		       whoami, filename, tag);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
  else if (file_format == FF_AUTO
Packit bbfece
	   || file_format == FF_BSD
Packit bbfece
	   || file_format == FF_BSD44)
Packit bbfece
    {
Packit bbfece
      struct hdr
Packit bbfece
      {
Packit bbfece
	bfd_vma low_pc;
Packit bbfece
	bfd_vma high_pc;
Packit bbfece
	unsigned int ncnt;
Packit bbfece
      };
Packit bbfece
      unsigned int i;
Packit bbfece
      int samp_bytes, header_size = 0;
Packit bbfece
      unsigned long count;
Packit bbfece
      bfd_vma from_pc, self_pc;
Packit bbfece
      UNIT raw_bin_count;
Packit bbfece
      struct hdr tmp;
Packit bbfece
      unsigned int version;
Packit bbfece
      unsigned int hist_num_bins;
Packit bbfece
Packit bbfece
      /* Information from a gmon.out file is in two parts: an array of
Packit bbfece
	 sampling hits within pc ranges, and the arcs.  */
Packit bbfece
      gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
Packit bbfece
Packit bbfece
      /* This fseek() ought to work even on stdin as long as it's
Packit bbfece
	 not an interactive device (heck, is there anybody who would
Packit bbfece
	 want to type in a gmon.out at the terminal?).  */
Packit bbfece
      if (fseek (ifp, 0, SEEK_SET) < 0)
Packit bbfece
	{
Packit bbfece
	  perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* The beginning of the old BSD header and the 4.4BSD header
Packit bbfece
	 are the same: lowpc, highpc, ncnt  */
Packit bbfece
      if (gmon_io_read_vma (ifp, &tmp.low_pc)
Packit bbfece
          || gmon_io_read_vma (ifp, &tmp.high_pc)
Packit bbfece
          || gmon_io_read_32 (ifp, &tmp.ncnt))
Packit bbfece
	{
Packit bbfece
 bad_gmon_file:
Packit bbfece
          fprintf (stderr, _("%s: file too short to be a gmon file\n"),
Packit bbfece
		   filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Check to see if this a 4.4BSD-style header.  */
Packit bbfece
      if (gmon_io_read_32 (ifp, &version))
Packit bbfece
	goto bad_gmon_file;
Packit bbfece
Packit bbfece
      if (version == GMONVERSION)
Packit bbfece
	{
Packit bbfece
	  unsigned int profrate;
Packit bbfece
Packit bbfece
	  /* 4.4BSD format header.  */
Packit bbfece
          if (gmon_io_read_32 (ifp, &profrate))
Packit bbfece
	    goto bad_gmon_file;
Packit bbfece
Packit bbfece
	  if (!histograms)
Packit bbfece
	    hz = profrate;
Packit bbfece
	  else if (hz != (int) profrate)
Packit bbfece
	    {
Packit bbfece
	      fprintf (stderr,
Packit bbfece
		       _("%s: profiling rate incompatible with first gmon file\n"),
Packit bbfece
		       filename);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
Packit bbfece
	  switch (gmon_get_ptr_size ())
Packit bbfece
	    {
Packit bbfece
	    case ptr_32bit:
Packit bbfece
	      header_size = GMON_HDRSIZE_BSD44_32;
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case ptr_64bit:
Packit bbfece
	      header_size = GMON_HDRSIZE_BSD44_64;
Packit bbfece
	      break;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  /* Old style BSD format.  */
Packit bbfece
	  if (file_format == FF_BSD44)
Packit bbfece
	    {
Packit bbfece
	      fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
Packit bbfece
		       whoami, filename);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
Packit bbfece
	  switch (gmon_get_ptr_size ())
Packit bbfece
	    {
Packit bbfece
	    case ptr_32bit:
Packit bbfece
	      header_size = GMON_HDRSIZE_OLDBSD_32;
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case ptr_64bit:
Packit bbfece
	      header_size = GMON_HDRSIZE_OLDBSD_64;
Packit bbfece
	      break;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Position the file to after the header.  */
Packit bbfece
      if (fseek (ifp, header_size, SEEK_SET) < 0)
Packit bbfece
	{
Packit bbfece
	  perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      samp_bytes = tmp.ncnt - header_size;
Packit bbfece
      hist_num_bins = samp_bytes / sizeof (UNIT);
Packit bbfece
      if (histograms && (tmp.low_pc != histograms->lowpc
Packit bbfece
			 || tmp.high_pc != histograms->highpc
Packit bbfece
			 || (hist_num_bins != histograms->num_bins)))
Packit bbfece
	{
Packit bbfece
	  fprintf (stderr, _("%s: incompatible with first gmon file\n"),
Packit bbfece
		   filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (!histograms)
Packit bbfece
	{
Packit bbfece
	  num_histograms = 1;
Packit bbfece
	  histograms = (struct histogram *) xmalloc (sizeof (struct histogram));
Packit bbfece
	  histograms->lowpc = tmp.low_pc;
Packit bbfece
	  histograms->highpc = tmp.high_pc;
Packit bbfece
	  histograms->num_bins = hist_num_bins;
Packit bbfece
	  hist_scale = (double)((tmp.high_pc - tmp.low_pc) / sizeof (UNIT))
Packit bbfece
	    / hist_num_bins;
Packit bbfece
	  histograms->sample = (int *) xmalloc (hist_num_bins * sizeof (int));
Packit bbfece
	  memset (histograms->sample, 0,
Packit bbfece
		  hist_num_bins * sizeof (int));
Packit bbfece
	}
Packit bbfece
Packit bbfece
      DBG (SAMPLEDEBUG,
Packit bbfece
	   printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
Packit bbfece
		   (unsigned long) tmp.low_pc, (unsigned long) tmp.high_pc,
Packit bbfece
		   tmp.ncnt);
Packit bbfece
	   printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
Packit bbfece
		   samp_bytes, hist_num_bins));
Packit bbfece
Packit bbfece
      /* Make sure that we have sensible values.  */
Packit bbfece
      if (samp_bytes < 0 || histograms->lowpc > histograms->highpc)
Packit bbfece
	{
Packit bbfece
	  fprintf (stderr,
Packit bbfece
	    _("%s: file '%s' does not appear to be in gmon.out format\n"),
Packit bbfece
	    whoami, filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (hist_num_bins)
Packit bbfece
	++nhist;
Packit bbfece
Packit bbfece
      for (i = 0; i < hist_num_bins; ++i)
Packit bbfece
	{
Packit bbfece
	  if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
Packit bbfece
	    {
Packit bbfece
	      fprintf (stderr,
Packit bbfece
		       _("%s: unexpected EOF after reading %d/%d bins\n"),
Packit bbfece
		       whoami, --i, hist_num_bins);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
Packit bbfece
	  histograms->sample[i]
Packit bbfece
	    += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* The rest of the file consists of a bunch of
Packit bbfece
	 <from,self,count> tuples.  */
Packit bbfece
      while (gmon_read_raw_arc (ifp, &from_pc, &self_pc, &count) == 0)
Packit bbfece
	{
Packit bbfece
	  ++narcs;
Packit bbfece
Packit bbfece
	  DBG (SAMPLEDEBUG,
Packit bbfece
	     printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
Packit bbfece
		     (unsigned long) from_pc, (unsigned long) self_pc, count));
Packit bbfece
Packit bbfece
	  /* Add this arc.  */
Packit bbfece
	  cg_tally (from_pc, self_pc, count);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (hz == HZ_WRONG)
Packit bbfece
	{
Packit bbfece
	  /* How many ticks per second?  If we can't tell, report
Packit bbfece
	     time in ticks.  */
Packit bbfece
	  hz = hertz ();
Packit bbfece
Packit bbfece
	  if (hz == HZ_WRONG)
Packit bbfece
	    {
Packit bbfece
	      hz = 1;
Packit bbfece
	      fprintf (stderr, _("time is in ticks, not seconds\n"));
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
Packit bbfece
	       whoami, file_format);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (ifp != stdin)
Packit bbfece
    fclose (ifp);
Packit bbfece
Packit bbfece
  if (output_style & STYLE_GMON_INFO)
Packit bbfece
    {
Packit bbfece
      printf (_("File `%s' (version %d) contains:\n"),
Packit bbfece
	      filename, gmon_file_version);
Packit bbfece
      printf (nhist == 1 ?
Packit bbfece
	      _("\t%d histogram record\n") :
Packit bbfece
	      _("\t%d histogram records\n"), nhist);
Packit bbfece
      printf (narcs == 1 ?
Packit bbfece
	      _("\t%d call-graph record\n") :
Packit bbfece
	      _("\t%d call-graph records\n"), narcs);
Packit bbfece
      printf (nbbs == 1 ?
Packit bbfece
	      _("\t%d basic-block count record\n") :
Packit bbfece
	      _("\t%d basic-block count records\n"), nbbs);
Packit bbfece
      first_output = FALSE;
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
void
Packit bbfece
gmon_out_write (const char *filename)
Packit bbfece
{
Packit bbfece
  FILE *ofp;
Packit bbfece
  struct gmon_hdr ghdr;
Packit bbfece
Packit bbfece
  ofp = fopen (filename, FOPEN_WB);
Packit bbfece
  if (!ofp)
Packit bbfece
    {
Packit bbfece
      perror (filename);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (file_format == FF_AUTO || file_format == FF_MAGIC)
Packit bbfece
    {
Packit bbfece
      /* Write gmon header.  */
Packit bbfece
Packit bbfece
      memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
Packit bbfece
      bfd_put_32 (core_bfd, (bfd_vma) GMON_VERSION, (bfd_byte *) ghdr.version);
Packit bbfece
Packit bbfece
      if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
Packit bbfece
	{
Packit bbfece
	  perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Write execution time histogram if we have one.  */
Packit bbfece
      if (gmon_input & INPUT_HISTOGRAM)
Packit bbfece
	hist_write_hist (ofp, filename);
Packit bbfece
Packit bbfece
      /* Write call graph arcs if we have any.  */
Packit bbfece
      if (gmon_input & INPUT_CALL_GRAPH)
Packit bbfece
	cg_write_arcs (ofp, filename);
Packit bbfece
Packit bbfece
      /* Write basic-block info if we have it.  */
Packit bbfece
      if (gmon_input & INPUT_BB_COUNTS)
Packit bbfece
	bb_write_blocks (ofp, filename);
Packit bbfece
    }
Packit bbfece
  else if (file_format == FF_BSD || file_format == FF_BSD44)
Packit bbfece
    {
Packit bbfece
      UNIT raw_bin_count;
Packit bbfece
      unsigned int i, hdrsize;
Packit bbfece
      unsigned padsize;
Packit bbfece
      char pad[3*4];
Packit bbfece
      Arc *arc;
Packit bbfece
      Sym *sym;
Packit bbfece
Packit bbfece
      memset (pad, 0, sizeof (pad));
Packit bbfece
Packit bbfece
      hdrsize = 0;
Packit bbfece
      /* Decide how large the header will be.  Use the 4.4BSD format
Packit bbfece
         header if explicitly specified, or if the profiling rate is
Packit bbfece
         non-standard.  Otherwise, use the old BSD format.  */
Packit bbfece
      if (file_format == FF_BSD44
Packit bbfece
	  || hz != hertz())
Packit bbfece
	{
Packit bbfece
	  padsize = 3*4;
Packit bbfece
	  switch (gmon_get_ptr_size ())
Packit bbfece
	    {
Packit bbfece
	    case ptr_32bit:
Packit bbfece
	      hdrsize = GMON_HDRSIZE_BSD44_32;
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case ptr_64bit:
Packit bbfece
	      hdrsize = GMON_HDRSIZE_BSD44_64;
Packit bbfece
	      break;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  padsize = 0;
Packit bbfece
	  switch (gmon_get_ptr_size ())
Packit bbfece
	    {
Packit bbfece
	    case ptr_32bit:
Packit bbfece
	      hdrsize = GMON_HDRSIZE_OLDBSD_32;
Packit bbfece
	      break;
Packit bbfece
Packit bbfece
	    case ptr_64bit:
Packit bbfece
	      hdrsize = GMON_HDRSIZE_OLDBSD_64;
Packit bbfece
	      /* FIXME: Checking host compiler defines here means that we can't
Packit bbfece
		 use a cross gprof alpha OSF.  */
Packit bbfece
#if defined(__alpha__) && defined (__osf__)
Packit bbfece
	      padsize = 4;
Packit bbfece
#endif
Packit bbfece
	      break;
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Write the parts of the headers that are common to both the
Packit bbfece
	 old BSD and 4.4BSD formats.  */
Packit bbfece
      if (gmon_io_write_vma (ofp, histograms->lowpc)
Packit bbfece
          || gmon_io_write_vma (ofp, histograms->highpc)
Packit bbfece
          || gmon_io_write_32 (ofp, histograms->num_bins
Packit bbfece
			       * sizeof (UNIT) + hdrsize))
Packit bbfece
	{
Packit bbfece
	  perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Write out the 4.4BSD header bits, if that's what we're using.  */
Packit bbfece
      if (file_format == FF_BSD44
Packit bbfece
	  || hz != hertz())
Packit bbfece
	{
Packit bbfece
          if (gmon_io_write_32 (ofp, GMONVERSION)
Packit bbfece
	      || gmon_io_write_32 (ofp, (unsigned int) hz))
Packit bbfece
	    {
Packit bbfece
	      perror (filename);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Now write out any necessary padding after the meaningful
Packit bbfece
	 header bits.  */
Packit bbfece
      if (padsize != 0
Packit bbfece
          && fwrite (pad, 1, padsize, ofp) != padsize)
Packit bbfece
        {
Packit bbfece
          perror (filename);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Dump the samples.  */
Packit bbfece
      for (i = 0; i < histograms->num_bins; ++i)
Packit bbfece
	{
Packit bbfece
	  bfd_put_16 (core_bfd, (bfd_vma) histograms->sample[i],
Packit bbfece
		      (bfd_byte *) &raw_bin_count[0]);
Packit bbfece
	  if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
Packit bbfece
	    {
Packit bbfece
	      perror (filename);
Packit bbfece
	      done (1);
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Dump the normalized raw arc information.  */
Packit bbfece
      for (sym = symtab.base; sym < symtab.limit; ++sym)
Packit bbfece
	{
Packit bbfece
	  for (arc = sym->cg.children; arc; arc = arc->next_child)
Packit bbfece
	    {
Packit bbfece
	      if (gmon_write_raw_arc (ofp, arc->parent->addr,
Packit bbfece
				      arc->child->addr, arc->count))
Packit bbfece
		{
Packit bbfece
		  perror (filename);
Packit bbfece
		  done (1);
Packit bbfece
		}
Packit bbfece
	      DBG (SAMPLEDEBUG,
Packit bbfece
		   printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
Packit bbfece
			   (unsigned long) arc->parent->addr,
Packit bbfece
			   (unsigned long) arc->child->addr, arc->count));
Packit bbfece
	    }
Packit bbfece
	}
Packit bbfece
Packit bbfece
      fclose (ofp);
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
Packit bbfece
	       whoami, file_format);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
  /* There is a potential resource leak here, but it is not important.  */
Packit bbfece
  /* coverity[leaked_storage: FALSE] */
Packit bbfece
}