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.
This commit is contained in:
parent
535ce76acb
commit
b749b5ec58
@ -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
|
||||
|
@ -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));
|
||||
/* Get return address based on our stackptr iterator. */
|
||||
current = (void *) *(unsigned long *) (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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user