[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#193207: [hppa] [patch] fix fptr comparision problem



tag 193207 +patch
thanks

Please replace the hppa-fptr patch in gcc-3.2 with this one, which has a
fix (already in gcc-3.3 upstream) for the fptr comparision problem.

thanks
randolph


#! /bin/sh -e

# DP: Handle function pointer comparisions on hppa properly
# DP: Backported from gcc-3.3 branch
# DP: http://gcc.gnu.org/ml/gcc-cvs/2002-12/msg00157.html
# DP: http://gcc.gnu.org/ml/gcc-cvs/2002-12/msg00195.html

dir=
if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
    dir="$3/"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch)
        patch $pdir -f --no-backup-if-mismatch -p1 < $0
        #cd ${dir}gcc && autoconf
        ;;
    -unpatch)
        patch $pdir -f --no-backup-if-mismatch -R -p1 < $0
        #rm ${dir}gcc/configure
        ;;
    *)
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
esac
exit 0

2002-12-04  John David Anglin  <dave@hiauly1.hia.nrc.ca>

	* pa/fptr.c (__canonicalize_funcptr_for_compare): New file and function.
	* pa.md (canonicalize_funcptr_for_compare): Output library call to
	canonicalize_funcptr_for_compare_libfunc on TARGET_ELF32.
	* pa32-linux.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL,
	CTOR_LIST_BEGIN): New defines.
	* pa/t-linux (LIB2FUNCS_EXTRA): New define.
	(fptr.c): Add make rules.

2002-12-05  John David Anglin  <dave@hiauly1.hia.nrc.ca>

	* pa32-linux.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL): Move define.
	* pa.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL): To here.


diff -uNrp src.orig/gcc/config/pa/fptr.c src/gcc/config/pa/fptr.c
--- src.orig/gcc/config/pa/fptr.c	1969-12-31 16:00:00.000000000 -0800
+++ src/gcc/config/pa/fptr.c	2003-03-30 14:50:24.000000000 -0800
@@ -0,0 +1,127 @@
+/* Subroutine for function pointer canonicalization on PA-RISC with ELF32.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by John David Anglin (dave.anglin@nrc.ca).
+
+This file is part of GNU CC.
+
+GNU CC 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, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* WARNING: The code is this function depends on internal and undocumented
+   details of the GNU linker and dynamic loader as implemented for parisc
+   linux.  */
+
+/* This MUST match the defines sysdeps/hppa/dl-machine.h and
+   bfd/elf32-hppa.c.  */
+#define GOT_FROM_PLT_STUB (4*4)
+
+/* List of byte offsets in _dl_runtime_resolve to search for "bl" branches.
+   The first "bl" branch instruction found MUST be a call to fixup.  See
+   the define for TRAMPOLINE_TEMPLATE in sysdeps/hppa/dl-machine.h.  If
+   the trampoline template is changed, the list must be appropriately
+   updated.  The offset of -4 allows for a magic branch at the start of
+   the template should it be necessary to change the current branch
+   position.  */
+#define NOFFSETS 2
+static int fixup_branch_offset[NOFFSETS] = { 32, -4 };
+
+#define GET_FIELD(X, FROM, TO) \
+  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
+#define SIGN_EXTEND(VAL,BITS) \
+  ((int) ((VAL) >> ((BITS) - 1) ? (-1 << (BITS)) | (VAL) : (VAL)))
+
+struct link_map;
+typedef int (*fptr_t) (void);
+typedef int (*fixup_t) (struct link_map *, unsigned int);
+extern unsigned int _GLOBAL_OFFSET_TABLE_;
+
+/* __canonicalize_funcptr_for_compare must be hidden so that it is not
+   placed in the dynamic symbol table.  Like millicode functions, it
+   must be linked into all binaries in order access the got table of 
+   that binary.  However, we don't use the millicode calling convention
+   and the routine must be a normal function so that it can be compiled
+   as pic code.  */
+unsigned int __canonicalize_funcptr_for_compare (fptr_t)
+      __attribute__ ((visibility ("hidden")));
+
+unsigned int
+__canonicalize_funcptr_for_compare (fptr)
+     fptr_t fptr;
+{
+  static unsigned int fixup_plabel[2];
+  static fixup_t fixup;
+  unsigned int *plabel, *got;
+
+  /* -1 and page 0 are special.  -1 is used in crtend to mark the end of
+     a list of function pointers.  Also return immediately if the plabel
+     bit is not set in the function pointer.  In this case, the function
+     pointer points directly to the function.  */
+  if ((int) fptr == -1 || (unsigned int) fptr < 4096 || !((int) fptr & 2))
+    return (unsigned int) fptr;     
+
+  /* The function pointer points to a function descriptor (plabel).  If
+     the plabel hasn't been resolved, the first word of the plabel points
+     to the entry of the PLT stub just before the global offset table.
+     The second word in the plabel contains the relocation offset for the
+     function.  */
+  plabel = (unsigned int *) ((unsigned int) fptr & ~3);
+  got = (unsigned int *) (plabel[0] + GOT_FROM_PLT_STUB);
+
+  /* Return the address of the function if the plabel has been resolved.  */
+  if (got !=  &_GLOBAL_OFFSET_TABLE_)
+    return plabel[0];
+
+  /* Initialize our plabel for calling fixup if we haven't done so already.
+     This code needs to be thread safe but we don't have to be too careful
+     as the result is invariant.  */
+  if (!fixup)
+    {
+      int i;
+      unsigned int *iptr;
+
+      /* Find the first "bl" branch in the offset search list.  This is a
+	 call to fixup or a magic branch to fixup at the beginning of the
+	 trampoline template.  The fixup function does the actual runtime
+	 resolution of function decriptors.  We only look for "bl" branches
+	 with a 17-bit pc-relative displacement.  */
+      for (i = 0; i < NOFFSETS; i++)
+	{
+	  iptr = (unsigned int *) (got[-2] + fixup_branch_offset[i]);
+	  if ((*iptr & 0xfc00e000) == 0xe8000000)
+	    break;
+	}
+
+      /* This should not happen... */
+      if (i == NOFFSETS)
+	return ~0;
+
+      /* Extract the 17-bit displacement from the instruction.  */
+      iptr += SIGN_EXTEND (GET_FIELD (*iptr, 19, 28) |
+			   GET_FIELD (*iptr, 29, 29) << 10 |
+			   GET_FIELD (*iptr, 11, 15) << 11 |
+			   GET_FIELD (*iptr, 31, 31) << 16, 17);
+
+      /* Build a plabel for an indirect call to fixup.  */
+      fixup_plabel[0] = (unsigned int) iptr + 8;  /* address of fixup */
+      fixup_plabel[1] = got[-1];		  /* ltp for fixup */
+      fixup = (fixup_t) ((int) fixup_plabel | 3);
+    }
+
+  /* Call fixup to resolve the function address.  got[1] contains the
+     link_map pointer and plabel[1] the relocation offset.  */
+  fixup ((struct link_map *) got[1], plabel[1]);
+
+  return plabel[0];
+}
diff -uNrp src.orig/gcc/config/pa/pa.h src/gcc/config/pa/pa.h
--- src.orig/gcc/config/pa/pa.h	2002-12-28 16:29:03.000000000 -0800
+++ src/gcc/config/pa/pa.h	2003-03-30 14:50:24.000000000 -0800
@@ -2033,3 +2033,7 @@ while (0)
   {"cmpib_comparison_operator", {EQ, NE, LT, LE, LEU,			\
    GT, GTU, GE}},							\
   {"movb_comparison_operator", {EQ, NE, LT, GE}},
