aboutsummaryrefslogtreecommitdiff
path: root/libgcc/config/s390
diff options
context:
space:
mode:
authorJim Johnston <jjohnst@us.ibm.com>2020-04-03 08:46:11 +0200
committerAndreas Krebbel <krebbel@linux.ibm.com>2020-04-03 08:46:11 +0200
commitb749b5ec58acd1da57f2afabac732027e8a88755 (patch)
tree935bd6a0185d65b54e1175ba2d5bb18d90f156ff /libgcc/config/s390
parent535ce76acbeb0791da0c2d707b543b54a9e0668f (diff)
downloadgcc-b749b5ec58acd1da57f2afabac732027e8a88755.zip
gcc-b749b5ec58acd1da57f2afabac732027e8a88755.tar.gz
gcc-b749b5ec58acd1da57f2afabac732027e8a88755.tar.bz2
S/390 zTPF: Handle skip trace addresses when unwinding
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.
Diffstat (limited to 'libgcc/config/s390')
-rw-r--r--libgcc/config/s390/tpf-unwind.h132
1 files changed, 75 insertions, 57 deletions
diff --git a/libgcc/config/s390/tpf-unwind.h b/libgcc/config/s390/tpf-unwind.h
index 2bd5493..fadc06b 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;
}
-