gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gprof / gmon_io.c
index 58bd3edfce0819758eeb5fed1170bca855787fe9..5686ebb6b99d679babd6374e012a97c10c2bae76 100644 (file)
@@ -1,12 +1,12 @@
 /* gmon_io.c - Input and output from/to gmon.out files.
 
-   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999-2020 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 \f
 #include "gprof.h"
+#include "binary-io.h"
 #include "search_list.h"
 #include "source.h"
 #include "symtab.h"
 #include "hist.h"
 #include "libiberty.h"
 
+enum gmon_ptr_size {
+  ptr_32bit,
+  ptr_64bit
+};
+
+enum gmon_ptr_signedness {
+  ptr_signed,
+  ptr_unsigned
+};
+
+static enum gmon_ptr_size gmon_get_ptr_size (void);
+static enum gmon_ptr_signedness gmon_get_ptr_signedness (void);
+
 #ifdef BFD_HOST_U_64_BIT
-static int gmon_io_read_64 PARAMS ((FILE *, BFD_HOST_U_64_BIT *));
-static int gmon_io_write_64 PARAMS ((FILE *, BFD_HOST_U_64_BIT));
+static int gmon_io_read_64 (FILE *, BFD_HOST_U_64_BIT *);
+static int gmon_io_write_64 (FILE *, BFD_HOST_U_64_BIT);
 #endif
 static int gmon_read_raw_arc
-  PARAMS ((FILE *, bfd_vma *, bfd_vma *, unsigned long *));
+  (FILE *, bfd_vma *, bfd_vma *, unsigned long *);
 static int gmon_write_raw_arc
-  PARAMS ((FILE *, bfd_vma, bfd_vma, unsigned long));
+  (FILE *, bfd_vma, bfd_vma, unsigned long);
 
 int gmon_input = 0;
 int gmon_file_version = 0;     /* 0 == old (non-versioned) file format.  */
 
+static enum gmon_ptr_size
+gmon_get_ptr_size (void)
+{
+  int size;
+
+  /* Pick best size for pointers.  Start with the ELF size, and if not
+     elf go with the architecture's address size.  */
+  size = bfd_get_arch_size (core_bfd);
+  if (size == -1)
+    size = bfd_arch_bits_per_address (core_bfd);
+
+  switch (size)
+    {
+    case 32:
+      return ptr_32bit;
+
+    case 64:
+      return ptr_64bit;
+
+    default:
+      fprintf (stderr, _("%s: address size has unexpected value of %u\n"),
+              whoami, size);
+      done (1);
+    }
+}
+
+static enum gmon_ptr_signedness
+gmon_get_ptr_signedness (void)
+{
+  int sext;
+
+  /* Figure out whether to sign extend.  If BFD doesn't know, assume no.  */
+  sext = bfd_get_sign_extend_vma (core_bfd);
+  if (sext == -1)
+    return ptr_unsigned;
+  return (sext ? ptr_signed : ptr_unsigned);
+}
+
 int
