+2004-10-02 P.J. Darcy <darcypj@us.ibm.com>
+
+ * config/s390/t-tpf (LIB2ADDEH): Remove tpf-eh.c.
+ * config/s390/tpf-eh.c: Remove file.
+ * config/s390/tpf-unwind.h: New file.
+ * config/s390/tpf.h (MD_FALLBACK_FRAME_STATE_FOR): Remove.
+ (MD_UNWIND_SUPPORT): Define.
+
2004-10-02 Joseph S. Myers <jsm@polyomino.org.uk>
* c-typeck.c (warn_for_assignment): Don't permit argnum == 0.
# the symbol versions that glibc used.
SHLIB_MAPFILES += $(srcdir)/config/s390/libgcc-glibc.ver
-# Use unwind-dw2-fde and extra tpf-eh support routines.
+# Use unwind-dw2-fde.
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
+ $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
+++ /dev/null
-/* 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 unwinding 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 necessary 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;
-}
-
--- /dev/null
+/* DWARF2 EH unwinding support for TPF OS.
+ 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
+
+/* 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. */
+
+#define MIN_PATRANGE 0x10000
+#define MAX_PATRANGE 0x800000
+
+static inline unsigned int
+__isPATrange (void *addr)
+{
+ if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
+ return 1;
+ else
+ return 0;
+}
+
+/* TPF stack placeholder offset. */
+#define TPF_LOC_DIFF_OFFSET 168
+
+/* Exceptions macro defined for TPF so that functions without
+ dwarf frame information can be used with exceptions. */
+#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
+
+static _Unwind_Reason_Code
+s390_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned long int regs;
+ unsigned long int new_cfa;
+ int i;
+
+ if (context->cfa == NULL)
+ return _URC_END_OF_STACK;
+
+ /* 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;
+
+ return _URC_NO_REASON;
+ }
+
+ 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;
+
+ return _URC_NO_REASON;
+}
+
+/* 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. */
+
+#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 INVALID_RETURN 0
+
+void * __tpf_eh_return (void *target);
+
+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;
+}
+
+
/* TPF OS specific stack-pointer offset. */
#undef STACK_POINTER_OFFSET
#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
%{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)
+#define MD_UNWIND_SUPPORT "config/s390/tpf-unwind.h"
#endif /* ! _TPF_H */