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 <[EMAIL PROTECTED]> * 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 <[EMAIL PROTECTED]> * 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 ([EMAIL PROTECTED]). + +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