-gmon_io_read_32 (ifp, valp)
-     FILE *ifp;
-     unsigned int *valp;
+gmon_io_read_32 (FILE *ifp, unsigned int *valp)
 {
   char buf[4];
 
@@ -61,9 +111,7 @@ gmon_io_read_32 (ifp, valp)
 
 #ifdef BFD_HOST_U_64_BIT
 static int
-gmon_io_read_64 (ifp, valp)
-     FILE *ifp;
-     BFD_HOST_U_64_BIT *valp;
+gmon_io_read_64 (FILE *ifp, BFD_HOST_U_64_BIT *valp)
 {
   char buf[8];
 
@@ -75,44 +123,42 @@ gmon_io_read_64 (ifp, valp)
 #endif
 
 int
-gmon_io_read_vma (ifp, valp)
-     FILE *ifp;
-     bfd_vma *valp;
+gmon_io_read_vma (FILE *ifp, bfd_vma *valp)
 {
   unsigned int val32;
 #ifdef BFD_HOST_U_64_BIT
   BFD_HOST_U_64_BIT val64;
 #endif
 
-  switch (bfd_arch_bits_per_address (core_bfd))
+  switch (gmon_get_ptr_size ())
     {
-    case 32:
+    case ptr_32bit:
       if (gmon_io_read_32 (ifp, &val32))
        return 1;
-      *valp = val32;
+      if (gmon_get_ptr_signedness () == ptr_signed)
+        *valp = (int) val32;
+      else
+        *valp = val32;
       break;
 
 #ifdef BFD_HOST_U_64_BIT
-    case 64:
+    case ptr_64bit:
       if (gmon_io_read_64 (ifp, &val64))
        return 1;
-      *valp = val64;
+#ifdef BFD_HOST_64_BIT
+      if (gmon_get_ptr_signedness () == ptr_signed)
+        *valp = (BFD_HOST_64_BIT) val64;
+      else
+#endif
+        *valp = val64;
       break;
 #endif
-
-    default:
-      fprintf (stderr, _("%s: bits per address has unexpected value of %u\n"),
-              whoami, bfd_arch_bits_per_address (core_bfd));
-      done (1);
     }
   return 0;
 }
 
 int
-gmon_io_read (ifp, buf, n)
-     FILE *ifp;
-     char *buf;
-     size_t n;
+gmon_io_read (FILE *ifp, char *buf, size_t n)
 {
   if (fread (buf, 1, n, ifp) != n)
     return 1;
@@ -120,9 +166,7 @@ gmon_io_read (ifp, buf, n)
 }
 
 int
-gmon_io_write_32 (ofp, val)
-     FILE *ofp;
-     unsigned int val;
+gmon_io_write_32 (FILE *ofp, unsigned int val)
 {
   char buf[4];
 
@@ -134,9 +178,7 @@ gmon_io_write_32 (ofp, val)
 
 #ifdef BFD_HOST_U_64_BIT
 static int
-gmon_io_write_64 (ofp, val)
-     FILE *ofp;        
-     BFD_HOST_U_64_BIT val;
+gmon_io_write_64 (FILE *ofp, BFD_HOST_U_64_BIT val)
 {
   char buf[8];
 
@@ -148,37 +190,28 @@ gmon_io_write_64 (ofp, val)
 #endif
 
 int
-gmon_io_write_vma (ofp, val)
-     FILE *ofp;
-     bfd_vma val;
+gmon_io_write_vma (FILE *ofp, bfd_vma val)
 {
 
-  switch (bfd_arch_bits_per_address (core_bfd))
+  switch (gmon_get_ptr_size ())
     {
-    case 32:
+    case ptr_32bit:
       if (gmon_io_write_32 (ofp, (unsigned int) val))
        return 1;
       break;
 
 #ifdef BFD_HOST_U_64_BIT
-    case 64:
+    case ptr_64bit:
       if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) val))
        return 1;
       break;
 #endif
-
-    default:
-      fprintf (stderr, _("%s: bits per address has unexpected value of %u\n"),
-              whoami, bfd_arch_bits_per_address (core_bfd));
-      done (1);
     }
   return 0;
 }
 
 int
-gmon_io_write_8 (ofp, val)
-     FILE *ofp;        
-     unsigned int val;
+gmon_io_write_8 (FILE *ofp, unsigned int val)
 {
   char buf[1];
 
@@ -189,10 +222,7 @@ gmon_io_write_8 (ofp, val)
 }
 
 int
-gmon_io_write (ofp, buf, n)
-     FILE *ofp;        
-     char *buf;
-     size_t n;
+gmon_io_write (FILE *ofp, char *buf, size_t n)
 {
   if (fwrite (buf, 1, n, ofp) != n)
     return 1;
@@ -200,11 +230,7 @@ gmon_io_write (ofp, buf, n)
 }
 
 static int
-gmon_read_raw_arc (ifp, fpc, spc, cnt)
-     FILE *ifp;
-     bfd_vma *fpc;
-     bfd_vma *spc;
-     unsigned long *cnt;
+gmon_read_raw_arc (FILE *ifp, bfd_vma *fpc, bfd_vma *spc, unsigned long *cnt)
 {
 #ifdef BFD_HOST_U_64_BIT
   BFD_HOST_U_64_BIT cnt64;
@@ -215,16 +241,16 @@ gmon_read_raw_arc (ifp, fpc, spc, cnt)
       || gmon_io_read_vma (ifp, spc))
     return 1;
 
-  switch (bfd_arch_bits_per_address (core_bfd))
+  switch (gmon_get_ptr_size ())
     {
-    case 32:
+    case ptr_32bit:
       if (gmon_io_read_32 (ifp, &cnt32))
        return 1;
       *cnt = cnt32;
       break;
 
 #ifdef BFD_HOST_U_64_BIT
-    case 64:
+    case ptr_64bit:
       if (gmon_io_read_64 (ifp, &cnt64))
        return 1;
       *cnt = cnt64;
@@ -232,50 +258,38 @@ gmon_read_raw_arc (ifp, fpc, spc, cnt)
 #endif
 
     default:
-      fprintf (stderr, _("%s: bits per address has unexpected value of %u\n"),
-              whoami, bfd_arch_bits_per_address (core_bfd));
-      done (1);
+      return 1;
     }
   return 0;
 }
 
 static int
