public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* S/390: Exception support for TPF
@ 2004-09-22 14:14 Ulrich Weigand
  2004-09-23 18:07 ` Richard Henderson
  2004-10-18 22:05 ` Gerald Pfeifer
  0 siblings, 2 replies; 4+ messages in thread
From: Ulrich Weigand @ 2004-09-22 14:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: darcypj

Hello,

this patch adds support for C++ exception handling for the TPF OS.
The problem solved here is that on TPF, transfer of control between
different shared libraries needs to be performed using special stubs
provided by the OS.  For normal calls and returns this happens
automatically (provided for by the loader), but it needs to be done
for exceptions as well.

This patch adds an eh_return expander for TPF that ensures control
is transferred to the proper OS stub when exceptions cross shared
library boundaries.  Likewise, an MD_FALLBACK_FRAME_STATE_FOR that
allows to unwind the stack past OS stubs is provided.

The patch also tweaks some other settings related to exceptions
(don't use glibc FDE handling, always use absolute encoding);
also, the amount of space reserved for the OS in the stack frame
is increased (note that this breaks the ABI).

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux,
tested on TPF by the TPF team.

Committed to mainline.

Bye,
Ulrich


Patch provided by P.J. Darcy (darcypj@us.ibm.com).

ChangeLog:

	* 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.


Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.56
diff -c -p -r1.56 s390-protos.h
*** gcc/config/s390/s390-protos.h	22 Aug 2004 22:07:12 -0000	1.56
--- gcc/config/s390/s390-protos.h	21 Sep 2004 17:13:50 -0000
*************** extern rtx s390_gen_rtx_const_DI (int, i
*** 95,100 ****
--- 95,101 ----
  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 */
  
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.177
diff -c -p -r1.177 s390.c
*** gcc/config/s390/s390.c	20 Sep 2004 23:42:00 -0000	1.177
--- gcc/config/s390/s390.c	21 Sep 2004 17:13:50 -0000
*************** s390_conditional_register_usage (void)
*** 8017,8021 ****
--- 8017,8041 ----
      }
  }
  
+ /* 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"
Index: gcc/config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.119
diff -c -p -r1.119 s390.h
*** gcc/config/s390/s390.h	22 Aug 2004 22:07:13 -0000	1.119
--- gcc/config/s390/s390.h	21 Sep 2004 17:13:51 -0000
*************** extern const char *s390_stack_guard_stri
*** 80,85 ****
--- 80,88 ----
  
  /* Run-time target specification.  */
  
+ /* This will be overridden by OS headers.  */
+ #define TARGET_TPF 0
+ 
  /* Target CPU builtins.  */
  #define TARGET_CPU_CPP_BUILTINS()			\
    do							\
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.124
diff -c -p -r1.124 s390.md
*** gcc/config/s390/s390.md	19 Aug 2004 21:37:32 -0000	1.124
--- gcc/config/s390/s390.md	21 Sep 2004 17:13:51 -0000
***************
*** 7504,7506 ****
--- 7504,7518 ----
  			 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;
+ })
+ 
Index: gcc/config/s390/t-tpf
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/t-tpf,v
retrieving revision 1.2
diff -c -p -r1.2 t-tpf
*** gcc/config/s390/t-tpf	4 May 2004 16:09:38 -0000	1.2
--- gcc/config/s390/t-tpf	21 Sep 2004 17:13:51 -0000
*************** TARGET_LIBGCC2_CFLAGS = -fPIC
*** 7,13 ****
  # 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
--- 7,14 ----
  # the symbol versions that glibc used.
  SHLIB_MAPFILES += $(srcdir)/config/s390/libgcc-glibc.ver
  
! # 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
Index: gcc/config/s390/tpf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/tpf.h,v
retrieving revision 1.1
diff -c -p -r1.1 tpf.h
*** gcc/config/s390/tpf.h	15 Oct 2003 17:10:20 -0000	1.1
--- gcc/config/s390/tpf.h	21 Sep 2004 17:13:51 -0000
***************
*** 1,5 ****
  /* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
!    Copyright (C) 2003 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).
--- 1,5 ----
  /* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
!    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).
*************** Software Foundation, 59 Temple Place - S
*** 25,30 ****
--- 25,32 ----
  #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
*************** Software Foundation, 59 Temple Place - S
*** 50,60 ****
  
  /* TPF OS specific stack-pointer offset.  */
  #undef STACK_POINTER_OFFSET
! #define STACK_POINTER_OFFSET 		280
  
  /* When building for TPF, set a generic default target that is 64 bits.  */
  #undef TARGET_DEFAULT
! #define TARGET_DEFAULT             0x33
  
  /* TPF OS specific compiler settings.  */
  #undef TARGET_OS_CPP_BUILTINS
