This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gprof [PATCH RFA] try harder when determining target pointersize.


Back at:

	2002-01-31  Jason R Thorpe <thorpej at wasabisystems dot com>

gprof was modified to attempt to determine the target pointer size.

Alas, it was made to use bfd_arch_bits_per_address().  Unfortunately,
this function seems to be documented (and implemented 8-) to return
the pointer size of the architecture/CPU for which the binary is
compiled, rather than the pointer size in the ABI followed by the
binary.

Those changes were apparently tested on SPARC, and for SPARC's
constraints about what CPU architectures are represented in which
object formats, it works well enough.

Unfortunately, it fails for MIPS because mips can have binaries marked
as using 64-bit CPUs in "32-bit" (ILP32) ABIs:

* the n32 ABI is, basically, "64-bit code in an ILP32 ABI".  On the
  processors on which n32 code runs, 64-bit pointers _are_ allowed,
  and bfd_arch_bits_per_address returns 64.  However, the ABI's notion
  of a pointer (and what C considers a pointer 8-) is only 32 bits.
  32 bits are stored for pointers (and longs) in the profiling data
  structures.

* it's possible to compile code like "-mabi=32 -mips4", to allow
  access to certain later-ISA instructions in O32 ABI code.  Again, in
  this case, the binaries are marked as "mips4" and so
  bfd_arch_bits_per_address returns 64.


The patch below attempts to fix this.  It consults bfd_get_arch_size
to get the ELF size, and if that produces no answer falls back on
bfd_arch_bits_per_address().  The theory is that if your ELF format
doesn't support 64-bit pointers, your ABI won't either.

In addition, it generally cleans up the code IMO (hey, look at all
those extra copies of the error message, gone away! 8-), and also
attempts to handle architectures with signed pointers (e.g., MIPS 8-)

I don't believe that this is perfect, but I believe it's better than
the current version.  This has been tested (on userland code on):

	* x86 Linux (RH 7.2 iirc),

	* MIPS Linux (mips64-linux), using o32, n32, and n64 ABIs.
	  (these currently have some trouble with the timer tick
	  propagation so report no time elapsed, but that's not
	  gprof's fault.  8-)

I believe it should work on the sparc systems that provoked the
original patch, as well (since their pointer size is the same as the
ELF size reported by bfd_get_arch_size()).

There are several possible MIPS ABIs on which I believe this will
fail, but, well, it's better than nothing.  8-)

A good long-term solution might be to add a BFD function which returns
the ABI's pointer size (if known), but really I don't want to go there
myself.  In the case that somebody _does_ implement that at some
point, this patch will make it easier to use that function in gprof.


Thoughts?


chris
--
2003-03-27  Chris Demetriou  <cgd at broadcom dot com>

	* gmon_io.c (enum gmon_ptr_size, enum gmon_ptr_signedness): New.
	(gmon_get_ptr_size, gmon_get_ptr_signedness): New.
	(gmon_io_read_vma, gmon_io_write_vma, gmon_read_raw_arc)
	(gmon_write_raw_arc, gmon_out_read, gmon_out_write): Adjust to
	use new functions and enums.

Index: gmon_io.c
===================================================================
RCS file: /cvs/src/src/gprof/gmon_io.c,v
retrieving revision 1.16
diff -u -p -r1.16 gmon_io.c
--- gmon_io.c	30 Nov 2002 08:39:44 -0000	1.16
+++ gmon_io.c	27 Mar 2003 18:55:31 -0000
@@ -34,6 +34,19 @@
 #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 PARAMS((void));
+static enum gmon_ptr_signedness gmon_get_ptr_signedness PARAMS((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));
@@ -46,6 +59,44 @@ static int gmon_write_raw_arc
 int gmon_input = 0;
 int gmon_file_version = 0;	/* 0 == old (non-versioned) file format.  */
 
+static enum gmon_ptr_size
+gmon_get_ptr_size ()
+{
+  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 ()
+{
+  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;
@@ -84,26 +135,29 @@ gmon_io_read_vma (ifp, valp)
   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;
 }
@@ -153,24 +207,19 @@ gmon_io_write_vma (ofp, val)
      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;
 }
@@ -215,26 +264,21 @@ 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;
       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;
 }
@@ -251,24 +295,19 @@ gmon_write_raw_arc (ofp, fpc, spc, cnt)
       || 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;
 }
@@ -425,21 +464,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 +485,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);
 	    }
 	}
 
@@ -649,33 +676,27 @@ 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.  */ 
@@ -683,12 +704,6 @@ gmon_out_write (filename)
 	      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);
 	    }
 	}
 



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]