From b749b5ec58acd1da57f2afabac732027e8a88755 Mon Sep 17 00:00:00 2001 From: Jim Johnston Date: Fri, 3 Apr 2020 08:46:11 +0200 Subject: 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 * 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(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index c5ff4f6..7548e34 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,17 @@ +2020-04-03 Jim Johnston + + * 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 PR target/94220 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; } - -- cgit v1.1