--- 52,71 ----
  
  /* 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
! #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
*************** Software Foundation, 59 Temple Place - S
*** 108,112 ****
--- 119,191 ----
          %{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 */
  
*** /dev/null	Mon Jul 12 10:01:50 2004
--- gcc/config/s390/tpf-eh.c	Tue Sep 21 19:10:28 2004
***************
*** 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, &currentcodeInfo);
+ 
+       /* 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, &currentcodeInfo);
+ 
+               /* 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;
+ }
+ 
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: S/390: Exception support for TPF
  2004-09-22 14:14 S/390: Exception support for TPF Ulrich Weigand
@ 2004-09-23 18:07 ` Richard Henderson
  2004-09-23 19:06   ` Ulrich Weigand
  2004-10-18 22:05 ` Gerald Pfeifer
  1 sibling, 1 reply; 4+ messages in thread
From: Richard Henderson @ 2004-09-23 18:07 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc-patches, darcypj

On Wed, Sep 22, 2004 at 03:59:06PM +0200, Ulrich Weigand wrote:
> 	(MD_FALLBACK_FRAME_STATE_FOR): Define.
> 	* config/s390/tpf-eh.c: New file.

We've rearranged MD_FALLBACK_FRAME_STATE_FOR.  See MD_UNWIND_SUPPORT.


r~

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: S/390: Exception support for TPF
  2004-09-23 18:07 ` Richard Henderson
@ 2004-09-23 19:06   ` Ulrich Weigand
  0 siblings, 0 replies; 4+ messages in thread
From: Ulrich Weigand @ 2004-09-23 19:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Ulrich Weigand, gcc-patches, darcypj

Richard Henderson wrote:
> 
> On Wed, Sep 22, 2004 at 03:59:06PM +0200, Ulrich Weigand wrote:
> > 	(MD_FALLBACK_FRAME_STATE_FOR): Define.
> > 	* config/s390/tpf-eh.c: New file.
> 
> We've rearranged MD_FALLBACK_FRAME_STATE_FOR.  See MD_UNWIND_SUPPORT.

Doh!  Thanks for catching this, I had missed that change.


PJ, with the new setup something like the appended patch should
work; could you test this on TPF against a current GCC tree?

Thanks,
Ulrich


diff -urN gcc-head/gcc/config/s390/t-tpf s390/t-tpf
--- gcc-head/gcc/config/s390/t-tpf	2004-09-21 19:56:36.000000000 +0200
+++ s390/t-tpf	2004-09-23 20:08:50.907103082 +0200
@@ -7,8 +7,7 @@
 # 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
diff -urN gcc-head/gcc/config/s390/tpf-eh.c s390/tpf-eh.c
--- gcc-head/gcc/config/s390/tpf-eh.c	2004-09-21 19:56:36.000000000 +0200
+++ s390/tpf-eh.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,183 +0,0 @@
-/* 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, &currentcodeInfo);
-
-      /* 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, &currentcodeInfo);
-
-              /* 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;
-}
-
diff -urN gcc-head/gcc/config/s390/tpf-unwind.h s390/tpf-unwind.h
--- gcc-head/gcc/config/s390/tpf-unwind.h	1970-01-01 01:00:00.000000000 +0100
+++ s390/tpf-unwind.h	2004-09-23 20:08:14.477103082 +0200
@@ -0,0 +1,255 @@
+/* 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_NO_REASON;
+
+  /* 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)
+{
+  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, &currentcodeInfo);
+
+      /* 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, &currentcodeInfo);
+
+              /* 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;
+}
+
+
diff -urN gcc-head/gcc/config/s390/tpf.h s390/tpf.h
--- gcc-head/gcc/config/s390/tpf.h	2004-09-21 19:56:36.000000000 +0200
+++ s390/tpf.h	2004-09-23 20:10:35.987103082 +0200
@@ -53,9 +53,6 @@
 /* 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
@@ -119,73 +116,7 @@
         %{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 */
 


-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: S/390: Exception support for TPF
  2004-09-22 14:14 S/390: Exception support for TPF Ulrich Weigand
  2004-09-23 18:07 ` Richard Henderson
@ 2004-10-18 22:05 ` Gerald Pfeifer
  1 sibling, 0 replies; 4+ messages in thread
From: Gerald Pfeifer @ 2004-10-18 22:05 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc-patches, darcypj

On Wed, 22 Sep 2004, Ulrich Weigand wrote:
> this patch adds support for C++ exception handling for the TPF OS.

Would you mind adding this (and the other new features) to 
gcc-4.0/changes.html?

Thanks,
Gerald

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-10-18 22:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-22 14:14 S/390: Exception support for TPF Ulrich Weigand
2004-09-23 18:07 ` Richard Henderson
2004-09-23 19:06   ` Ulrich Weigand
2004-10-18 22:05 ` Gerald Pfeifer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).