-gmon_write_raw_arc (ofp, fpc, spc, cnt)
-     FILE *ofp;
-     bfd_vma fpc;
-     bfd_vma spc;
-     unsigned long cnt;
+gmon_write_raw_arc (FILE *ofp, bfd_vma fpc, bfd_vma spc, unsigned long cnt)
 {
 
   if (gmon_io_write_vma (ofp, fpc)
       || gmon_io_write_vma (ofp, spc))
     return 1;
 
-  switch (bfd_arch_bits_per_address (core_bfd))
+  switch (gmon_get_ptr_size ())
     {
-    case 32:
+    case ptr_32bit:
       if (gmon_io_write_32 (ofp, (unsigned int) cnt))
        return 1;
       break;
 
 #ifdef BFD_HOST_U_64_BIT
-    case 64:
+    case ptr_64bit:
       if (gmon_io_write_64 (ofp, (BFD_HOST_U_64_BIT) cnt))
        return 1;
       break;
 #endif
-
-    default:
-      fprintf (stderr, _("%s: bits per address has unexpected value of %u\n"),
-              whoami, bfd_arch_bits_per_address (core_bfd));
-      done (1);
     }
   return 0;
 }
 
 void
-gmon_out_read (filename)
-     const char *filename;
+gmon_out_read (const char *filename)
 {
   FILE *ifp;
   struct gmon_hdr ghdr;
@@ -286,9 +300,7 @@ gmon_out_read (filename)
   if (strcmp (filename, "-") == 0)
     {
       ifp = stdin;
-#ifdef SET_BINARY
       SET_BINARY (fileno (stdin));
-#endif
     }
   else
     {
@@ -368,15 +380,16 @@ gmon_out_read (filename)
       {
        bfd_vma low_pc;
        bfd_vma high_pc;
-       int ncnt;
+       unsigned int ncnt;
       };
-      int i, samp_bytes, header_size = 0;
+      unsigned int i;
+      int samp_bytes, header_size = 0;
       unsigned long count;
       bfd_vma from_pc, self_pc;
-      static struct hdr h;
       UNIT raw_bin_count;
       struct hdr tmp;
-      int version;
+      unsigned int version;
+      unsigned int hist_num_bins;
 
       /* Information from a gmon.out file is in two parts: an array of
         sampling hits within pc ranges, and the arcs.  */
@@ -409,15 +422,15 @@ gmon_out_read (filename)
 
       if (version == GMONVERSION)
        {
-         int profrate;
+         unsigned int profrate;
 
          /* 4.4BSD format header.  */
           if (gmon_io_read_32 (ifp, &profrate))
            goto bad_gmon_file;
 
-         if (!s_highpc)
+         if (!histograms)
            hz = profrate;
-         else if (hz != profrate)
+         else if (hz != (int) profrate)
            {
              fprintf (stderr,
                       _("%s: profiling rate incompatible with first gmon file\n"),
@@ -425,21 +438,15 @@ gmon_out_read (filename)
              done (1);
            }
 
-         switch (bfd_arch_bits_per_address (core_bfd))
+         switch (gmon_get_ptr_size ())
            {
-           case 32:
+           case ptr_32bit:
              header_size = GMON_HDRSIZE_BSD44_32;
              break;
 
-           case 64:
+           case ptr_64bit:
              header_size = GMON_HDRSIZE_BSD44_64;
              break;
-
-           default:
-              fprintf (stderr,
-                       _("%s: bits per address has unexpected value of %u\n"),
-                      whoami, bfd_arch_bits_per_address (core_bfd));
-              done (1);
            }
        }
       else
@@ -452,21 +459,15 @@ gmon_out_read (filename)
              done (1);
            }
 
-         switch (bfd_arch_bits_per_address (core_bfd))
+         switch (gmon_get_ptr_size ())
            {
-           case 32:
+           case ptr_32bit:
              header_size = GMON_HDRSIZE_OLDBSD_32;
              break;
 
-           case 64:
+           case ptr_64bit:
              header_size = GMON_HDRSIZE_OLDBSD_64;
              break;
-
-           default:
-              fprintf (stderr,
-                       _("%s: bits per address has unexpected value of %u\n"),
-                      whoami, bfd_arch_bits_per_address (core_bfd));
-              done (1);
            }
        }
 
@@ -477,35 +478,40 @@ gmon_out_read (filename)
          done (1);
        }
 
