s390.c (s390_emit_tpf_eh_return): Pass original return address as second parameter...
authorUlrich Weigand <uweigand@gcc.gnu.org>
Wed, 30 Jul 2014 16:26:15 +0000 (16:26 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Wed, 30 Jul 2014 16:26:15 +0000 (16:26 +0000)
gcc/

2014-07-30  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

* config/s390/s390.c (s390_emit_tpf_eh_return): Pass original return
address as second parameter to __tpf_eh_return routine.

libgcc/

2014-07-30  J. D. Johnston  <jjohnst@us.ibm.com>

* config/s390/tpf-unwind.h: Include <stdbool.h>.
(__tpf_eh_return): Add original return address as second parameter.
Handle cases where unwinder routines were called directly, instead
of from within the C++ library.

From-SVN: r213305

gcc/ChangeLog
gcc/config/s390/s390.c
libgcc/ChangeLog
libgcc/config/s390/tpf-unwind.h

index 1bb3d3360769602548755e8b34db7f9f83ec7a81..04b0d3cf1873e2e4441bb9401cf2df56cb7dfc3a 100644 (file)
@@ -1,3 +1,8 @@
+2014-07-30  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * config/s390/s390.c (s390_emit_tpf_eh_return): Pass original return
+       address as second parameter to __tpf_eh_return routine.
+
 2014-07-30  Jiong Wang  <jiong.wang@arm.com>
 
        * config/arm/arm.c (arm_get_frame_offsets): Adjust condition for
index bc6206e779fcf668fccca10d1172a1ea4f8f08c2..03b85ff2ee1dbe66592afd5b3a9c7a378ecdc9bd 100644 (file)
@@ -10850,17 +10850,20 @@ static GTY(()) rtx s390_tpf_eh_return_symbol;
 void
 s390_emit_tpf_eh_return (rtx target)
 {
-  rtx insn, reg;
+  rtx insn, reg, orig_ra;
 
   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);
+  orig_ra = gen_rtx_REG (Pmode, 3);
 
   emit_move_insn (reg, target);
+  emit_move_insn (orig_ra, get_hard_reg_initial_val (Pmode, RETURN_REGNUM));
   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);
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), orig_ra);
 
   emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
 }
index 88fb09f25cc328f734acc6a4c359428e6d8018e3..4795414d166a565dbd9cc12fc520569bc6c5bb90 100644 (file)
@@ -1,3 +1,10 @@
+2014-07-30  J. D. Johnston  <jjohnst@us.ibm.com>
+
+       * config/s390/tpf-unwind.h: Include <stdbool.h>.
+       (__tpf_eh_return): Add original return address as second parameter.
+       Handle cases where unwinder routines were called directly, instead
+       of from within the C++ library.
+
 2014-07-29  Nathan Sidwell  <nathan@acm.org>
 
        * libgcov.h: Move renaming of entry points to lib gcov specific
index 5fa177b5078e7d9b35939c117be270a8675b20dc..efffda5d434e2fcad653ad1a52ae47fe371be880 100644 (file)
@@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
 #include <dlfcn.h>
+#include <stdbool.h>
 
 /* Function Name: __isPATrange
    Parameters passed into it:  address to check
@@ -139,29 +140,38 @@ s390_fallback_frame_state (struct _Unwind_Context *context,
 #define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET
 #define INVALID_RETURN 0
 
-void * __tpf_eh_return (void *target);
+void * __tpf_eh_return (void *target, void *origRA);
 
 void *
-__tpf_eh_return (void *target)
+__tpf_eh_return (void *target, void *origRA)
 {
   Dl_info targetcodeInfo, currentcodeInfo;
   int retval;
   void *current, *stackptr, *destination_frame;
-  unsigned long int shifter, is_a_stub;
+  unsigned long int shifter;
+  bool is_a_stub, frameDepth2, firstIteration;
 
-  is_a_stub = 0;
+  is_a_stub = false;
+  frameDepth2 = false;
+  firstIteration = true;
 
   /* Get code info for target return's address.  */
   retval = dladdr (target, &targetcodeInfo);
 
+  /* Check if original RA is a Pat stub.  If so set flag.  */
+  if (__isPATrange (origRA))
+    frameDepth2 = true;
+
   /* Ensure the code info is valid (for target).  */
   if (retval != INVALID_RETURN)
     {
-
-      /* Get the stack pointer of the stack frame to be modified by
-         the exception unwinder.  So that we can begin our climb
-         there.  */
-      stackptr = (void *) *((unsigned long int *) (*(PREVIOUS_STACK_PTR())));
+      /* Get the stack pointer of the first stack frame beyond the
+         unwinder or if exists the calling C++ runtime function (e.g.,
+         __cxa_throw).  */
+      if (!frameDepth2)
+        stackptr = (void *) *((unsigned long int *) (*(PREVIOUS_STACK_PTR())));
+      else
+        stackptr = (void *) *(PREVIOUS_STACK_PTR());
 
       /* Begin looping through stack frames.  Stop if invalid
          code information is retrieved or if a match between the
@@ -169,18 +179,26 @@ __tpf_eh_return (void *target)
          matches that of the target, calculated above.  */
       do
         {
-          /* Get return address based on our stackptr iterator.  */
-          current = (void *) *((unsigned long int *)
-                      (stackptr+RA_OFFSET));
-
-          /* Is it a Pat Stub?  */
-          if (__isPATrange (current))
+          if (!frameDepth2 || (frameDepth2 && !firstIteration))
+            {
+              /* Get return address based on our stackptr iterator.  */
+              current = (void *) *((unsigned long int *)
+                                   (stackptr + RA_OFFSET));
+
+              /* 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))
+                  is_a_stub = true;
+                }
+            }
+          else
             {
-              /* Yes it was, get real return address
-                 in TPF stack area.  */
               current = (void *) *((unsigned long int *)
-                          (stackptr+TPFRA_OFFSET));
-              is_a_stub = 1;
+                                   (stackptr + TPFRA_OFFSET));
+              is_a_stub = true;
             }
 
           /* Get codeinfo on RA so that we can figure out
@@ -219,8 +237,10 @@ __tpf_eh_return (void *target)
                   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));
+               if (!frameDepth2 || (frameDepth2 && !firstIteration))
+                 shifter = *((unsigned long int *) (stackptr + RA_OFFSET));
+               else
+                 shifter = (unsigned long int) origRA;
 
                shifter &= ~1ul;
 
@@ -239,7 +259,8 @@ __tpf_eh_return (void *target)
              Bump stack frame iterator.  */
           stackptr = (void *) *(unsigned long int *) stackptr;
 
-          is_a_stub = 0;
+          is_a_stub = false;
+          firstIteration = false;
 
         }  while (stackptr && retval != INVALID_RETURN
                 && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase);