diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/config/s390/tpf-unwind.h | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'gcc/config/s390/tpf-unwind.h')
-rw-r--r-- | gcc/config/s390/tpf-unwind.h | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/gcc/config/s390/tpf-unwind.h b/gcc/config/s390/tpf-unwind.h new file mode 100644 index 000000000..33fd5f5c8 --- /dev/null +++ b/gcc/config/s390/tpf-unwind.h @@ -0,0 +1,252 @@ +/* DWARF2 EH unwinding support for TPF OS. + Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. + Contributed by P.J. Darcy (darcypj@us.ibm.com). + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> + +/* Function Name: __isPATrange + Parameters passed into it: address to check + Return Value: A 1 if address is in pat code "range", 0 if not + 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 + +static inline unsigned int +__isPATrange (void *addr) +{ + if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE) + return 1; + else + return 0; +} + +/* TPF return address offset from start of stack frame. */ +#define TPFRA_OFFSET 168 + +/* Exceptions macro defined for TPF so that functions without + dwarf frame information can be used with exceptions. */ +#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state + +static _Unwind_Reason_Code +s390_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned long int regs; + unsigned long int new_cfa; + int i; + + regs = *((unsigned long int *) + (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET)); + + /* Are we going through special linkage code? */ + if (__isPATrange (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) + return _URC_END_OF_STACK; + + /* No stack frame. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = STACK_POINTER_OFFSET; + + /* All registers remain unchanged ... */ + for (i = 0; i < 32; i++) + { + fs->regs.reg[i].how = REG_SAVED_REG; + 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; + + return _URC_NO_REASON; + } + + regs = *((unsigned long int *) + (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET)); + new_cfa = regs + STACK_POINTER_OFFSET; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = new_cfa - + (unsigned long int) context->cfa + STACK_POINTER_OFFSET; + + for (i = 0; i < 16; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = regs + i*8 - new_cfa; + } + + for (i = 0; i < 4; i++) + { + fs->regs.reg[16 + i].how = REG_SAVED_OFFSET; + fs->regs.reg[16 + i].loc.offset = regs + 16*8 + i*8 - new_cfa; + } + + fs->retaddr_column = 14; + + return _URC_NO_REASON; +} + +/* Function Name: __tpf_eh_return + Parameters passed into it: Destination address to jump to. + Return Value: Converted Destination address if a Pat Stub exists. + Description: This function swaps the unwinding return address + with the cp stub code. The original target return address is + then stored into the tpf return address field. The cp stub + code is searched for by climbing back up the stack and + comparing the tpf stored return address object address to + that of the targets object address. */ + +#define CURRENT_STACK_PTR() \ + ({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; }) + +#define PREVIOUS_STACK_PTR() \ + ((unsigned long int *)(*(CURRENT_STACK_PTR()))) + +#define RA_OFFSET 112 +#define R15_OFFSET 120 +#define TPFAREA_OFFSET 160 +#define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET +#define INVALID_RETURN 0 + +void * __tpf_eh_return (void *target); + +void * +__tpf_eh_return (void *target) +{ + Dl_info targetcodeInfo, currentcodeInfo; + int retval; + void *current, *stackptr, *destination_frame; + unsigned long int shifter, is_a_stub; + + is_a_stub = 0; + + /* Get code info for target return's address. */ + retval = dladdr (target, &targetcodeInfo); + + /* 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()))); + + /* Begin looping through stack frames. Stop if invalid + code information is retrieved or if a match between the + current stack frame iteration shared object's address + 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)) + { + /* Yes it was, get real return address + in TPF stack area. */ + current = (void *) *((unsigned long int *) + (stackptr+TPFRA_OFFSET)); + is_a_stub = 1; + } + + /* Get codeinfo on RA so that we can figure out + the module address. */ + retval = dladdr (current, ¤tcodeInfo); + + /* Check that codeinfo for current stack frame is valid. + Then compare the module address of current stack frame + to target stack frame to determine if we have the pat + stub address we want. Also ensure we are dealing + with a module crossing, stub return address. */ + if (is_a_stub && retval != INVALID_RETURN + && targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase) + { + /* Yes! They are in the same module. + Force copy of TPF private stack area to + destination stack frame TPF private area. */ + destination_frame = (void *) *((unsigned long int *) + (*PREVIOUS_STACK_PTR() + R15_OFFSET)); + + /* Copy TPF linkage area from current frame to + destination frame. */ + memcpy((void *) (destination_frame + TPFAREA_OFFSET), + (void *) (stackptr + TPFAREA_OFFSET), TPFAREA_SIZE); + + /* 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; + + /* Before returning the desired pat stub address to + the exception handling unwinder so that it can + actually do the "leap" shift out the low order + bit designated to determine if we are in 64BIT mode. + 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)); + + shifter &= ~1ul; + + /* Store Pat Stub Address in destination Stack Frame. */ + *((unsigned long int *) (destination_frame + + RA_OFFSET)) = shifter; + + /* Re-adjust pat stub address to go to correct place + in linkage. */ + shifter = shifter - 4; + + return (void *) shifter; + } + + /* Desired module pat stub not found ... + Bump stack frame iterator. */ + stackptr = (void *) *(unsigned long int *) stackptr; + + is_a_stub = 0; + + } while (stackptr && retval != INVALID_RETURN + && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase); + } + + /* No pat stub found, could be a problem? Simply return unmodified + target address. */ + return target; +} + |