[Committed] S/390 zTPF: Handle skip trace addresses when unwinding

Message ID 20200403064733.12432-1-krebbel@linux.ibm.com
State New
Headers show
Series
  • [Committed] S/390 zTPF: Handle skip trace addresses when unwinding
Related show

Commit Message

Richard Biener via Gcc-patches April 3, 2020, 6:47 a.m.
From: Jim Johnston <jjohnst@us.ibm.com>


Check for and handle new skip trace addresses when unwinding on zTPF.

libgcc/ChangeLog:

2020-04-03  Jim Johnston  <jjohnst@us.ibm.com>

	* config/s390/tpf-unwind.h (MIN_PATRANGE, MAX_PATRANGE)
	(TPFRA_OFFSET): Macros removed.
	(CP_CNF, cinfc_fast, CINFC_CMRESET, CINTFC_CMCENBKST)
	(CINTFC_CMCENBKED, ICST_CRET, ICST_SRET, LOWCORE_PAGE3_ADDR)
	(PG3_SKIPPING_OFFSET): New macros.
	(__isPATrange): Use cinfc_fast for the check.
	(__isSkipResetAddr): New function.
	(s390_fallback_frame_state): Check for skip trace addresses. Use
	either ICST_CRET or ICST_SRET to calculate return address
	location.
	(__tpf_eh_return): Handle skip trace addresses.
---
 libgcc/ChangeLog                |  14 ++++
 libgcc/config/s390/tpf-unwind.h | 132 ++++++++++++++++++--------------
 2 files changed, 89 insertions(+), 57 deletions(-)

-- 
2.17.1

Patch

diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index c5ff4f63c7d..7548e347640 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,17 @@ 
+2020-04-03  Jim Johnston  <jjohnst@us.ibm.com>
+
+	* config/s390/tpf-unwind.h (MIN_PATRANGE, MAX_PATRANGE)
+	(TPFRA_OFFSET): Macros removed.
+	(CP_CNF, cinfc_fast, CINFC_CMRESET, CINTFC_CMCENBKST)
+	(CINTFC_CMCENBKED, ICST_CRET, ICST_SRET, LOWCORE_PAGE3_ADDR)
+	(PG3_SKIPPING_OFFSET): New macros.
+	(__isPATrange): Use cinfc_fast for the check.
+	(__isSkipResetAddr): New function.
+	(s390_fallback_frame_state): Check for skip trace addresses. Use
+	either ICST_CRET or ICST_SRET to calculate return address
+	location.
+	(__tpf_eh_return): Handle skip trace addresses.
+
 2020-03-26  Richard Earnshaw  <rearnsha@arm.com>
 
 	PR target/94220
diff --git a/libgcc/config/s390/tpf-unwind.h b/libgcc/config/s390/tpf-unwind.h
index 2bd5493bb71..fadc06b5e59 100644
--- a/libgcc/config/s390/tpf-unwind.h
+++ b/libgcc/config/s390/tpf-unwind.h
@@ -32,20 +32,29 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    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
+#define CP_CNF  0x000000000000c18u /* location of BSS CINFC pointer */
+#define cinfc_fast(TAG) (void *) \
+  *((unsigned long *) *(unsigned long *) (CP_CNF) + (TAG))
+#define CINFC_CMRESET 187
+#define CINTFC_CMCENBKST 431
+#define CINTFC_CMCENBKED 432
 
 static inline unsigned int
 __isPATrange (void *addr)
 {
-  if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
-    return 1;
-  else
-    return 0;
+  return !!(addr > cinfc_fast (CINTFC_CMCENBKST)
+	    && addr < cinfc_fast (CINTFC_CMCENBKED));
+}
+
+static inline unsigned int
+__isSkipResetAddr (void *addr)
+{
+  return !!(addr == cinfc_fast (CINFC_CMRESET));
 }
 
 /* TPF return address offset from start of stack frame.  */
-#define TPFRA_OFFSET 168
+#define ICST_CRET 168
+#define ICST_SRET 320
 
 /* Exceptions macro defined for TPF so that functions without
    dwarf frame information can be used with exceptions.  */