+
+/* We need a libcall to canonicalize function pointers on TARGET_ELF32.  */
+#define CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL \
+  "__canonicalize_funcptr_for_compare"
diff -uNrp src.orig/gcc/config/pa/pa.md src/gcc/config/pa/pa.md
--- src.orig/gcc/config/pa/pa.md	2003-02-21 02:19:25.000000000 -0800
+++ src/gcc/config/pa/pa.md	2003-03-30 14:50:24.000000000 -0800
@@ -7144,9 +7144,20 @@
 	      (clobber (reg:SI 31))])
    (set (match_operand:SI 0 "register_operand" "")
 	(reg:SI 29))]
-  "! TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && !TARGET_ELF32"
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "
 {
+  if (TARGET_ELF32)
+    {
+      rtx canonicalize_funcptr_for_compare_libfunc
+        = init_one_libfunc (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL);
+
+      emit_library_call_value (canonicalize_funcptr_for_compare_libfunc,
+      			       operands[0], LCT_NORMAL, Pmode,
+			       1, operands[1], Pmode);
+      DONE;
+    }
+
   operands[2] = gen_reg_rtx (SImode);
   if (GET_CODE (operands[1]) != REG)
     {
diff -uNrp src.orig/gcc/config/pa/pa32-linux.h src/gcc/config/pa/pa32-linux.h
--- src.orig/gcc/config/pa/pa32-linux.h	2002-03-01 15:38:29.000000000 -0800
+++ src/gcc/config/pa/pa32-linux.h	2003-03-30 14:52:25.000000000 -0800
@@ -24,3 +24,17 @@ Boston, MA 02111-1307, USA.  */
 
 #undef CPP_SPEC
 #define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{mhppa:-D__hppa__} %{posix:-D_POSIX_SOURCE} -D_PA_RISC1_1"
+
+/* The libcall __canonicalize_funcptr_for_compare is referenced in
+   crtend.o and the reference isn't resolved in objects that don't
+   compare function pointers.  Thus, we need to play games to provide
+   a reference in crtbegin.o.  The rest of the define is the same
+   as that in crtstuff.c  */
+#define CTOR_LIST_BEGIN \
+  asm (".type __canonicalize_funcptr_for_compare,@function\n"		\
+"	.text\n"							\
+"	.word __canonicalize_funcptr_for_compare-$PIC_pcrel$0");	\
+  STATIC func_ptr __CTOR_LIST__[1]					\
+    __attribute__ ((__unused__, section(".ctors"),			\
+		    aligned(sizeof(func_ptr))))				\
+    = { (func_ptr) (-1) }
diff -uNrp src.orig/gcc/config/pa/t-linux src/gcc/config/pa/t-linux
--- src.orig/gcc/config/pa/t-linux	2002-05-01 02:45:08.000000000 -0700
+++ src/gcc/config/pa/t-linux	2003-03-30 14:50:24.000000000 -0800
@@ -9,8 +9,14 @@ LIB1ASMFUNCS =  _divI _divU _remI _remU 
 
 LIB1ASMSRC = pa/milli32.S
 
-# Compile crtbeginS.o and crtendS.o as PIC.
-CRTSTUFF_T_CFLAGS_S = -fPIC
-
 # Compile libgcc2.a as PIC.
 TARGET_LIBGCC2_CFLAGS = -fPIC -DELF=1 -DLINUX=1
+
+LIB2FUNCS_EXTRA=fptr.c
+
+fptr.c: $(srcdir)/config/pa/fptr.c
+	rm -f fptr.c
+	cp $(srcdir)/config/pa/fptr.c .
+
+# Compile crtbeginS.o and crtendS.o as PIC.
+CRTSTUFF_T_CFLAGS_S = -fPIC




Reply to: