gprof [PATCH RFA] try harder when determining target pointer size.
cgd@broadcom.com
cgd@broadcom.com
Fri Mar 28 20:55:00 GMT 2003
More information about the Binutils mailing list
Fri Mar 28 20:55:00 GMT 2003
- Previous message (by thread): ELF dynamic loader and undefined weak symbols
- Next message (by thread): gprof [PATCH RFA] try harder when determining target pointer size.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Back at: 2002-01-31 Jason R Thorpe <thorpej@wasabisystems.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@broadcom.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); } }
- Previous message (by thread): ELF dynamic loader and undefined weak symbols
- Next message (by thread): gprof [PATCH RFA] try harder when determining target pointer size.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list