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