-      if (s_highpc && (tmp.low_pc != h.low_pc
-                      || tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt))
+      samp_bytes = tmp.ncnt - header_size;
+      hist_num_bins = samp_bytes / sizeof (UNIT);
+      if (histograms && (tmp.low_pc != histograms->lowpc
+                        || tmp.high_pc != histograms->highpc
+                        || (hist_num_bins != histograms->num_bins)))
        {
          fprintf (stderr, _("%s: incompatible with first gmon file\n"),
                   filename);
          done (1);
        }
 
-      h = tmp;
-      s_lowpc = (bfd_vma) h.low_pc;
-      s_highpc = (bfd_vma) h.high_pc;
-      lowpc = (bfd_vma) h.low_pc / sizeof (UNIT);
-      highpc = (bfd_vma) h.high_pc / sizeof (UNIT);
-      samp_bytes = h.ncnt - header_size;
-      hist_num_bins = samp_bytes / sizeof (UNIT);
+      if (!histograms)
+       {
+         num_histograms = 1;
+         histograms = (struct histogram *) xmalloc (sizeof (struct histogram));
+         histograms->lowpc = tmp.low_pc;
+         histograms->highpc = tmp.high_pc;
+         histograms->num_bins = hist_num_bins;
+         hist_scale = (double)((tmp.high_pc - tmp.low_pc) / sizeof (UNIT))
+           / hist_num_bins;
+         histograms->sample = (int *) xmalloc (hist_num_bins * sizeof (int));
+         memset (histograms->sample, 0,
+                 hist_num_bins * sizeof (int));
+       }
 
       DBG (SAMPLEDEBUG,
           printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
-                  (unsigned long) h.low_pc, (unsigned long) h.high_pc,
-                  h.ncnt);
-          printf ("[gmon_out_read]   s_lowpc 0x%lx   s_highpc 0x%lx\n",
-                  (unsigned long) s_lowpc, (unsigned long) s_highpc);
-          printf ("[gmon_out_read]     lowpc 0x%lx     highpc 0x%lx\n",
-                  (unsigned long) lowpc, (unsigned long) highpc);
+                  (unsigned long) tmp.low_pc, (unsigned long) tmp.high_pc,
+                  tmp.ncnt);
           printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
                   samp_bytes, hist_num_bins));
 
       /* Make sure that we have sensible values.  */
