Back to index

cell-binutils  2.17cvs20070401
gmon_io.c
Go to the documentation of this file.
00001 /* gmon_io.c - Input and output from/to gmon.out files.
00002 
00003    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 #include "gprof.h"
00024 #include "search_list.h"
00025 #include "source.h"
00026 #include "symtab.h"
00027 #include "cg_arcs.h"
00028 #include "basic_blocks.h"
00029 #include "corefile.h"
00030 #include "call_graph.h"
00031 #include "gmon_io.h"
00032 #include "gmon_out.h"
00033 #include "gmon.h"           /* Fetch header for old format.  */
00034 #include "hertz.h"
00035 #include "hist.h"
00036 #include "libiberty.h"
00037 
00038 enum gmon_ptr_size {
00039   ptr_32bit,
00040   ptr_64bit
00041 };
00042 
00043 enum gmon_ptr_signedness {
00044   ptr_signed,
00045   ptr_unsigned
00046 };
00047 
00048 static enum gmon_ptr_size gmon_get_ptr_size (void);
00049 static enum gmon_ptr_signedness gmon_get_ptr_signedness (void);
00050 
00051 #ifdef BFD_HOST_U_64_BIT
00052 static int gmon_io_read_64 (FILE *, BFD_HOST_U_64_BIT *);
00053 static int gmon_io_write_64 (FILE *, BFD_HOST_U_64_BIT);
00054 #endif
00055 static int gmon_read_raw_arc
00056   (FILE *, bfd_vma *, bfd_vma *, unsigned long *);
00057 static int gmon_write_raw_arc
00058   (FILE *, bfd_vma, bfd_vma, unsigned long);
00059 
00060 int gmon_input = 0;
00061 int gmon_file_version = 0;  /* 0 == old (non-versioned) file format.  */
00062 
00063 static enum gmon_ptr_size
00064 gmon_get_ptr_size ()
00065 {
00066   int size;
00067 
00068   /* Pick best size for pointers.  Start with the ELF size, and if not
00069      elf go with the architecture's address size.  */
00070   size = bfd_get_arch_size (core_bfd);
00071   if (size == -1)
00072     size = bfd_arch_bits_per_address (core_bfd);
00073 
00074   switch (size)
00075     {
00076     case 32:
00077       return ptr_32bit;
00078 
00079     case 64:
00080       return ptr_64bit;
00081 
00082     default:
00083       fprintf (stderr, _("%s: address size has unexpected value of %u\n"),
00084               whoami, size);
00085       done (1);
00086     }
00087 }
00088 
00089 static enum gmon_ptr_signedness
00090 gmon_get_ptr_signedness ()
00091 {
00092   int sext;
00093 
00094   /* Figure out whether to sign extend.  If BFD doesn't know, assume no.  */
00095   sext = bfd_get_sign_extend_vma (core_bfd);
00096   if (sext == -1)
00097     return ptr_unsigned;
00098   return (sext ? ptr_signed : ptr_unsigned);
00099 }
00100 
00101 int
00102 gmon_io_read_32 (FILE *ifp, unsigned int *valp)
00103 {
00104   char buf[4];
00105 
00106   if (fread (buf, 1, 4, ifp) != 4)
00107     return 1;
00108   *valp = bfd_get_32 (core_bfd, buf);
00109   return 0;
00110 }
00111 
00112 #ifdef BFD_HOST_U_64_BIT
00113 static int
00114 gmon_io_read_64 (FILE *ifp, BFD_HOST_U_64_BIT *valp)
00115 {
00116   char buf[8];
00117 
00118   if (fread (buf, 1, 8, ifp) != 8)
00119     return 1;
00120   *valp = bfd_get_64 (core_bfd, buf);
00121   return 0;
00122 }
00123 #endif
00124 
00125 int
00126 gmon_io_read_vma (FILE *ifp, bfd_vma *valp)
00127 {
00128   unsigned int val32;
00129 #ifdef BFD_HOST_U_64_BIT
00130   BFD_HOST_U_64_BIT val64;
00131 #endif
00132 
00133   switch (gmon_get_ptr_size ())
00134     {
00135     case ptr_32bit:
00136       if (gmon_io_read_32 (ifp, &val32))
00137        return 1;
00138       if (gmon_get_ptr_signedness () == ptr_signed)
00139         *valp = (int) val32;
00140       else
00141         *valp = val32;
00142       break;
00143 
00144 #ifdef BFD_HOST_U_64_BIT
00145     case ptr_64bit:
00146       if (gmon_io_read_64 (ifp, &val64))
00147        return 1;
00148 #ifdef BFD_HOST_64_BIT
00149       if (gmon_get_ptr_signedness () == ptr_signed)
00150         *valp = (BFD_HOST_64_BIT) val64;
00151       else
00152 #endif
00153         *valp = val64;
00154       break;
00155 #endif
00156     }
00157   return 0;
00158 }
00159 
00160 int
00161 gmon_io_read (FILE *ifp, char *buf, size_t n)
00162 {
00163   if (fread (buf, 1, n, ifp) != n)
00164     return 1;
00165   return 0;
00166 }
00167 
00168 int
00169 gmon_io_write_32 (FILE *ofp, unsigned int val)
00170 {
00171   char buf[4];
00172 
00173   bfd_put_32 (core_bfd, (bfd_vma) val, buf);
00174   if (fwrite (buf, 1, 4, ofp) != 4)
00175     return 1;
00176   return 0;
00177 }
00178 
00179 #ifdef BFD_HOST_U_64_BIT
00180 static int
00181 gmon_io_write_64 (FILE *ofp, BFD_HOST_U_64_BIT val)
00182 {
00183   char buf[8];
00184 
00185   bfd_put_64 (core_bfd, (bfd_vma) val, buf);
00186   if (fwrite (buf, 1, 8, ofp) != 8)
00187     return 1;
00188   return 0;
00189 }
00190 #endif
00191 
00192 int
00193 gmon_io_write_vma (FILE *ofp, bfd_vma val)
00194 {
00195 
00196   switch (gmon_get_ptr_size ())
00197     {
00198     case ptr_32bit:
00199       if (gmon_io_write_32 (ofp, (unsigned int) val))
00200        return 1;
00201       break;
00202 
00203 #ifdef BFD_HOST_U_64_BIT
00204     case ptr_64bit:
00205       if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) val))
00206        return 1;
00207       break;
00208 #endif
00209     }
00210   return 0;
00211 }
00212 
00213 int
00214 gmon_io_write_8 (FILE *ofp, unsigned int val)
00215 {
00216   char buf[1];
00217 
00218   bfd_put_8 (core_bfd, val, buf);
00219   if (fwrite (buf, 1, 1, ofp) != 1)
00220     return 1;
00221   return 0;
00222 }
00223 
00224 int
00225 gmon_io_write (FILE *ofp, char *buf, size_t n)
00226 {
00227   if (fwrite (buf, 1, n, ofp) != n)
00228     return 1;
00229   return 0;
00230 }
00231 
00232 static int
00233 gmon_read_raw_arc (FILE *ifp, bfd_vma *fpc, bfd_vma *spc, unsigned long *cnt)
00234 {
00235 #ifdef BFD_HOST_U_64_BIT
00236   BFD_HOST_U_64_BIT cnt64;
00237 #endif
00238   unsigned int cnt32;
00239 
00240   if (gmon_io_read_vma (ifp, fpc)
00241       || gmon_io_read_vma (ifp, spc))
00242     return 1;
00243 
00244   switch (gmon_get_ptr_size ())
00245     {
00246     case ptr_32bit:
00247       if (gmon_io_read_32 (ifp, &cnt32))
00248        return 1;
00249       *cnt = cnt32;
00250       break;
00251 
00252 #ifdef BFD_HOST_U_64_BIT
00253     case ptr_64bit:
00254       if (gmon_io_read_64 (ifp, &cnt64))
00255        return 1;
00256       *cnt = cnt64;
00257       break;
00258 #endif
00259 
00260     default:
00261       return 1;
00262     }
00263   return 0;
00264 }
00265 
00266 static int
00267 gmon_write_raw_arc (FILE *ofp, bfd_vma fpc, bfd_vma spc, unsigned long cnt)
00268 {
00269 
00270   if (gmon_io_write_vma (ofp, fpc)
00271       || gmon_io_write_vma (ofp, spc))
00272     return 1;
00273 
00274   switch (gmon_get_ptr_size ())
00275     {
00276     case ptr_32bit:
00277       if (gmon_io_write_32 (ofp, (unsigned int) cnt))
00278        return 1;
00279       break;
00280 
00281 #ifdef BFD_HOST_U_64_BIT
00282     case ptr_64bit:
00283       if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) cnt))
00284        return 1;
00285       break;
00286 #endif
00287     }
00288   return 0;
00289 }
00290 
00291 void
00292 gmon_out_read (const char *filename)
00293 {
00294   FILE *ifp;
00295   struct gmon_hdr ghdr;
00296   unsigned char tag;
00297   int nhist = 0, narcs = 0, nbbs = 0;
00298 
00299   /* Open gmon.out file.  */
00300   if (strcmp (filename, "-") == 0)
00301     {
00302       ifp = stdin;
00303 #ifdef SET_BINARY
00304       SET_BINARY (fileno (stdin));
00305 #endif
00306     }
00307   else
00308     {
00309       ifp = fopen (filename, FOPEN_RB);
00310 
00311       if (!ifp)
00312        {
00313          perror (filename);
00314          done (1);
00315        }
00316     }
00317 
00318   if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1)
00319     {
00320       fprintf (stderr, _("%s: file too short to be a gmon file\n"),
00321               filename);
00322       done (1);
00323     }
00324 
00325   if ((file_format == FF_MAGIC)
00326       || (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)))
00327     {
00328       if (file_format == FF_MAGIC && strncmp (&ghdr.cookie[0], GMON_MAGIC, 4))
00329        {
00330          fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
00331                  whoami, filename);
00332          done (1);
00333        }
00334 
00335       /* Right magic, so it's probably really a new gmon.out file.  */
00336       gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
00337 
00338       if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
00339        {
00340          fprintf (stderr,
00341                  _("%s: file `%s' has unsupported version %d\n"),
00342                  whoami, filename, gmon_file_version);
00343          done (1);
00344        }
00345 
00346       /* Read in all the records.  */
00347       while (fread (&tag, sizeof (tag), 1, ifp) == 1)
00348        {
00349          switch (tag)
00350            {
00351            case GMON_TAG_TIME_HIST:
00352              ++nhist;
00353              gmon_input |= INPUT_HISTOGRAM;
00354              hist_read_rec (ifp, filename);
00355              break;
00356 
00357            case GMON_TAG_CG_ARC:
00358              ++narcs;
00359              gmon_input |= INPUT_CALL_GRAPH;
00360              cg_read_rec (ifp, filename);
00361              break;
00362 
00363            case GMON_TAG_BB_COUNT:
00364              ++nbbs;
00365              gmon_input |= INPUT_BB_COUNTS;
00366              bb_read_rec (ifp, filename);
00367              break;
00368 
00369            default:
00370              fprintf (stderr,
00371                      _("%s: %s: found bad tag %d (file corrupted?)\n"),
00372                      whoami, filename, tag);
00373              done (1);
00374            }
00375        }
00376     }
00377   else if (file_format == FF_AUTO
00378           || file_format == FF_BSD
00379           || file_format == FF_BSD44)
00380     {
00381       struct hdr
00382       {
00383        bfd_vma low_pc;
00384        bfd_vma high_pc;
00385        unsigned int ncnt;
00386       };
00387       unsigned int i;
00388       int samp_bytes, header_size = 0;
00389       unsigned long count;
00390       bfd_vma from_pc, self_pc;
00391       static struct hdr h;
00392       UNIT raw_bin_count;
00393       struct hdr tmp;
00394       unsigned int version;
00395 
00396       /* Information from a gmon.out file is in two parts: an array of
00397         sampling hits within pc ranges, and the arcs.  */
00398       gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
00399 
00400       /* This fseek() ought to work even on stdin as long as it's
00401         not an interactive device (heck, is there anybody who would
00402         want to type in a gmon.out at the terminal?).  */
00403       if (fseek (ifp, 0, SEEK_SET) < 0)
00404        {
00405          perror (filename);
00406          done (1);
00407        }
00408 
00409       /* The beginning of the old BSD header and the 4.4BSD header
00410         are the same: lowpc, highpc, ncnt  */
00411       if (gmon_io_read_vma (ifp, &tmp.low_pc)
00412           || gmon_io_read_vma (ifp, &tmp.high_pc)
00413           || gmon_io_read_32 (ifp, &tmp.ncnt))
00414        {
00415  bad_gmon_file:
00416           fprintf (stderr, _("%s: file too short to be a gmon file\n"),
00417                  filename);
00418          done (1);
00419        }
00420 
00421       /* Check to see if this a 4.4BSD-style header.  */
00422       if (gmon_io_read_32 (ifp, &version))
00423        goto bad_gmon_file;
00424 
00425       if (version == GMONVERSION)
00426        {
00427          unsigned int profrate;
00428 
00429          /* 4.4BSD format header.  */
00430           if (gmon_io_read_32 (ifp, &profrate))
00431            goto bad_gmon_file;
00432 
00433          if (!s_highpc)
00434            hz = profrate;
00435          else if (hz != (int) profrate)
00436            {
00437              fprintf (stderr,
00438                      _("%s: profiling rate incompatible with first gmon file\n"),
00439                      filename);
00440              done (1);
00441            }
00442 
00443          switch (gmon_get_ptr_size ())
00444            {
00445            case ptr_32bit:
00446              header_size = GMON_HDRSIZE_BSD44_32;
00447              break;
00448 
00449            case ptr_64bit:
00450              header_size = GMON_HDRSIZE_BSD44_64;
00451              break;
00452            }
00453        }
00454       else
00455        {
00456          /* Old style BSD format.  */
00457          if (file_format == FF_BSD44)
00458            {
00459              fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
00460                      whoami, filename);
00461              done (1);
00462            }
00463 
00464          switch (gmon_get_ptr_size ())
00465            {
00466            case ptr_32bit:
00467              header_size = GMON_HDRSIZE_OLDBSD_32;
00468              break;
00469 
00470            case ptr_64bit:
00471              header_size = GMON_HDRSIZE_OLDBSD_64;
00472              break;
00473            }
00474        }
00475 
00476       /* Position the file to after the header.  */
00477       if (fseek (ifp, header_size, SEEK_SET) < 0)
00478        {
00479          perror (filename);
00480          done (1);
00481        }
00482 
00483       if (s_highpc && (tmp.low_pc != h.low_pc
00484                      || tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt))
00485        {
00486          fprintf (stderr, _("%s: incompatible with first gmon file\n"),
00487                  filename);
00488          done (1);
00489        }
00490 
00491       h = tmp;
00492       s_lowpc = (bfd_vma) h.low_pc;
00493       s_highpc = (bfd_vma) h.high_pc;
00494       lowpc = (bfd_vma) h.low_pc / sizeof (UNIT);
00495       highpc = (bfd_vma) h.high_pc / sizeof (UNIT);
00496       samp_bytes = h.ncnt - header_size;
00497       hist_num_bins = samp_bytes / sizeof (UNIT);
00498 
00499       DBG (SAMPLEDEBUG,
00500           printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
00501                  (unsigned long) h.low_pc, (unsigned long) h.high_pc,
00502                  h.ncnt);
00503           printf ("[gmon_out_read]   s_lowpc 0x%lx   s_highpc 0x%lx\n",
00504                  (unsigned long) s_lowpc, (unsigned long) s_highpc);
00505           printf ("[gmon_out_read]     lowpc 0x%lx     highpc 0x%lx\n",
00506                  (unsigned long) lowpc, (unsigned long) highpc);
00507           printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
00508                  samp_bytes, hist_num_bins));
00509 
00510       /* Make sure that we have sensible values.  */
00511       if (samp_bytes < 0 || lowpc > highpc)
00512        {
00513          fprintf (stderr,
00514            _("%s: file '%s' does not appear to be in gmon.out format\n"),
00515            whoami, filename);
00516          done (1);
00517        }
00518 
00519       if (hist_num_bins)
00520        ++nhist;
00521 
00522       if (!hist_sample)
00523        {
00524          hist_sample =
00525            (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
00526 
00527          memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
00528        }
00529 
00530       for (i = 0; i < hist_num_bins; ++i)
00531        {
00532          if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
00533            {
00534              fprintf (stderr,
00535                      _("%s: unexpected EOF after reading %d/%d bins\n"),
00536                      whoami, --i, hist_num_bins);
00537              done (1);
00538            }
00539 
00540          hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
00541        }
00542 
00543       /* The rest of the file consists of a bunch of
00544         <from,self,count> tuples.  */
00545       while (gmon_read_raw_arc (ifp, &from_pc, &self_pc, &count) == 0)
00546        {
00547          ++narcs;
00548 
00549          DBG (SAMPLEDEBUG,
00550             printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
00551                    (unsigned long) from_pc, (unsigned long) self_pc, count));
00552 
00553          /* Add this arc.  */
00554          cg_tally (from_pc, self_pc, count);
00555        }
00556 
00557       fclose (ifp);
00558 
00559       if (hz == HZ_WRONG)
00560        {
00561          /* How many ticks per second?  If we can't tell, report
00562             time in ticks.  */
00563          hz = hertz ();
00564 
00565          if (hz == HZ_WRONG)
00566            {
00567              hz = 1;
00568              fprintf (stderr, _("time is in ticks, not seconds\n"));
00569            }
00570        }
00571     }
00572   else
00573     {
00574       fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
00575               whoami, file_format);
00576       done (1);
00577     }
00578 
00579   if (output_style & STYLE_GMON_INFO)
00580     {
00581       printf (_("File `%s' (version %d) contains:\n"),
00582              filename, gmon_file_version);
00583       printf (nhist == 1 ?
00584              _("\t%d histogram record\n") :
00585              _("\t%d histogram records\n"), nhist);
00586       printf (narcs == 1 ?
00587              _("\t%d call-graph record\n") :
00588              _("\t%d call-graph records\n"), narcs);
00589       printf (nbbs == 1 ?
00590              _("\t%d basic-block count record\n") :
00591              _("\t%d basic-block count records\n"), nbbs);
00592       first_output = FALSE;
00593     }
00594 }
00595 
00596 
00597 void
00598 gmon_out_write (const char *filename)
00599 {
00600   FILE *ofp;
00601   struct gmon_hdr ghdr;
00602 
00603   ofp = fopen (filename, FOPEN_WB);
00604   if (!ofp)
00605     {
00606       perror (filename);
00607       done (1);
00608     }
00609 
00610   if (file_format == FF_AUTO || file_format == FF_MAGIC)
00611     {
00612       /* Write gmon header.  */
00613 
00614       memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
00615       bfd_put_32 (core_bfd, (bfd_vma) GMON_VERSION, (bfd_byte *) ghdr.version);
00616 
00617       if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
00618        {
00619          perror (filename);
00620          done (1);
00621        }
00622 
00623       /* Write execution time histogram if we have one.  */
00624       if (gmon_input & INPUT_HISTOGRAM)
00625        hist_write_hist (ofp, filename);
00626 
00627       /* Write call graph arcs if we have any.  */
00628       if (gmon_input & INPUT_CALL_GRAPH)
00629        cg_write_arcs (ofp, filename);
00630 
00631       /* Write basic-block info if we have it.  */
00632       if (gmon_input & INPUT_BB_COUNTS)
00633        bb_write_blocks (ofp, filename);
00634     }
00635   else if (file_format == FF_BSD || file_format == FF_BSD44)
00636     {
00637       UNIT raw_bin_count;
00638       unsigned int i, hdrsize;
00639       unsigned padsize;
00640       char pad[3*4];
00641       Arc *arc;
00642       Sym *sym;
00643 
00644       memset (pad, 0, sizeof (pad));
00645 
00646       hdrsize = 0;
00647       /* Decide how large the header will be.  Use the 4.4BSD format
00648          header if explicitly specified, or if the profiling rate is
00649          non-standard.  Otherwise, use the old BSD format.  */
00650       if (file_format == FF_BSD44
00651          || hz != hertz())
00652        {
00653          padsize = 3*4;
00654          switch (gmon_get_ptr_size ())
00655            {
00656            case ptr_32bit:
00657              hdrsize = GMON_HDRSIZE_BSD44_32;
00658              break;
00659 
00660            case ptr_64bit:
00661              hdrsize = GMON_HDRSIZE_BSD44_64;
00662              break;
00663            }
00664        }
00665       else
00666        {
00667          padsize = 0;
00668          switch (gmon_get_ptr_size ())
00669            {
00670            case ptr_32bit:
00671              hdrsize = GMON_HDRSIZE_OLDBSD_32;
00672              break;
00673 
00674            case ptr_64bit:
00675              hdrsize = GMON_HDRSIZE_OLDBSD_64;
00676              /* FIXME: Checking host compiler defines here means that we can't
00677                use a cross gprof alpha OSF.  */ 
00678 #if defined(__alpha__) && defined (__osf__)
00679              padsize = 4;
00680 #endif
00681              break;
00682            }
00683        }
00684 
00685       /* Write the parts of the headers that are common to both the
00686         old BSD and 4.4BSD formats.  */
00687       if (gmon_io_write_vma (ofp, s_lowpc)
00688           || gmon_io_write_vma (ofp, s_highpc)
00689           || gmon_io_write_32 (ofp, hist_num_bins * sizeof (UNIT) + hdrsize))
00690        {
00691          perror (filename);
00692          done (1);
00693        }
00694 
00695       /* Write out the 4.4BSD header bits, if that's what we're using.  */
00696       if (file_format == FF_BSD44
00697          || hz != hertz())
00698        {
00699           if (gmon_io_write_32 (ofp, GMONVERSION)
00700              || gmon_io_write_32 (ofp, (unsigned int) hz))
00701            {
00702              perror (filename);
00703              done (1);
00704            }
00705        }
00706 
00707       /* Now write out any necessary padding after the meaningful
00708         header bits.  */
00709       if (padsize != 0
00710           && fwrite (pad, 1, padsize, ofp) != padsize)
00711         {
00712           perror (filename);
00713          done (1);
00714        }
00715 
00716       /* Dump the samples.  */
00717       for (i = 0; i < hist_num_bins; ++i)
00718        {
00719          bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i],
00720                     (bfd_byte *) &raw_bin_count[0]);
00721          if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
00722            {
00723              perror (filename);
00724              done (1);
00725            }
00726        }
00727 
00728       /* Dump the normalized raw arc information.  */
00729       for (sym = symtab.base; sym < symtab.limit; ++sym)
00730        {
00731          for (arc = sym->cg.children; arc; arc = arc->next_child)
00732            {
00733              if (gmon_write_raw_arc (ofp, arc->parent->addr,
00734                                   arc->child->addr, arc->count))
00735               {
00736                 perror (filename);
00737                 done (1);
00738               }
00739              DBG (SAMPLEDEBUG,
00740                  printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
00741                         (unsigned long) arc->parent->addr,
00742                         (unsigned long) arc->child->addr, arc->count));
00743            }
00744        }
00745 
00746       fclose (ofp);
00747     }
00748   else
00749     {
00750       fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
00751               whoami, file_format);
00752       done (1);
00753     }
00754 }