@@ -63,12 +72,12 @@  s390_fallback_frame_state (struct _Unwind_Context *context,
         (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
 
   /* Are we going through special linkage code?  */
-  if (__isPATrange (context->ra))
+  if (__isPATrange (context->ra) || __isSkipResetAddr (context->ra))
     {
 
       /* Our return register isn't zero for end of stack, so
          check backward stackpointer to see if it is zero.  */
-      if (regs == NULL)
+      if (regs == 0)
          return _URC_END_OF_STACK;
 
       /* No stack frame.  */
@@ -83,11 +92,18 @@  s390_fallback_frame_state (struct _Unwind_Context *context,
 	  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 = TPFRA_OFFSET - STACK_POINTER_OFFSET;
-      fs->retaddr_column = 14;
+      /* ... except for %r14, which is stored at CFA+offset where offset
+	 is displacment of ICST_CRET or ICST_SRET from CFA */
+      if ( __isPATrange(context->ra) )  {
+	   fs->regs.reg[14].how = REG_SAVED_OFFSET;
+	   fs->regs.reg[14].loc.offset = ICST_CRET - STACK_POINTER_OFFSET;
+	   fs->retaddr_column = 14;
+      }  else  {
+	   fs->regs.reg[14].how = REG_SAVED_OFFSET;
+	   fs->regs.reg[14].loc.offset = ICST_SRET - STACK_POINTER_OFFSET;
+	   fs->retaddr_column = 14;
+
+      }
 
       return _URC_NO_REASON;
     }
@@ -140,6 +156,9 @@  s390_fallback_frame_state (struct _Unwind_Context *context,
 #define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET
 #define INVALID_RETURN 0
 
+#define LOWCORE_PAGE3_ADDR 4032
+#define PG3_SKIPPING_OFFSET 18
+
 void * __tpf_eh_return (void *target, void *origRA);
 
 void *
@@ -148,30 +167,29 @@  __tpf_eh_return (void *target, void *origRA)
   Dl_info targetcodeInfo, currentcodeInfo;
   int retval;
   void *current, *stackptr, *destination_frame;
+  unsigned char *skipFlagAddress;
   unsigned long int shifter;
-  bool is_a_stub, frameDepth2, firstIteration;
+  bool is_a_stub;
 
   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 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 climbing stack searching for target address. */
+      stackptr = (void *) *(CURRENT_STACK_PTR());
+
+      /* Get return address based on our stackptr. */
+      current = (void *) *(unsigned long *) (stackptr + RA_OFFSET);
+
+      /* Is current return address our initiating exception stack
+	 frame? If not, climb the stack one more frame. */
+      if (current != origRA)  {
+	   stackptr = (void *) *(unsigned long *) stackptr;
+      }
 
       /* Begin looping through stack frames.  Stop if invalid
          code information is retrieved or if a match between the
@@ -179,27 +197,19 @@  __tpf_eh_return (void *target, void *origRA)
          matches that of the target, calculated above.  */
       do
         {
-          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
-            {
-              current = (void *) *((unsigned long int *)
-                                   (stackptr + TPFRA_OFFSET));
-              is_a_stub = true;
-            }
+	  /* Get return address based on our stackptr iterator.  */
+	  current = (void *) *(unsigned long *) (stackptr + RA_OFFSET);
+
+	  /* Is it a Pat Stub?  */
+	  if (__isPATrange (current)
+	      || (__isSkipResetAddr (current)
+		  && __isPATrange ((void *) *(unsigned long *) (stackptr
+								+ ICST_SRET))))
+	    {
+	      /* Yes it was, get real return address in TPF stack area.  */
+	      current = (void *) *(unsigned long *) (stackptr + ICST_CRET);
+	      is_a_stub = true;
+	    }
 
           /* Get codeinfo on RA so that we can figure out
              the module address.  */
@@ -227,8 +237,8 @@  __tpf_eh_return (void *target, void *origRA)
                /* Now overlay the
                   real target address into the TPF stack area of
                   the target frame we are jumping to.  */
-               *((unsigned long int *) (destination_frame +
-                   TPFRA_OFFSET)) = (unsigned long int) target;
+	       *(unsigned long *) (destination_frame + ICST_CRET) =
+		 (unsigned long) target;
 
                /* Before returning the desired pat stub address to
                   the exception handling unwinder so that it can
@@ -237,10 +247,7 @@  __tpf_eh_return (void *target, void *origRA)
                   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.  */
-               if (!frameDepth2 || (frameDepth2 && !firstIteration))
-                 shifter = *((unsigned long int *) (stackptr + RA_OFFSET));
-               else
-                 shifter = (unsigned long int) origRA;
+	       shifter = *(unsigned long *) (stackptr + RA_OFFSET);
 
                shifter &= ~1ul;
 
@@ -252,6 +259,13 @@  __tpf_eh_return (void *target, void *origRA)
                   in linkage.  */
                shifter = shifter - 4;
 
+	       /* Reset the Function Trace Skipping Switch to re-enable */
+	       /* recording Trace entries if it was turned off. */
+	       skipFlagAddress =
+		 (unsigned char *) *(unsigned long *) LOWCORE_PAGE3_ADDR;
+	       skipFlagAddress += PG3_SKIPPING_OFFSET;
+	       *skipFlagAddress = '\x00';
+
                return (void *) shifter;
              }
 
@@ -260,14 +274,18 @@  __tpf_eh_return (void *target, void *origRA)
           stackptr = (void *) *(unsigned long int *) stackptr;
 
           is_a_stub = false;
-          firstIteration = false;
 
         }  while (stackptr && retval != INVALID_RETURN
                 && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase);
     }
 
+  /* Reset the Function Trace Skipping Switch to re-enable */
+  /* recording Trace entries if it was turned off. */
+  skipFlagAddress = (unsigned char *) *(unsigned long *) LOWCORE_PAGE3_ADDR;
+  skipFlagAddress += PG3_SKIPPING_OFFSET;
+  *skipFlagAddress = '\x00';
+
   /* No pat stub found, could be a problem?  Simply return unmodified
      target address.  */
   return target;
 }
-