s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
2004-09-22 P.J. Darcy <darcypj@us.ibm.com> * config/s390/s390-protos.h (s390_emit_tpf_eh_return): Add prototype. * config/s390/s390.c (s390_emit_tpf_eh_return): New function. * config/s390/s390.h (TARGET_TPF): New macro. * config/s390/s390.md ("eh_return"): New expander. * config/s390/t-tpf (LIB2ADDEH): Use unwind-dw2-fde.c rather than unwind-dw2-fde-glibc.c. Add config/s390/tpf-eh.c. (LIB2ADDEHDEP): Remove unwind-dw2-fde.c. * config/s390/tpf.h (TARGET_TPF): Define to 1. (STACK_POINTER_OFFSET): Increase to 448. (TARGET_DEFAULT): Set -mtpf-trace on as default. (TPF_LOC_DIFF_OFFSET): New macro. (ASM_PREFERRED_EH_DATA_FORMAT): Redefine to always use absolute encoding. (__isPATrange): Add prototype. (MD_FALLBACK_FRAME_STATE_FOR): Define. * config/s390/tpf-eh.c: New file. From-SVN: r87857
This commit is contained in:
parent
6a97296a06
commit
4798630cb0
@ -1,3 +1,22 @@
|
||||
2004-09-22 P.J. Darcy <darcypj@us.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_emit_tpf_eh_return): Add prototype.
|
||||
* config/s390/s390.c (s390_emit_tpf_eh_return): New function.
|
||||
* config/s390/s390.h (TARGET_TPF): New macro.
|
||||
* config/s390/s390.md ("eh_return"): New expander.
|
||||
* config/s390/t-tpf (LIB2ADDEH): Use unwind-dw2-fde.c rather than
|
||||
unwind-dw2-fde-glibc.c. Add config/s390/tpf-eh.c.
|
||||
(LIB2ADDEHDEP): Remove unwind-dw2-fde.c.
|
||||
* config/s390/tpf.h (TARGET_TPF): Define to 1.
|
||||
(STACK_POINTER_OFFSET): Increase to 448.
|
||||
(TARGET_DEFAULT): Set -mtpf-trace on as default.
|
||||
(TPF_LOC_DIFF_OFFSET): New macro.
|
||||
(ASM_PREFERRED_EH_DATA_FORMAT): Redefine to always use absolute
|
||||
encoding.
|
||||
(__isPATrange): Add prototype.
|
||||
(MD_FALLBACK_FRAME_STATE_FOR): Define.
|
||||
* config/s390/tpf-eh.c: New file.
|
||||
|
||||
2004-09-22 Diego Novillo <dnovillo@redhat.com>
|
||||
|
||||
* fold-const.c (fold): Avoid non INTEGER_TYPEs when widening
|
||||
|
@ -95,6 +95,7 @@ extern rtx s390_gen_rtx_const_DI (int, int);
|
||||
extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
|
||||
extern int s390_agen_dep_p (rtx, rtx);
|
||||
extern rtx s390_load_got (void);
|
||||
extern void s390_emit_tpf_eh_return (rtx);
|
||||
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
|
@ -8017,5 +8017,25 @@ s390_conditional_register_usage (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Corresponding function to eh_return expander. */
|
||||
|
||||
static GTY(()) rtx s390_tpf_eh_return_symbol;
|
||||
void
|
||||
s390_emit_tpf_eh_return (rtx target)
|
||||
{
|
||||
rtx insn, reg;
|
||||
|
||||
if (!s390_tpf_eh_return_symbol)
|
||||
s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return");
|
||||
|
||||
reg = gen_rtx_REG (Pmode, 2);
|
||||
|
||||
emit_move_insn (reg, target);
|
||||
insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM));
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
|
||||
|
||||
emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
|
||||
}
|
||||
|
||||
#include "gt-s390.h"
|
||||
|
@ -80,6 +80,9 @@ extern const char *s390_stack_guard_string;
|
||||
|
||||
/* Run-time target specification. */
|
||||
|
||||
/* This will be overridden by OS headers. */
|
||||
#define TARGET_TPF 0
|
||||
|
||||
/* Target CPU builtins. */
|
||||
#define TARGET_CPU_CPP_BUILTINS() \
|
||||
do \
|
||||
|
@ -7504,3 +7504,15 @@
|
||||
GEN_INT (0x7fffffff)));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Instruction definition to expand eh_return macro to support
|
||||
;; swapping in special linkage return addresses.
|
||||
|
||||
(define_expand "eh_return"
|
||||
[(use (match_operand 0 "register_operand" ""))]
|
||||
"TARGET_TPF"
|
||||
{
|
||||
s390_emit_tpf_eh_return (operands[0]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
@ -7,7 +7,8 @@ TARGET_LIBGCC2_CFLAGS = -fPIC
|
||||
# the symbol versions that glibc used.
|
||||
SHLIB_MAPFILES += $(srcdir)/config/s390/libgcc-glibc.ver
|
||||
|
||||
# Use unwind-dw2-fde-glibc
|
||||
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
|
||||
$(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
|
||||
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
|
||||
# Use unwind-dw2-fde and extra tpf-eh support routines.
|
||||
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
|
||||
$(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c \
|
||||
$(srcdir)/config/s390/tpf-eh.c
|
||||
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
|
||||
|
183
gcc/config/s390/tpf-eh.c
Normal file
183
gcc/config/s390/tpf-eh.c
Normal file
@ -0,0 +1,183 @@
|
||||
/* Exception handling routines for TPF.
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Contributed by P.J. Darcy (darcypj@us.ibm.com).
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
In addition to the permissions in the GNU General Public License, the
|
||||
Free Software Foundation gives you unlimited permission to link the
|
||||
compiled version of this file into combinations with other programs,
|
||||
and to distribute those combinations without any restriction coming
|
||||
from the use of this file. (The General Public License restrictions
|
||||
do apply in other respects; for example, they cover modification of
|
||||
the file, and distribution when not linked into a combined
|
||||
executable.)
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#define __USE_GNU 1
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#undef __USE_GNU
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
#define CURRENT_STACK_PTR() \
|
||||
({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; })
|
||||
|
||||
#define PREVIOUS_STACK_PTR() \
|
||||
((unsigned long int *)(*(CURRENT_STACK_PTR())))
|
||||
|
||||
#define RA_OFFSET_FROM_START_OF_STACK_FRAME 112
|
||||
#define CURRENT_STACK_PTR_OFFSET 120
|
||||
#define TPFRA_OFFSET_FROM_START_OF_STACK_FRAME 168
|
||||
#define MIN_PATRANGE 0x10000
|
||||
#define MAX_PATRANGE 0x800000
|
||||
#define INVALID_RETURN 0
|
||||
|
||||
/* Function Name: __isPATrange
|
||||
Parameters passed into it: address to check
|
||||
Return Value: A 1 if address is in pat code "range", 0 if not
|
||||
Description: This function simply checks to see if the address
|
||||
passed to it is in the CP pat code range. */
|
||||
|
||||
unsigned int __isPATrange(void *addr)
|
||||
{
|
||||
if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function Name: __tpf_eh_return
|
||||
Parameters passed into it: Destination address to jump to.
|
||||
Return Value: Converted Destination address if a Pat Stub exists.
|
||||
Description: This function swaps the uwinding return address
|
||||
with the cp stub code. The original target return address is
|
||||
then stored into the tpf return address field. The cp stub
|
||||
code is searched for by climbing back up the stack and
|
||||
comparing the tpf stored return address object address to
|
||||
that of the targets object address. */
|
||||
|
||||
void *__tpf_eh_return (void *target)
|
||||
{
|
||||
Dl_info targetcodeInfo, currentcodeInfo;
|
||||
int retval;
|
||||
void *current, *stackptr;
|
||||
unsigned long int shifter;
|
||||
|
||||
/* Get code info for target return's address. */
|
||||
retval = dladdr (target, &targetcodeInfo);
|
||||
|
||||
/* Get the return address of the stack frame to be replaced by
|
||||
the exception unwinder. So that the __cxa_throw return is
|
||||
replaced by the target return. */
|
||||
current = (void *) *((unsigned long int *)
|
||||
((*((unsigned long int *)*(PREVIOUS_STACK_PTR())))
|
||||
+ RA_OFFSET_FROM_START_OF_STACK_FRAME));
|
||||
|
||||
/* Ensure the code info is valid (for target). */
|
||||
if (retval != INVALID_RETURN)
|
||||
{
|
||||
/* Now check to see if the current RA is a PAT
|
||||
stub return address. */
|
||||
if ( __isPATrange(current))
|
||||
{
|
||||
/* It was! Then go into the TPF private stack area and fetch
|
||||
the real address. */
|
||||
current = (void *) *((unsigned long int *)
|
||||
((unsigned long int)*((unsigned long int *)
|
||||
*(PREVIOUS_STACK_PTR()))
|
||||
+TPFRA_OFFSET_FROM_START_OF_STACK_FRAME));
|
||||
}
|
||||
|
||||
/* Get code info for current return address. */
|
||||
retval = dladdr (current, ¤tcodeInfo);
|
||||
|
||||
/* Ensure the code info is valid (for current frame). */
|
||||
if (retval != INVALID_RETURN)
|
||||
{
|
||||
/* Get the stack pointer of the stack frame to be replaced by
|
||||
the exception unwinder. So that we can begin our climb
|
||||
there. */
|
||||
stackptr = (void *) (*((unsigned long int *)
|
||||
(*((unsigned long int *)(*(PREVIOUS_STACK_PTR()))))));
|
||||
|
||||
/* Begin looping through stack frames. Stop if invalid
|
||||
code information is retrieved or if a match between the
|
||||
current stack frame iteration shared object's address
|
||||
matches that of the target, calculated above. */
|
||||
while (retval != INVALID_RETURN
|
||||
&& targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase)
|
||||
{
|
||||
/* Get return address based on our stackptr iterator. */
|
||||
current = (void *) *((unsigned long int *)
|
||||
(stackptr+RA_OFFSET_FROM_START_OF_STACK_FRAME));
|
||||
|
||||
/* Is it a Pat Stub? */
|
||||
if (__isPATrange (current))
|
||||
{
|
||||
/* Yes it was, get real return address
|
||||
in TPF stack area. */
|
||||
current = (void *) *((unsigned long int *)
|
||||
(stackptr+TPFRA_OFFSET_FROM_START_OF_STACK_FRAME));
|
||||
}
|
||||
|
||||
/* Get codeinfo on RA so that we can figure out
|
||||
the module address. */
|
||||
retval = dladdr (current, ¤tcodeInfo);
|
||||
|
||||
/* Check that codeinfo for current stack frame is valid.
|
||||
Then compare the module address of current stack frame
|
||||
to target stack frame to determine if we have the pat
|
||||
stub address we want. */
|
||||
if (retval != INVALID_RETURN
|
||||
&& targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase)
|
||||
{
|
||||
/* Yes! They are in the same module. Now store the
|
||||
real target address into the TPF stack area of
|
||||
the target frame we are jumping to. */
|
||||
*((unsigned long int *)(*((unsigned long int *)
|
||||
(*PREVIOUS_STACK_PTR() + CURRENT_STACK_PTR_OFFSET))
|
||||
+ TPFRA_OFFSET_FROM_START_OF_STACK_FRAME))
|
||||
= (unsigned long int) target;
|
||||
|
||||
/* Before returning the desired pat stub address to
|
||||
the exception handling unwinder so that it can
|
||||
actually do the "leap" shift out the low order
|
||||
bit designated to determine if we are in 64BIT mode.
|
||||
This is nececcary for CTOA stubs.
|
||||
Otherwise we leap one byte past where we want to
|
||||
go to in the TPF pat stub linkage code. */
|
||||
shifter = *((unsigned long int *)
|
||||
(stackptr + RA_OFFSET_FROM_START_OF_STACK_FRAME));
|
||||
|
||||
shifter &= ~1ul;
|
||||
|
||||
return (void *) shifter;
|
||||
}
|
||||
|
||||
/* Desired module pat stub not found ...
|
||||
Bump stack frame iterator. */
|
||||
stackptr = (void *) *(unsigned long int *) stackptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No pat stub found, could be a problem? Simply return unmodified
|
||||
target address. */
|
||||
return target;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by P.J. Darcy (darcypj@us.ibm.com),
|
||||
Hartmut Penner (hpenner@de.ibm.com), and
|
||||
Ulrich Weigand (uweigand@de.ibm.com).
|
||||
@ -25,6 +25,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#define _TPF_H
|
||||
|
||||
/* TPF wants the following macros defined/undefined as follows. */
|
||||
#undef TARGET_TPF
|
||||
#define TARGET_TPF 1
|
||||
#undef ASM_APP_ON
|
||||
#define ASM_APP_ON "#APP\n"
|
||||
#undef ASM_APP_OFF
|
||||
@ -50,11 +52,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
/* TPF OS specific stack-pointer offset. */
|
||||
#undef STACK_POINTER_OFFSET
|
||||
#define STACK_POINTER_OFFSET 280
|
||||
#define STACK_POINTER_OFFSET 448
|
||||
/* TPF stack placeholder offset. */
|
||||
#undef TPF_LOC_DIFF_OFFSET
|
||||
#define TPF_LOC_DIFF_OFFSET 168
|
||||
|
||||
/* When building for TPF, set a generic default target that is 64 bits. */
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0x33
|
||||
#define TARGET_DEFAULT 0xb3
|
||||
|
||||
/* Exception handling. */
|
||||
|
||||
/* Select a format to encode pointers in exception handling data. */
|
||||
#undef ASM_PREFERRED_EH_DATA_FORMAT
|
||||
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) DW_EH_PE_absptr
|
||||
|
||||
/* TPF OS specific compiler settings. */
|
||||
#undef TARGET_OS_CPP_BUILTINS
|
||||
@ -108,5 +119,73 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{!dynamic-linker:-dynamic-linker /lib/ld64.so}}}"
|
||||
|
||||
extern unsigned int __isPATrange (void *);
|
||||
|
||||
/* Exceptions macro defined for TPF so that functions without
|
||||
dwarf frame information can be used with exceptions. */
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do \
|
||||
{ \
|
||||
unsigned long int regs_; \
|
||||
unsigned long int new_cfa_; \
|
||||
int i_; \
|
||||
\
|
||||
if ((CONTEXT)->cfa == NULL) \
|
||||
goto SUCCESS; \
|
||||
\
|
||||
/* Are we going through special linkage code? */ \
|
||||
if (__isPATrange((CONTEXT)->ra)) \
|
||||
{ \
|
||||
/* No stack frame. */ \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 15; \
|
||||
(FS)->cfa_offset = STACK_POINTER_OFFSET; \
|
||||
\
|
||||
/* All registers remain unchanged ... */ \
|
||||
for (i_ = 0; i_ < 32; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_REG; \
|
||||
(FS)->regs.reg[i_].loc.reg = i_; \
|
||||
} \
|
||||
\
|
||||
/* ... except for %r14, which is stored at CFA-112 \
|
||||
and used as return address. */ \
|
||||
(FS)->regs.reg[14].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[14].loc.offset = \
|
||||
TPF_LOC_DIFF_OFFSET - STACK_POINTER_OFFSET; \
|
||||
(FS)->retaddr_column = 14; \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
regs_ = *((unsigned long int *) \
|
||||
(((unsigned long int) (CONTEXT)->cfa) - STACK_POINTER_OFFSET)); \
|
||||
new_cfa_ = regs_ + STACK_POINTER_OFFSET; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 15; \
|
||||
(FS)->cfa_offset = new_cfa_ - \
|
||||
(unsigned long int) (CONTEXT)->cfa + STACK_POINTER_OFFSET; \
|
||||
\
|
||||
for (i_ = 0; i_ < 16; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset = \
|
||||
(regs_+(i_*8)) - new_cfa_; \
|
||||
} \
|
||||
\
|
||||
for (i_ = 0; i_ < 4; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[16+i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[16+i_].loc.offset = \
|
||||
(regs_+(16*8)+(i_*8)) - new_cfa_; \
|
||||
} \
|
||||
\
|
||||
(FS)->retaddr_column = 14; \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif /* ! _TPF_H */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user