-      if (samp_bytes < 0 || lowpc > highpc)
+      if (samp_bytes < 0 || histograms->lowpc > histograms->highpc)
        {
          fprintf (stderr,
            _("%s: file '%s' does not appear to be in gmon.out format\n"),
@@ -516,14 +522,6 @@ gmon_out_read (filename)
       if (hist_num_bins)
        ++nhist;
 
-      if (!hist_sample)
-       {
-         hist_sample =
-           (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
-
-         memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
-       }
-
       for (i = 0; i < hist_num_bins; ++i)
        {
          if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
@@ -534,7 +532,8 @@ gmon_out_read (filename)
              done (1);
            }
 
-         hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
+         histograms->sample[i]
+           += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
        }
 
       /* The rest of the file consists of a bunch of
@@ -551,8 +550,6 @@ gmon_out_read (filename)
          cg_tally (from_pc, self_pc, count);
        }
 
-      fclose (ifp);
-
       if (hz == HZ_WRONG)
        {
          /* How many ticks per second?  If we can't tell, report
@@ -573,6 +570,9 @@ gmon_out_read (filename)
       done (1);
     }
 
+  if (ifp != stdin)
+    fclose (ifp);
+
   if (output_style & STYLE_GMON_INFO)
     {
       printf (_("File `%s' (version %d) contains:\n"),
@@ -586,14 +586,13 @@ gmon_out_read (filename)
       printf (nbbs == 1 ?
              _("\t%d basic-block count record\n") :
              _("\t%d basic-block count records\n"), nbbs);
-      first_output = false;
+      first_output = FALSE;
     }
 }
 
 
 void
-gmon_out_write (filename)
-     const char *filename;
+gmon_out_write (const char *filename)
 {
   FILE *ofp;
   struct gmon_hdr ghdr;
@@ -633,7 +632,7 @@ gmon_out_write (filename)
   else if (file_format == FF_BSD || file_format == FF_BSD44)
     {
       UNIT raw_bin_count;
-      int i, hdrsize;
+      unsigned int i, hdrsize;
       unsigned padsize;
       char pad[3*4];
       Arc *arc;
@@ -649,54 +648,43 @@ gmon_out_write (filename)
          || hz != hertz())
        {
          padsize = 3*4;
-         switch (bfd_arch_bits_per_address (core_bfd))
+         switch (gmon_get_ptr_size ())
            {
-           case 32:
+           case ptr_32bit:
              hdrsize = GMON_HDRSIZE_BSD44_32;
              break;
 
-           case 64:
+           case ptr_64bit:
              hdrsize = GMON_HDRSIZE_BSD44_64;
              break;
-
-           default:
-              fprintf (stderr,
-                       _("%s: bits per address has unexpected value of %u\n"),
-                      whoami, bfd_arch_bits_per_address (core_bfd));
-              done (1);
            }
        }
       else
        {
          padsize = 0;
-         switch (bfd_arch_bits_per_address (core_bfd))
+         switch (gmon_get_ptr_size ())
            {
-           case 32:
+           case ptr_32bit:
              hdrsize = GMON_HDRSIZE_OLDBSD_32;
              break;
 
-           case 64:
+           case ptr_64bit:
              hdrsize = GMON_HDRSIZE_OLDBSD_64;
              /* FIXME: Checking host compiler defines here means that we can't
-                use a cross gprof alpha OSF.  */ 
+                use a cross gprof alpha OSF.  */
 #if defined(__alpha__) && defined (__osf__)
              padsize = 4;
 #endif
              break;
-
-           default:
-              fprintf (stderr,
-                       _("%s: bits per address has unexpected value of %u\n"),
-                      whoami, bfd_arch_bits_per_address (core_bfd));
-              done (1);
            }
        }
 
       /* Write the parts of the headers that are common to both the
         old BSD and 4.4BSD formats.  */
-      if (gmon_io_write_vma (ofp, s_lowpc)
-          || gmon_io_write_vma (ofp, s_highpc)
-          || gmon_io_write_32 (ofp, hist_num_bins * sizeof (UNIT) + hdrsize))
+      if (gmon_io_write_vma (ofp, histograms->lowpc)
+          || gmon_io_write_vma (ofp, histograms->highpc)
+          || gmon_io_write_32 (ofp, histograms->num_bins
+                              * sizeof (UNIT) + hdrsize))
        {
          perror (filename);
          done (1);
@@ -724,9 +712,9 @@ gmon_out_write (filename)
        }
 
       /* Dump the samples.  */
-      for (i = 0; i < hist_num_bins; ++i)
+      for (i = 0; i < histograms->num_bins; ++i)
        {
-         bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i],
+         bfd_put_16 (core_bfd, (bfd_vma) histograms->sample[i],
                      (bfd_byte *) &raw_bin_count[0]);
          if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
            {
This page took 0.045848 seconds and 4 git commands to generate.