fptr.c (__canonicalize_funcptr_for_compare): New file and function.
* 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. From-SVN: r59842
This commit is contained in:
parent
16823694d5
commit
9e1ab8c1a5
@ -1,3 +1,13 @@
|
||||
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-04 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* combine.c (combine_simplify_rtx): Add new canonicalizations.
|
||||
|
127
gcc/config/pa/fptr.c
Normal file
127
gcc/config/pa/fptr.c
Normal file
@ -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 is special. It 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 || !((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];
|
||||
}
|
@ -7277,9 +7277,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)
|
||||
{
|
||||
|
@ -29,3 +29,22 @@ Boston, MA 02111-1307, USA. */
|
||||
subspace stubs, so we allow sibcalls to all functions. */
|
||||
#undef FUNCTION_OK_FOR_SIBCALL
|
||||
#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
|
||||
|
||||
/* We need a libcall to canonicalize function pointers because of
|
||||
the way function pointers are handled when doing lazy linking. */
|
||||
#define CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL \
|
||||
"__canonicalize_funcptr_for_compare"
|
||||
|
||||
/* 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) }
|
||||
|
@ -5,8 +5,14 @@
|
||||
LIB1ASMFUNCS = _divI _divU _remI _remU _div_const _mulI _dyncall
|
||||
LIB1ASMSRC = pa/milli64.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
|
||||
|
Loading…
Reference in New Issue
Block a user