From: Rainer Orth Date: Fri, 3 Jun 2011 18:30:39 +0000 (+0000) Subject: linux.h (MD_UNWIND_SUPPORT): Remove. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=58cd1d70dd8cd4b95773c0487a5d2aecad2b4dc1;p=gcc.git linux.h (MD_UNWIND_SUPPORT): Remove. gcc: * config/alpha/linux.h (MD_UNWIND_SUPPORT): Remove. * config/alpha/osf5.h (MD_UNWIND_SUPPORT): Remove. * config/alpha/vms.h (MD_UNWIND_SUPPORT): Remove. * config/bfin/linux.h (MD_UNWIND_SUPPORT): Remove. * config/bfin/uclinux.h (MD_UNWIND_SUPPORT): Remove. * config/i386/linux.h (MD_UNWIND_SUPPORT): Remove. * config/i386/linux64.h (MD_UNWIND_SUPPORT): Remove. * config/i386/sol2.h (MD_UNWIND_SUPPORT): Remove. * config/i386/mingw32.h (MD_UNWIND_SUPPORT): Remove. * config/ia64/linux.h (MD_UNWIND_SUPPORT): Remove. * config/ia64/vms.h (MD_UNWIND_SUPPORT): Remove. * config/m68k/linux.h (MD_UNWIND_SUPPORT): Remove. * config/mips/linux.h (MD_UNWIND_SUPPORT): Remove. * config/pa/pa-hpux.h (MD_UNWIND_SUPPORT): Remove. * config/pa/pa32-linux.h (MD_UNWIND_SUPPORT): Remove. * config/rs6000/darwin.h (MD_UNWIND_SUPPORT): Remove. * config/rs6000/linux.h (MD_UNWIND_SUPPORT): Remove. * config/rs6000/linux64.h (MD_UNWIND_SUPPORT): Remove. * config/s390/linux.h (MD_UNWIND_SUPPORT): Remove. * config/s390/tpf.h (MD_UNWIND_SUPPORT): Remove. * config/sh/linux.h (MD_UNWIND_SUPPORT): Remove. * config/sparc/linux.h (MD_UNWIND_SUPPORT): Remove. * config/sparc/linux64.h (MD_UNWIND_SUPPORT): Remove. * config/sparc/sol2.h (MD_UNWIND_SUPPORT): Remove. * config/xtensa/linux.h (MD_UNWIND_SUPPORT): Remove. * config/alpha/linux-unwind.h: Move to ../libgcc/config/alpha. * config/alpha/osf5-unwind.h: Move to ../libgcc/config/alpha. * config/alpha/vms-unwind.h: Move to ../libgcc/config/alpha. * config/bfin/linux-unwind.h: Move to ../libgcc/config/bfin. * config/i386/linux-unwind.h: Move to ../libgcc/config/i386. * config/i386/sol2-unwind.h: Move to ../libgcc/config/i386. * config/i386/w32-unwind.h: Move to ../libgcc/config/i386. * config/ia64/linux-unwind.h: Move to ../libgcc/config/ia64. * config/ia64/vms-unwind.h: Move to ../libgcc/config/ia64. * config/m68k/linux-unwind.h: Move to ../libgcc/config/m68k. * config/mips/linux-unwind.h: Move to ../libgcc/config/mips. * config/pa/hpux-unwind.h: Move to ../libgcc/config/pa. * config/pa/linux-unwind.h: Move to ../libgcc/config/pa. * config/rs6000/darwin-unwind.h: Move to ../libgcc/config/rs6000. * config/rs6000/linux-unwind.h: Move to ../libgcc/config/rs6000. * config/s390/linux-unwind.h: Move to ../libgcc/config/s390. * config/s390/tpf-unwind.h: Move to ../libgcc/config/s390. * config/sh/linux-unwind.h: Move to ../libgcc/config/sh. * config/sparc/linux-unwind.h: Move to ../libgcc/config/sparc. * config/sparc/sol2-unwind.h: Move to ../libgcc/config/sparc. * config/xtensa/linux-unwind.h: Move to ../libgcc/config/xtensa. * config/darwin9.h (DARWIN_LIBSYSTEM_HAS_UNWIND): Remove. * system.h (MD_UNWIND_SUPPORT): Poison. * doc/tm.texi.in (Exception Handling, MD_UNWIND_SUPPORT): Remove. * doc/tm.texi: Regenerate. * unwind-dw2.c: Include md-unwind-support.h instead of MD_UNWIND_SUPPORT. * config/ia64/unwind-ia64.c: Likewise. * config/xtensa/unwind-dw2-xtensa.c: Likewise. libgcc: * config/alpha/linux-unwind.h: Move from ../gcc/config/alpha. * config/alpha/osf5-unwind.h: Move from ../gcc/config/alpha. * config/alpha/vms-unwind.h: Move from ../gcc/config/alpha. * config/bfin/linux-unwind.h: Move from ../gcc/config/bfin. * config/i386/linux-unwind.h: Move from ../gcc/config/i386. * config/i386/sol2-unwind.h: Move from ../gcc/config/i386. * config/i386/w32-unwind.h: Move from ../gcc/config/i386. Wrap in !__MINGW64__. * config/ia64/linux-unwind.h: Move from ../gcc/config/ia64. * config/ia64/vms-unwind.h: Move from ../gcc/config/ia64. * config/m68k/linux-unwind.h: Move from ../gcc/config/m68k. * config/mips/linux-unwind.h: Move from ../gcc/config/mips. * config/pa/hpux-unwind.h: Move from ../gcc/config/pa. * config/pa/linux-unwind.h: Move from ../gcc/config/pa. * config/rs6000/darwin-unwind.h: Move from ../gcc/config/rs6000. Wrap in !__LP64__. * config/rs6000/linux-unwind.h: Move from ../gcc/config/rs6000. * config/s390/linux-unwind.h: Move from ../gcc/config/s390. * config/s390/tpf-unwind.h: Move from ../gcc/config/s390. * config/sh/linux-unwind.h: Move from ../gcc/config/sh. * config/sparc/linux-unwind.h: Move from ../gcc/config/sparc. * config/sparc/sol2-unwind.h: Move from ../gcc/config/sparc. * config/xtensa/linux-unwind.h: Move from ../gcc/config/xtensa. * config/no-unwind.h: New file. * config.host (md_unwind_header): Document. Define. (alpha*-*-linux*, alpha*-dec-osf5.1*, alpha64-dec-*vms*, alpha*-dec-*vms*, bfin*-uclinux*, bfin*-linux-uclibc*, hppa*-*-linux*, hppa[12]*-*-hpux10*, hppa*64*-*-hpux11*, hppa[12]*-*-hpux11*): Set md_unwind_header. (i[34567]86-*-linux*): Handle i[34567]86-*-kopensolaris*-gnu. Set md_unwind_header. (x86_64-*-linux*, i[34567]86-*-solaris2*): Set md_unwind_header. (i[34567]86-*-cygwin*): Split from i[34567]86-*-mingw*. (i[34567]86-*-mingw*, ia64*-*-linux*, ia64-hp-*vms*, m68k-*-uclinux*, m68k-*-linux*, mips64*-*-linux*, mips*-*-linux*, powerpc-*-darwin*, powerpc-*-linux*, s390-*-linux*, s390x-*-linux*, s390x-ibm-tpf*, sh*-*-linux*, sparc-*-linux*, sparc*-*-solaris2*, sparc64-*-linux*, xtensa*-*-linux*): Set md_unwind_header. * configure.ac: Link md-unwind-support.h to $md_unwind_header. * configure: Regenerate. From-SVN: r174613 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 46ee4cfa1e5..94b105e2633 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,60 @@ +2011-06-03 Rainer Orth + + * config/alpha/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/alpha/osf5.h (MD_UNWIND_SUPPORT): Remove. + * config/alpha/vms.h (MD_UNWIND_SUPPORT): Remove. + * config/bfin/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/bfin/uclinux.h (MD_UNWIND_SUPPORT): Remove. + * config/i386/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/i386/linux64.h (MD_UNWIND_SUPPORT): Remove. + * config/i386/sol2.h (MD_UNWIND_SUPPORT): Remove. + * config/i386/mingw32.h (MD_UNWIND_SUPPORT): Remove. + * config/ia64/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/ia64/vms.h (MD_UNWIND_SUPPORT): Remove. + * config/m68k/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/mips/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/pa/pa-hpux.h (MD_UNWIND_SUPPORT): Remove. + * config/pa/pa32-linux.h (MD_UNWIND_SUPPORT): Remove. + * config/rs6000/darwin.h (MD_UNWIND_SUPPORT): Remove. + * config/rs6000/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/rs6000/linux64.h (MD_UNWIND_SUPPORT): Remove. + * config/s390/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/s390/tpf.h (MD_UNWIND_SUPPORT): Remove. + * config/sh/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/sparc/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/sparc/linux64.h (MD_UNWIND_SUPPORT): Remove. + * config/sparc/sol2.h (MD_UNWIND_SUPPORT): Remove. + * config/xtensa/linux.h (MD_UNWIND_SUPPORT): Remove. + * config/alpha/linux-unwind.h: Move to ../libgcc/config/alpha. + * config/alpha/osf5-unwind.h: Move to ../libgcc/config/alpha. + * config/alpha/vms-unwind.h: Move to ../libgcc/config/alpha. + * config/bfin/linux-unwind.h: Move to ../libgcc/config/bfin. + * config/i386/linux-unwind.h: Move to ../libgcc/config/i386. + * config/i386/sol2-unwind.h: Move to ../libgcc/config/i386. + * config/i386/w32-unwind.h: Move to ../libgcc/config/i386. + * config/ia64/linux-unwind.h: Move to ../libgcc/config/ia64. + * config/ia64/vms-unwind.h: Move to ../libgcc/config/ia64. + * config/m68k/linux-unwind.h: Move to ../libgcc/config/m68k. + * config/mips/linux-unwind.h: Move to ../libgcc/config/mips. + * config/pa/hpux-unwind.h: Move to ../libgcc/config/pa. + * config/pa/linux-unwind.h: Move to ../libgcc/config/pa. + * config/rs6000/darwin-unwind.h: Move to ../libgcc/config/rs6000. + * config/rs6000/linux-unwind.h: Move to ../libgcc/config/rs6000. + * config/s390/linux-unwind.h: Move to ../libgcc/config/s390. + * config/s390/tpf-unwind.h: Move to ../libgcc/config/s390. + * config/sh/linux-unwind.h: Move to ../libgcc/config/sh. + * config/sparc/linux-unwind.h: Move to ../libgcc/config/sparc. + * config/sparc/sol2-unwind.h: Move to ../libgcc/config/sparc. + * config/xtensa/linux-unwind.h: Move to ../libgcc/config/xtensa. + * config/darwin9.h (DARWIN_LIBSYSTEM_HAS_UNWIND): Remove. + * system.h (MD_UNWIND_SUPPORT): Poison. + * doc/tm.texi.in (Exception Handling, MD_UNWIND_SUPPORT): Remove. + * doc/tm.texi: Regenerate. + * unwind-dw2.c: Include md-unwind-support.h instead of + MD_UNWIND_SUPPORT. + * config/ia64/unwind-ia64.c: Likewise. + * config/xtensa/unwind-dw2-xtensa.c: Likewise. + 2011-06-03 Jack Howarth * varpool.c (varpool_extra_name_alias): Return NULL, not false. diff --git a/gcc/config/alpha/linux-unwind.h b/gcc/config/alpha/linux-unwind.h deleted file mode 100644 index e43aacfd00b..00000000000 --- a/gcc/config/alpha/linux-unwind.h +++ /dev/null @@ -1,78 +0,0 @@ -/* DWARF2 EH unwinding support for Alpha Linux. - Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#include -#include - -#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state - -static _Unwind_Reason_Code -alpha_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned int *pc = context->ra; - struct sigcontext *sc; - long new_cfa, i; - - if (pc[0] != 0x47fe0410 /* mov $30,$16 */ - || pc[2] != 0x00000083 /* callsys */) - return _URC_END_OF_STACK; - if (context->cfa == 0) - return _URC_END_OF_STACK; - if (pc[1] == 0x201f0067) /* lda $0,NR_sigreturn */ - sc = context->cfa; - else if (pc[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */ - { - struct rt_sigframe { - struct siginfo info; - struct ucontext uc; - } *rt_ = context->cfa; - sc = &rt_->uc.uc_mcontext; - } - else - return _URC_END_OF_STACK; - new_cfa = sc->sc_regs[30]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 30; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - for (i = 0; i < 30; ++i) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = (long)&sc->sc_regs[i] - new_cfa; - } - for (i = 0; i < 31; ++i) - { - fs->regs.reg[i+32].how = REG_SAVED_OFFSET; - fs->regs.reg[i+32].loc.offset - = (long)&sc->sc_fpregs[i] - new_cfa; - } - fs->regs.reg[64].how = REG_SAVED_OFFSET; - fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa; - fs->retaddr_column = 64; - return _URC_NO_REASON; -} diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h index a1881c8168b..38dbdb0c8be 100644 --- a/gcc/config/alpha/linux.h +++ b/gcc/config/alpha/linux.h @@ -1,7 +1,7 @@ /* Definitions of target machine for GNU compiler, for Alpha Linux-based GNU systems. Copyright (C) 1996, 1997, 1998, 2002, 2003, 2004, 2005, 2006, 2007, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. Contributed by Richard Henderson. This file is part of GCC. @@ -84,8 +84,6 @@ along with GCC; see the file COPYING3. If not see #define USE_LD_AS_NEEDED 1 #endif -#define MD_UNWIND_SUPPORT "config/alpha/linux-unwind.h" - /* Define if long doubles should be mangled as 'g'. */ #define TARGET_ALTERNATE_LONG_DOUBLE_MANGLING diff --git a/gcc/config/alpha/osf5-unwind.h b/gcc/config/alpha/osf5-unwind.h deleted file mode 100644 index c649099349e..00000000000 --- a/gcc/config/alpha/osf5-unwind.h +++ /dev/null @@ -1,329 +0,0 @@ -/* DWARF2 EH unwinding support for Alpha Tru64. - Copyright (C) 2010 Free Software Foundation, Inc. - -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. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -/* This file implements the MD_FALLBACK_FRAME_STATE_FOR macro, triggered when - the GCC table based unwinding process hits a frame for which no unwind info - has been registered. This typically occurs when raising an exception from a - signal handler, because the handler is actually called from the OS kernel. - - The basic idea is to detect that we are indeed trying to unwind past a - signal handler and to fill out the GCC internal unwinding structures for - the OS kernel frame as if it had been directly called from the interrupted - context. - - This is all assuming that the code to set the handler asked the kernel to - pass a pointer to such context information. */ - -/* -------------------------------------------------------------------------- - -- Basic principles of operation: - -------------------------------------------------------------------------- - - 1/ We first need a way to detect if we are trying to unwind past a signal - handler. - - The typical method that is used on most platforms is to look at the code - around the return address we have and check if it matches the OS code - calling a handler. To determine what this code is expected to be, get a - breakpoint into a real signal handler and look at the code around the - return address. Depending on the library versions the pattern of the - signal handler is different; this is the reason why we check against more - than one pattern. - - On this target, the return address is right after the call and every - instruction is 4 bytes long. For the simple case of a null dereference in - a single-threaded app, it went like: - - # Check that we indeed have something we expect: the instruction right - # before the return address is within a __sigtramp function and is a call. - - [... run gdb and break at the signal handler entry ...] - - (gdb) x /i $ra-4 - <__sigtramp+160>: jsr ra,(a3),0x3ff800d0ed4 <_fpdata+36468> - - # Look at the code around that return address, and eventually observe a - # significantly large chunk of *constant* code right before the call: - - (gdb) x /10i $ra-44 - <__sigtramp+120>: lda gp,-27988(gp) - <__sigtramp+124>: ldq at,-18968(gp) - <__sigtramp+128>: lda t0,-1 - <__sigtramp+132>: stq t0,0(at) - <__sigtramp+136>: ldq at,-18960(gp) - <__sigtramp+140>: ldl t1,8(at) - <__sigtramp+144>: ldq at,-18960(gp) - <__sigtramp+148>: stl t1,12(at) - <__sigtramp+152>: ldq at,-18960(gp) - <__sigtramp+156>: stl t0,8(at) - - # The hexadecimal equivalent that we will have to match is: - - (gdb) x /10x $ra-44 - <__sigtramp+120>: 0x23bd92ac 0xa79db5e8 0x203fffff 0xb43c0000 - <__sigtramp+136>: 0xa79db5f0 0xa05c0008 0xa79db5f0 0xb05c000c - <__sigtramp+152>: 0xa79db5f0 0xb03c0008 - - The problem observed on this target with this approach is that although - we found a constant set of instruction patterns there were some - gp-related offsets that made the machine code to differ from one - installation to another. This problem could have been overcome by masking - these offsets, but we found that it would be simpler and more efficient to - check whether the return address was part of a signal handler, by comparing - it against some expected code offset from __sigtramp. - - # Check that we indeed have something we expect: the instruction - # right before the return address is within a __sigtramp - # function and is a call. We also need to obtain the offset - # between the return address and the start address of __sigtramp. - - [... run gdb and break at the signal handler entry ...] - - (gdb) x /2i $ra-4 - <__sigtramp+160>: jsr ra,(a3),0x3ff800d0ed4 <_fpdata+36468> - <__sigtramp+164>: ldah gp,16381(ra) - - (gdb) p (long)$ra - (long)&__sigtramp - $2 = 164 - - -------------------------------------------------------------------------- - - 2/ Once we know we are going through a signal handler, we need a way to - retrieve information about the interrupted run-time context. - - On this platform, the third handler's argument is a pointer to a structure - describing this context (struct sigcontext *). We unfortunately have no - direct way to transfer this value here, so a couple of tricks are required - to compute it. - - As documented at least in some header files (e.g. sys/machine/context.h), - the structure the handler gets a pointer to is located on the stack. As of - today, while writing this macro, we have unfortunately not been able to - find a detailed description of the full stack layout at handler entry time, - so we'll have to resort to empirism :) - - When unwinding here, we have the handler's CFA at hand, as part of the - current unwinding context which is one of our arguments. We presume that - for each call to a signal handler by the same kernel routine, the context's - structure location on the stack is always at the same offset from the - handler's CFA, and we compute that offset from bare observation: - - For the simple case of a bare null dereference in a single-threaded app, - computing the offset was done using GNAT like this: - - # Break on the first handler's instruction, before the prologue to have the - # CFA in $sp, and get there: - - (gdb) b *&__gnat_error_handler - Breakpoint 1 at 0x120016090: file init.c, line 378. - - (gdb) r - Program received signal SIGSEGV, Segmentation fault. - - (gdb) c - Breakpoint 1, __gnat_error_handler (sig=..., sip=..., context=...) - - # The displayed argument value are meaningless because we stopped before - # their final "homing". We know they are passed through $a0, $a1 and $a2 - # from the ABI, though, so ... - - # Observe that $sp and the context pointer are in the same (stack) area, - # and compute the offset: - - (gdb) p /x $sp - $2 = 0x11fffbc80 - - (gdb) p /x $a2 - $3 = 0x11fffbcf8 - - (gdb) p /x (long)$a2 - (long)$sp - $4 = 0x78 - - -------------------------------------------------------------------------- - - 3/ Once we know we are unwinding through a signal handler and have the - address of the structure describing the interrupted context at hand, we - have to fill the internal frame-state/unwind-context structures properly - to allow the unwinding process to proceed. - - Roughly, we are provided with an *unwinding* CONTEXT, describing the state - of some point P in the call chain we are unwinding through. The macro we - implement has to fill a "frame state" structure FS that describe the P's - caller state, by way of *rules* to compute its CFA, return address, and - **saved** registers *locations*. - - For the case we are going to deal with, the caller is some kernel code - calling a signal handler, and: - - o The saved registers are all in the interrupted run-time context, - - o The CFA is the stack pointer value when the kernel code is entered, that - is, the stack pointer value at the interruption point, also part of the - interrupted run-time context. - - o We want the return address to appear as the address of the active - instruction at the interruption point, so that the unwinder proceeds as - if the interruption had been a regular call. This address is also part - of the interrupted run-time context. - - -- - - Also, note that there is an important difference between the return address - we need to claim for the kernel frame and the value of the return address - register at the interruption point. - - The latter might be required to be able to unwind past the interrupted - routine, for instance if it is interrupted before saving the incoming - register value in its own frame, which may typically happen during stack - probes for stack-checking purposes. - - It is then essential that the rules stated to locate the kernel frame - return address don't clobber the rules describing where is saved the return - address register at the interruption point, so some scratch register state - entry should be used for the former. We have DWARF_ALT_FRAME_RETURN_COLUMN - at hand exactly for that purpose. - - -------------------------------------------------------------------------- - - 4/ Depending on the context (single-threaded or multi-threaded app, ...), - the code calling the handler and the handler-cfa to interrupted-context - offset might change, so we use a simple generic data structure to track - the possible variants. */ - -/* This is the structure to wrap information about each possible sighandler - caller we may have to identify. */ - -typedef struct { - /* Expected return address when being called from a sighandler. */ - void *ra_value; - - /* Offset to get to the sigcontext structure from the handler's CFA - when the pattern matches. */ - int cfa_to_context_offset; - -} sighandler_call_t; - -/* Helper macro for MD_FALLBACK_FRAME_STATE_FOR below. - - Look at RA to see if it matches within a sighandler caller. - Set SIGCTX to the corresponding sigcontext structure (computed from - CFA) if it does, or to 0 otherwise. */ - -#define COMPUTE_SIGCONTEXT_FOR(RA,CFA,SIGCTX) \ -do { \ - /* Define and register the applicable patterns. */ \ - extern void __sigtramp (void); \ - \ - sighandler_call_t sighandler_calls [] = { \ - {__sigtramp + 164, 0x78} \ - }; \ - \ - int n_patterns_to_match \ - = sizeof (sighandler_calls) / sizeof (sighandler_call_t); \ - \ - int pn; /* pattern number */ \ - \ - int match = 0; /* Did last pattern match ? */ \ - \ - /* Try to match each pattern in turn. */ \ - for (pn = 0; !match && pn < n_patterns_to_match; pn ++) \ - match = ((RA) == sighandler_calls[pn].ra_value); \ - \ - (SIGCTX) = (struct sigcontext *) \ - (match ? ((CFA) + sighandler_calls[pn - 1].cfa_to_context_offset) : 0); \ -} while (0); - -#include - -#define REG_SP 30 /* hard reg for stack pointer */ -#define REG_RA 26 /* hard reg for return address */ - -#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state - -static _Unwind_Reason_Code -alpha_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - /* Return address and CFA of the frame we're attempting to unwind through, - possibly a signal handler. */ - void *ctx_ra = (void *)context->ra; - void *ctx_cfa = (void *)context->cfa; - - /* CFA of the intermediate abstract kernel frame between the interrupted - code and the signal handler, if we're indeed unwinding through a signal - handler. */ - void *k_cfa; - - /* Pointer to the sigcontext structure pushed by the kernel when we're - unwinding through a signal handler. */ - struct sigcontext *sigctx; - int i; - - COMPUTE_SIGCONTEXT_FOR (ctx_ra, ctx_cfa, sigctx); - - if (sigctx == 0) - return _URC_END_OF_STACK; - - /* The kernel frame's CFA is exactly the stack pointer value at the - interruption point. */ - k_cfa = (void *) sigctx->sc_regs [REG_SP]; - - /* State the rules to compute the CFA we have the value of: use the - previous CFA and offset by the difference between the two. See - uw_update_context_1 for the supporting details. */ - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = k_cfa - ctx_cfa; - - /* Fill the internal frame_state structure with information stating - where each register of interest in the saved context can be found - from the CFA. */ - - /* The general registers are in sigctx->sc_regs. Leave out r31, which - is read-as-zero. It makes no sense restoring it, and we are going to - use the state entry for the kernel return address rule below. - - This loop must cover at least all the callee-saved registers, and - we just don't bother specializing the set here. */ - for (i = 0; i <= 30; i ++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = (void *) &sigctx->sc_regs[i] - (void *) k_cfa; - } - - /* Ditto for the floating point registers in sigctx->sc_fpregs. */ - for (i = 0; i <= 31; i ++) - { - fs->regs.reg[32+i].how = REG_SAVED_OFFSET; - fs->regs.reg[32+i].loc.offset - = (void *) &sigctx->sc_fpregs[i] - (void *) k_cfa; - } - - /* State the rules to find the kernel's code "return address", which - is the address of the active instruction when the signal was caught, - in sigctx->sc_pc. Use DWARF_ALT_FRAME_RETURN_COLUMN since the return - address register is a general register and should be left alone. */ - fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset - = (void *) &sigctx->sc_pc - (void *) k_cfa; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} diff --git a/gcc/config/alpha/osf5.h b/gcc/config/alpha/osf5.h index 7713b7ee045..995f35d4f32 100644 --- a/gcc/config/alpha/osf5.h +++ b/gcc/config/alpha/osf5.h @@ -274,5 +274,3 @@ __enable_execute_stack (void *addr) \ /* Handle #pragma extern_prefix. */ #define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 1 - -#define MD_UNWIND_SUPPORT "config/alpha/osf5-unwind.h" diff --git a/gcc/config/alpha/vms-unwind.h b/gcc/config/alpha/vms-unwind.h deleted file mode 100644 index 71cb7b87920..00000000000 --- a/gcc/config/alpha/vms-unwind.h +++ /dev/null @@ -1,293 +0,0 @@ -/* Fallback frame unwinding for Alpha/VMS. - Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2009, 2010, 2011 - Free Software Foundation, Inc. - - 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 - . */ - -#include -#include -#include -#include -#include -#include - -#define MD_FALLBACK_FRAME_STATE_FOR alpha_vms_fallback_frame_state - -typedef void * ADDR; -typedef unsigned long long REG; -typedef PDSCDEF * PV; - -#define REG_AT(addr) (*(REG *)(addr)) -#define ADDR_AT(addr) (*(ADDR *)(addr)) - -/* Compute pointer to procedure descriptor (Procedure Value) from Frame - Pointer FP, according to the rules in [ABI-3.5.1 Current Procedure]. */ -#define PV_FOR(FP) \ - (((FP) != 0) \ - ? (((REG_AT (FP) & 0x7) == 0) ? *(PDSCDEF **)(FP) : (PDSCDEF *)(FP)) : 0) - -extern int SYS$GL_CALL_HANDL; -/* This is actually defined as a "long", but in system code where longs - are always 4bytes while GCC longs might be 8bytes. */ - -#define UPDATE_FS_FOR_CFA_GR(FS, GRN, LOC, CFA) \ -do { \ -(FS)->regs.reg[GRN].how = REG_SAVED_OFFSET; \ -(FS)->regs.reg[GRN].loc.offset = (_Unwind_Sword) ((REG) (LOC) - (REG) (CFA)); \ -} while (0); - -#define GIVEUP_ON_FAILURE(STATUS) \ - { if ((((STATUS) & 1) != 1)) return _URC_END_OF_STACK; } -#define DENOTES_EXC_DISPATCHER(PV) ((PV) == (ADDR) (REG) SYS$GL_CALL_HANDL) - -#define RA_COLUMN (DWARF_ALT_FRAME_RETURN_COLUMN) - -static int -alpha_vms_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - static int eh_debug = -1; - - /* Our goal is to update FS to reflect the state one step up CONTEXT, that - is: the CFA, return address and *saved* registers locations associated - with the function designated by CONTEXT->ra. We are called when the - libgcc unwinder has not found any dwarf FDE for this address, which - typically happens when trying to propagate a language exception through a - signal global vector or frame based handler. - - The CONTEXT->reg[] entries reflect the state/location of register saves - so designate values live at the CONTEXT->ra point. Of precious value to - us here is the frame pointer (r29), which gets us a procedure value. */ - - PV pv = (context->reg[29] != 0) ? PV_FOR (ADDR_AT (context->reg[29])) : 0; - - int pkind = pv ? pv->pdsc$w_flags & 0xf : 0; - /* VMS procedure kind, as indicated by the procedure descriptor. We only - know how to deal with FP_STACK or FP_REGISTER here. */ - - ADDR new_cfa = 0; - /* CFA we will establish for the caller, computed in different ways, - e.g. depending whether we cross an exception dispatcher frame. */ - - CHFCTX *chfctx = 0; - /* Pointer to the VMS CHF context associated with an exception dispatcher - frame, if we happen to come across one. */ - - int i,j; - - if (eh_debug == -1) - { - char * eh_debug_env = getenv ("EH_DEBUG"); - eh_debug = eh_debug_env ? atoi (eh_debug_env) : 0; - } - - if (eh_debug) - printf ("MD_FALLBACK running ...\n"); - - /* We only know how to deal with stack or reg frame procedures, so give - up if we're handed anything else. */ - if (pkind != PDSC$K_KIND_FP_STACK && pkind != PDSC$K_KIND_FP_REGISTER) - return _URC_END_OF_STACK; - - if (eh_debug) - printf ("FALLBACK: CTX FP = 0x%p, PV = 0x%p, EN = 0x%llx, RA = 0x%p\n", - ADDR_AT (context->reg[29]), pv, pv->pdsc$q_entry, context->ra); - - fs->retaddr_column = RA_COLUMN; - - /* If PV designates a VMS exception vector or condition handler, we need to - do as if the caller was the signaling point and estabish the state of the - intermediate VMS code (CFA, RA and saved register locations) as if it was - a single regular function. This requires special processing. - - The datastructures available from an condition dispatcher frame (signal - context) do not contain the values of most callee-saved registers, so - whathever PV designates, we need to account for the registers it saves. - - Besides, we need to express all the locations with respect to a - consistent CFA value, so we compute this first. */ - - if (DENOTES_EXC_DISPATCHER (pv)) - { - /* The CFA to establish is the signaling point's stack pointer. We - compute it using the system invocation context unwinding services and - save the CHF context data pointer along the way for later uses. */ - - INVO_CONTEXT_BLK icb; - int status, invo_handle; - - if (eh_debug) - printf ("FALLBACK: SYS$HANDLER\n"); - - icb.libicb$q_ireg [29] = REG_AT (context->reg[29]); - icb.libicb$q_ireg [30] = 0; - invo_handle = LIB$GET_INVO_HANDLE (&icb); - - status = LIB$GET_INVO_CONTEXT (invo_handle, &icb); - GIVEUP_ON_FAILURE (status); - - chfctx = (CHFCTX *) icb.libicb$ph_chfctx_addr; - - status = LIB$GET_PREV_INVO_CONTEXT (&icb); - GIVEUP_ON_FAILURE (status); - - new_cfa = (ADDR) icb.libicb$q_ireg[30]; - } - else - { - /* The CFA to establish is the SP value on entry of the procedure - designated by PV, which we compute as the corresponding frame base - register value + frame size. Note that the frame base may differ - from CONTEXT->cfa, typically if the caller has performed dynamic - stack allocations. */ - - int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; - ADDR base_addr = ADDR_AT (context->reg[base_reg]); - - new_cfa = base_addr + pv->pdsc$l_size; - } - - /* State to compute the caller's CFA by adding an offset to the current - one in CONTEXT. */ - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = new_cfa - context->cfa; - - /* Regular unwind first, accounting for the register saves performed by - the procedure designated by PV. */ - - switch (pkind) - { - case PDSC$K_KIND_FP_STACK: - { - /* The saved registers are all located in the Register Save Area, - except for the procedure value register (R27) found at the frame - base address. */ - - int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; - ADDR base_addr = ADDR_AT (context->reg[base_reg]); - ADDR rsa_addr = base_addr + pv->pdsc$w_rsa_offset; - - if (eh_debug) - printf ("FALLBACK: STACK frame procedure\n"); - - UPDATE_FS_FOR_CFA_GR (fs, 27, base_addr, new_cfa); - - /* The first RSA entry is for the return address register, R26. */ - - UPDATE_FS_FOR_CFA_GR (fs, 26, rsa_addr, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, rsa_addr, new_cfa); - - /* The following entries are for registers marked as saved according - to ireg_mask. */ - for (i = 0, j = 0; i < 32; i++) - if ((1 << i) & pv->pdsc$l_ireg_mask) - UPDATE_FS_FOR_CFA_GR (fs, i, rsa_addr + 8 * ++j, new_cfa); - - /* ??? floating point registers ? */ - - break; - } - - case PDSC$K_KIND_FP_REGISTER: - { - if (eh_debug) - printf ("FALLBACK: REGISTER frame procedure\n"); - - fs->regs.reg[RA_COLUMN].how = REG_SAVED_REG; - fs->regs.reg[RA_COLUMN].loc.reg = pv->pdsc$b_save_ra; - - fs->regs.reg[29].how = REG_SAVED_REG; - fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; - - break; - } - - default: - /* Should never reach here. */ - return _URC_END_OF_STACK; - } - - /* If PV designates an exception dispatcher, we have to adjust the return - address column to get at the signal occurrence point, and account for - what the CHF context contains. */ - - if (DENOTES_EXC_DISPATCHER (pv)) - { - /* The PC of the instruction causing the condition is available from the - signal argument vector. Extra saved register values are available - from the mechargs array. */ - - CHF$SIGNAL_ARRAY *sigargs - = (CHF$SIGNAL_ARRAY *) chfctx->chfctx$q_sigarglst; - - CHF$MECH_ARRAY *mechargs - = (CHF$MECH_ARRAY *) chfctx->chfctx$q_mcharglst; - - ADDR condpc_addr - = &((int *)(&sigargs->chf$l_sig_name)) [sigargs->chf$is_sig_args-2]; - - ADDR rei_frame_addr = (void *) mechargs->chf$q_mch_esf_addr; - - /* Adjust the return address location. */ - - UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, condpc_addr, new_cfa); - - /* The frame pointer at the condition point is available from the - chf context directly. */ - - UPDATE_FS_FOR_CFA_GR (fs, 29, &chfctx->chfctx$q_expt_fp, new_cfa); - - /* Registers available from the mechargs array. */ - - UPDATE_FS_FOR_CFA_GR (fs, 0, &mechargs->chf$q_mch_savr0, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 1, &mechargs->chf$q_mch_savr1, new_cfa); - - UPDATE_FS_FOR_CFA_GR (fs, 16, &mechargs->chf$q_mch_savr16, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 17, &mechargs->chf$q_mch_savr17, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 18, &mechargs->chf$q_mch_savr18, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 19, &mechargs->chf$q_mch_savr19, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 20, &mechargs->chf$q_mch_savr20, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 21, &mechargs->chf$q_mch_savr21, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 22, &mechargs->chf$q_mch_savr22, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 23, &mechargs->chf$q_mch_savr23, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 24, &mechargs->chf$q_mch_savr24, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 25, &mechargs->chf$q_mch_savr25, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 26, &mechargs->chf$q_mch_savr26, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 27, &mechargs->chf$q_mch_savr27, new_cfa); - UPDATE_FS_FOR_CFA_GR (fs, 28, &mechargs->chf$q_mch_savr28, new_cfa); - - /* Registers R2 to R7 are available from the rei frame pointer. */ - - for (i = 2; i <= 7; i ++) - UPDATE_FS_FOR_CFA_GR (fs, i, rei_frame_addr+(i - 2)*8, new_cfa); - - /* ??? floating point registers ? */ - } - - fs->signal_frame = 1; - - return _URC_NO_REASON; -} - - - diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h index 8e931033989..f730ea1b5dd 100644 --- a/gcc/config/alpha/vms.h +++ b/gcc/config/alpha/vms.h @@ -225,14 +225,6 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info; #define LINK_EH_SPEC "vms-dwarf2eh.o%s " #define LINK_GCC_C_SEQUENCE_SPEC "%G" -#ifdef IN_LIBGCC2 -/* Get the definition for MD_FALLBACK_FRAME_STATE_FOR from a separate - file. This avoids having to recompile the world instead of libgcc only - when changes to this macro are exercised. */ - -#define MD_UNWIND_SUPPORT "config/alpha/vms-unwind.h" -#endif - #define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ avms_asm_output_external (FILE, DECL, NAME) diff --git a/gcc/config/bfin/linux-unwind.h b/gcc/config/bfin/linux-unwind.h deleted file mode 100644 index 88c8285632d..00000000000 --- a/gcc/config/bfin/linux-unwind.h +++ /dev/null @@ -1,164 +0,0 @@ -/* DWARF2 EH unwinding support for Blackfin. - Copyright (C) 2007, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. - Don't use this at all if inhibit_libc is used. */ - -#ifndef inhibit_libc - -#include -#include - -#define MD_FALLBACK_FRAME_STATE_FOR bfin_fallback_frame_state - -static _Unwind_Reason_Code -bfin_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - long new_cfa; - - /* P0=__NR_rt_sigreturn (X); EXCPT 0x0; */ - if (*(unsigned short *)pc == 0xe128 - && *(unsigned short *)(pc + 2) == 0x00ad - && *(unsigned short *)(pc + 4) == 0x00a0) - { - struct rt_sigframe { - int sig; - struct siginfo *pinfo; - void *puc; - char retcode[8]; - struct siginfo info; - struct ucontext uc; - } *rt_ = context->cfa; - - /* The void * cast is necessary to avoid an aliasing warning. - The aliasing warning is correct, but should not be a problem - because it does not alias anything. */ - sc = (struct sigcontext *)(void *)&rt_->uc.uc_mcontext.gregs; - } - else - return _URC_END_OF_STACK; - - new_cfa = sc->sc_usp; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 14; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&sc->sc_r0 - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&sc->sc_r1 - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&sc->sc_r2 - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&sc->sc_r3 - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; - fs->regs.reg[4].loc.offset = (long)&sc->sc_r4 - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&sc->sc_r5 - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&sc->sc_r6 - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; - fs->regs.reg[7].loc.offset = (long)&sc->sc_r7 - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&sc->sc_p0 - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; - fs->regs.reg[9].loc.offset = (long)&sc->sc_p1 - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; - fs->regs.reg[10].loc.offset = (long)&sc->sc_p2 - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; - fs->regs.reg[11].loc.offset = (long)&sc->sc_p3 - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; - fs->regs.reg[12].loc.offset = (long)&sc->sc_p4 - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; - fs->regs.reg[13].loc.offset = (long)&sc->sc_p5 - new_cfa; - - fs->regs.reg[15].how = REG_SAVED_OFFSET; - fs->regs.reg[15].loc.offset = (long)&sc->sc_fp - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; - fs->regs.reg[16].loc.offset = (long)&sc->sc_i0 - new_cfa; - fs->regs.reg[17].how = REG_SAVED_OFFSET; - fs->regs.reg[17].loc.offset = (long)&sc->sc_i1 - new_cfa; - fs->regs.reg[18].how = REG_SAVED_OFFSET; - fs->regs.reg[18].loc.offset = (long)&sc->sc_i2 - new_cfa; - fs->regs.reg[19].how = REG_SAVED_OFFSET; - fs->regs.reg[19].loc.offset = (long)&sc->sc_i3 - new_cfa; - fs->regs.reg[20].how = REG_SAVED_OFFSET; - fs->regs.reg[20].loc.offset = (long)&sc->sc_b0 - new_cfa; - fs->regs.reg[21].how = REG_SAVED_OFFSET; - fs->regs.reg[21].loc.offset = (long)&sc->sc_b1 - new_cfa; - fs->regs.reg[22].how = REG_SAVED_OFFSET; - fs->regs.reg[22].loc.offset = (long)&sc->sc_b2 - new_cfa; - fs->regs.reg[23].how = REG_SAVED_OFFSET; - fs->regs.reg[23].loc.offset = (long)&sc->sc_b3 - new_cfa; - fs->regs.reg[24].how = REG_SAVED_OFFSET; - fs->regs.reg[24].loc.offset = (long)&sc->sc_l0 - new_cfa; - fs->regs.reg[25].how = REG_SAVED_OFFSET; - fs->regs.reg[25].loc.offset = (long)&sc->sc_l1 - new_cfa; - fs->regs.reg[26].how = REG_SAVED_OFFSET; - fs->regs.reg[26].loc.offset = (long)&sc->sc_l2 - new_cfa; - fs->regs.reg[27].how = REG_SAVED_OFFSET; - fs->regs.reg[27].loc.offset = (long)&sc->sc_l3 - new_cfa; - fs->regs.reg[28].how = REG_SAVED_OFFSET; - fs->regs.reg[28].loc.offset = (long)&sc->sc_m0 - new_cfa; - fs->regs.reg[29].how = REG_SAVED_OFFSET; - fs->regs.reg[29].loc.offset = (long)&sc->sc_m1 - new_cfa; - fs->regs.reg[30].how = REG_SAVED_OFFSET; - fs->regs.reg[30].loc.offset = (long)&sc->sc_m2 - new_cfa; - fs->regs.reg[31].how = REG_SAVED_OFFSET; - fs->regs.reg[31].loc.offset = (long)&sc->sc_m3 - new_cfa; - /* FIXME: Handle A0, A1, CC. */ - fs->regs.reg[35].how = REG_SAVED_OFFSET; - fs->regs.reg[35].loc.offset = (long)&sc->sc_rets - new_cfa; - fs->regs.reg[36].how = REG_SAVED_OFFSET; - fs->regs.reg[36].loc.offset = (long)&sc->sc_pc - new_cfa; - fs->regs.reg[37].how = REG_SAVED_OFFSET; - fs->regs.reg[37].loc.offset = (long)&sc->sc_retx - new_cfa; - - fs->regs.reg[40].how = REG_SAVED_OFFSET; - fs->regs.reg[40].loc.offset = (long)&sc->sc_astat - new_cfa; - fs->regs.reg[41].how = REG_SAVED_OFFSET; - fs->regs.reg[41].loc.offset = (long)&sc->sc_seqstat - new_cfa; - - fs->regs.reg[44].how = REG_SAVED_OFFSET; - fs->regs.reg[44].loc.offset = (long)&sc->sc_lt0 - new_cfa; - fs->regs.reg[45].how = REG_SAVED_OFFSET; - fs->regs.reg[45].loc.offset = (long)&sc->sc_lt1 - new_cfa; - fs->regs.reg[46].how = REG_SAVED_OFFSET; - fs->regs.reg[46].loc.offset = (long)&sc->sc_lc0 - new_cfa; - fs->regs.reg[47].how = REG_SAVED_OFFSET; - fs->regs.reg[47].loc.offset = (long)&sc->sc_lc1 - new_cfa; - fs->regs.reg[48].how = REG_SAVED_OFFSET; - fs->regs.reg[48].loc.offset = (long)&sc->sc_lb0 - new_cfa; - fs->regs.reg[49].how = REG_SAVED_OFFSET; - fs->regs.reg[49].loc.offset = (long)&sc->sc_lb1 - new_cfa; - fs->retaddr_column = 35; - - return _URC_NO_REASON; -} - -#endif /* ifdef inhibit_libc */ diff --git a/gcc/config/bfin/linux.h b/gcc/config/bfin/linux.h index cd15f48ed72..f91cf17f141 100644 --- a/gcc/config/bfin/linux.h +++ b/gcc/config/bfin/linux.h @@ -48,7 +48,5 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -dynamic-linker /lib/ld-uClibc.so.0} \ %{static}} -init __init -fini __fini" -#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h" - #undef TARGET_SUPPORTS_SYNC_CALLS #define TARGET_SUPPORTS_SYNC_CALLS 1 diff --git a/gcc/config/bfin/uclinux.h b/gcc/config/bfin/uclinux.h index 354ff55a60b..da26be57606 100644 --- a/gcc/config/bfin/uclinux.h +++ b/gcc/config/bfin/uclinux.h @@ -32,8 +32,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see %{mfast-fp:-lbffastfp} %G %L %{mfast-fp:-lbffastfp} %G \ " -#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h" - /* Like the definition in gcc.c, but for purposes of uClinux, every link is static. */ #define MFWRAP_SPEC " %{fmudflap|fmudflapth: \ diff --git a/gcc/config/darwin9.h b/gcc/config/darwin9.h index 82811837282..bb62dd4ca9f 100644 --- a/gcc/config/darwin9.h +++ b/gcc/config/darwin9.h @@ -1,5 +1,5 @@ /* Target definitions for Darwin (Mac OS X) systems. - Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2010, 2011 Free Software Foundation, Inc. Contributed by Apple Inc. This file is part of GCC. @@ -35,9 +35,6 @@ along with GCC; see the file COPYING3. If not see /* Tell collect2 to run dsymutil for us as necessary. */ #define COLLECT_RUN_DSYMUTIL 1 -/* libSystem contains unwind information for signal frames. */ -#define DARWIN_LIBSYSTEM_HAS_UNWIND - #undef ASM_OUTPUT_ALIGNED_COMMON #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ do { \ diff --git a/gcc/config/i386/linux-unwind.h b/gcc/config/i386/linux-unwind.h deleted file mode 100644 index de44823e053..00000000000 --- a/gcc/config/i386/linux-unwind.h +++ /dev/null @@ -1,197 +0,0 @@ -/* DWARF2 EH unwinding support for AMD x86-64 and x86. - Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 - Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. - Don't use this at all if inhibit_libc is used. */ - -#ifndef inhibit_libc - -#ifdef __x86_64__ - -#include -#include - -#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state - -static _Unwind_Reason_Code -x86_64_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - long new_cfa; - - /* movq __NR_rt_sigreturn, %rax ; syscall */ - if (*(unsigned char *)(pc+0) == 0x48 - && *(unsigned long *)(pc+1) == 0x050f0000000fc0c7) - { - struct ucontext *uc_ = context->cfa; - /* The void * cast is necessary to avoid an aliasing warning. - The aliasing warning is correct, but should not be a problem - because it does not alias anything. */ - sc = (struct sigcontext *) (void *) &uc_->uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = sc->rsp; - fs->regs.cfa_how = CFA_REG_OFFSET; - /* Register 7 is rsp */ - fs->regs.cfa_reg = 7; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&sc->rax - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&sc->rdx - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&sc->rcx - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&sc->rbx - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; - fs->regs.reg[4].loc.offset = (long)&sc->rsi - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&sc->rdi - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&sc->rbp - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&sc->r8 - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; - fs->regs.reg[9].loc.offset = (long)&sc->r9 - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; - fs->regs.reg[10].loc.offset = (long)&sc->r10 - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; - fs->regs.reg[11].loc.offset = (long)&sc->r11 - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; - fs->regs.reg[12].loc.offset = (long)&sc->r12 - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; - fs->regs.reg[13].loc.offset = (long)&sc->r13 - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; - fs->regs.reg[14].loc.offset = (long)&sc->r14 - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; - fs->regs.reg[15].loc.offset = (long)&sc->r15 - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; - fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa; - fs->retaddr_column = 16; - fs->signal_frame = 1; - return _URC_NO_REASON; -} - -#else /* ifdef __x86_64__ */ - -/* There's no sys/ucontext.h for glibc 2.0, so no - signal-turned-exceptions for them. There's also no configure-run for - the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the - target libc version macro should be enough. */ -#if defined __GLIBC__ && !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) - -#include -#include - -#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state - -static _Unwind_Reason_Code -x86_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - long new_cfa; - - /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ - if (*(unsigned short *)(pc+0) == 0xb858 - && *(unsigned int *)(pc+2) == 119 - && *(unsigned short *)(pc+6) == 0x80cd) - sc = context->cfa + 4; - /* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ - else if (*(unsigned char *)(pc+0) == 0xb8 - && *(unsigned int *)(pc+1) == 173 - && *(unsigned short *)(pc+5) == 0x80cd) - { - struct rt_sigframe { - int sig; - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - } *rt_ = context->cfa; - /* The void * cast is necessary to avoid an aliasing warning. - The aliasing warning is correct, but should not be a problem - because it does not alias anything. */ - sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = sc->esp; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 4; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&sc->eax - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&sc->ebx - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&sc->ecx - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&sc->edx - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&sc->esi - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; - fs->regs.reg[7].loc.offset = (long)&sc->edi - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&sc->ebp - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&sc->eip - new_cfa; - fs->retaddr_column = 8; - fs->signal_frame = 1; - return _URC_NO_REASON; -} - -#define MD_FROB_UPDATE_CONTEXT x86_frob_update_context - -/* Fix up for kernels that have vDSO, but don't have S flag in it. */ - -static void -x86_frob_update_context (struct _Unwind_Context *context, - _Unwind_FrameState *fs ATTRIBUTE_UNUSED) -{ - unsigned char *pc = context->ra; - - /* movl $__NR_rt_sigreturn,%eax ; {int $0x80 | syscall} */ - if (*(unsigned char *)(pc+0) == 0xb8 - && *(unsigned int *)(pc+1) == 173 - && (*(unsigned short *)(pc+5) == 0x80cd - || *(unsigned short *)(pc+5) == 0x050f)) - _Unwind_SetSignalFrame (context, 1); -} - -#endif /* not glibc 2.0 */ -#endif /* ifdef __x86_64__ */ -#endif /* ifdef inhibit_libc */ diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h index 833416d59a5..73681fe82f6 100644 --- a/gcc/config/i386/linux.h +++ b/gcc/config/i386/linux.h @@ -22,5 +22,3 @@ along with GCC; see the file COPYING3. If not see #define GNU_USER_LINK_EMULATION "elf_i386" #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2" - -#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h" diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h index 99d62496860..9bf7eab04af 100644 --- a/gcc/config/i386/linux64.h +++ b/gcc/config/i386/linux64.h @@ -26,5 +26,3 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2" #define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2" - -#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h" diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index 6ae7799359d..c1c12778d70 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -241,12 +241,6 @@ __enable_execute_stack (void *addr) \ #include #endif -/* For 64-bit Windows we can't use DW2 unwind info. Also for multilib - builds we can't use it, too. */ -#if !TARGET_64BIT_DEFAULT && !defined (TARGET_BI_ARCH) -#define MD_UNWIND_SUPPORT "config/i386/w32-unwind.h" -#endif - /* This matches SHLIB_SONAME and SHLIB_SOVERSION in t-cygming. */ /* This matches SHLIB_SONAME and SHLIB_SOVERSION in t-cygwin. */ #if DWARF2_UNWIND_INFO diff --git a/gcc/config/i386/sol2-unwind.h b/gcc/config/i386/sol2-unwind.h deleted file mode 100644 index d93b60c781c..00000000000 --- a/gcc/config/i386/sol2-unwind.h +++ /dev/null @@ -1,289 +0,0 @@ -/* DWARF2 EH unwinding support for AMD x86-64 and x86. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#include -#include - -#ifdef __x86_64__ - -#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state - -static _Unwind_Reason_Code -x86_64_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - mcontext_t *mctx; - long new_cfa; - - if (/* Solaris 10+ - ------------ - <__sighndlr+0>: push %rbp - <__sighndlr+1>: mov %rsp,%rbp - <__sighndlr+4>: callq *%rcx - <__sighndlr+6>: leaveq <--- PC - <__sighndlr+7>: retq */ - *(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855) - - /* We need to move up three frames: - - <-- context->cfa - __sighndlr - call_user_handler - sigacthandler - - - context->cfa points into the frame after the saved frame pointer and - saved pc (struct frame). - - The ucontext_t structure is in the kernel frame after the signal - number and a siginfo_t *. Since the frame sizes vary even within - Solaris 10 updates, we need to walk the stack to get there. */ - { - struct frame *fp = (struct frame *) context->cfa - 1; - struct handler_args { - int signo; - siginfo_t *sip; - ucontext_t ucontext; - } *handler_args; - ucontext_t *ucp; - - /* Next frame: __sighndlr frame pointer. */ - fp = (struct frame *) fp->fr_savfp; - /* call_user_handler frame pointer. */ - fp = (struct frame *) fp->fr_savfp; - /* sigacthandler frame pointer. */ - fp = (struct frame *) fp->fr_savfp; - - /* The argument area precedes the struct frame. */ - handler_args = (struct handler_args *) (fp + 1); - ucp = &handler_args->ucontext; - mctx = &ucp->uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = mctx->gregs[REG_RSP]; - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 7; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; - fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; - fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; - fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; - fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; - fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; - fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; - fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; - fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; - fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa; - fs->retaddr_column = 16; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} - -#else - -#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state - -static _Unwind_Reason_Code -x86_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - mcontext_t *mctx; - long new_cfa; - - if (/* Solaris 8 - single-threaded - ---------------------------- - : mov 0x10(%ebp),%esi - : push %esi - : pushl 0xc(%ebp) - : mov 0x8(%ebp),%ecx - : push %ecx - : mov offset(%ebx),%eax - : call *(%eax,%ecx,4) - : add $0xc,%esp <--- PC - : push %esi ... */ - (*(unsigned long *)(pc - 20) == 0x5610758b - && *(unsigned long *)(pc - 16) == 0x8b0c75ff - && *(unsigned long *)(pc - 12) == 0x8b51084d - && *(unsigned char *)(pc - 8) == 0x83 - && *(unsigned long *)(pc - 4) == 0x8814ff00 - && *(unsigned long *)(pc - 0) == 0x560cc483) - - || /* Solaris 8 - multi-threaded - --------------------------- - <__sighndlr+0>: push %ebp - <__sighndlr+1>: mov %esp,%ebp - <__sighndlr+3>: pushl 0x10(%ebp) - <__sighndlr+6>: pushl 0xc(%ebp) - <__sighndlr+9>: pushl 0x8(%ebp) - <__sighndlr+12>: call *0x14(%ebp) - <__sighndlr+15>: leave <--- PC */ - (*(unsigned long *)(pc - 15) == 0xffec8b55 - && *(unsigned long *)(pc - 11) == 0x75ff1075 - && *(unsigned long *)(pc - 7) == 0x0875ff0c - && *(unsigned long *)(pc - 3) == 0xc91455ff) - - || /* Solaris 9 - single-threaded - ---------------------------- - : mov 0x244(%ebx),%ecx - : mov 0x8(%ebp),%eax - : mov (%ecx,%eax,4),%ecx - : pushl 0x10(%ebp) - : pushl 0xc(%ebp) - : push %eax - : call *%ecx - : add $0xc,%esp <--- PC - : pushl 0x10(%ebp) */ - (*(unsigned long *)(pc - 21) == 0x2448b8b - && *(unsigned long *)(pc - 17) == 0x458b0000 - && *(unsigned long *)(pc - 13) == 0x810c8b08 - && *(unsigned long *)(pc - 9) == 0xff1075ff - && *(unsigned long *)(pc - 5) == 0xff500c75 - && *(unsigned long *)(pc - 1) == 0xcc483d1) - - || /* Solaris 9 - multi-threaded, Solaris 10 - --------------------------------------- - <__sighndlr+0>: push %ebp - <__sighndlr+1>: mov %esp,%ebp - <__sighndlr+3>: pushl 0x10(%ebp) - <__sighndlr+6>: pushl 0xc(%ebp) - <__sighndlr+9>: pushl 0x8(%ebp) - <__sighndlr+12>: call *0x14(%ebp) - <__sighndlr+15>: add $0xc,%esp <--- PC - <__sighndlr+18>: leave - <__sighndlr+19>: ret */ - (*(unsigned long *)(pc - 15) == 0xffec8b55 - && *(unsigned long *)(pc - 11) == 0x75ff1075 - && *(unsigned long *)(pc - 7) == 0x0875ff0c - && *(unsigned long *)(pc - 3) == 0x831455ff - && *(unsigned long *)(pc + 1) == 0xc3c90cc4) - - || /* Solaris 11 before snv_125 - -------------------------- - <__sighndlr+0> push %ebp - <__sighndlr+1> mov %esp,%ebp - <__sighndlr+4> pushl 0x10(%ebp) - <__sighndlr+6> pushl 0xc(%ebp) - <__sighndlr+9> pushl 0x8(%ebp) - <__sighndlr+12> call *0x14(%ebp) - <__sighndlr+15> add $0xc,%esp - <__sighndlr+18> leave <--- PC - <__sighndlr+19> ret */ - (*(unsigned long *)(pc - 18) == 0xffec8b55 - && *(unsigned long *)(pc - 14) == 0x7fff107f - && *(unsigned long *)(pc - 10) == 0x0875ff0c - && *(unsigned long *)(pc - 6) == 0x83145fff - && *(unsigned long *)(pc - 1) == 0xc3c90cc4) - - || /* Solaris 11 since snv_125 - ------------------------- - <__sighndlr+0> push %ebp - <__sighndlr+1> mov %esp,%ebp - <__sighndlr+3> and $0xfffffff0,%esp - <__sighndlr+6> sub $0x4,%esp - <__sighndlr+9> pushl 0x10(%ebp) - <__sighndlr+12> pushl 0xc(%ebp) - <__sighndlr+15> pushl 0x8(%ebp) - <__sighndlr+18> call *0x14(%ebp) - <__sighndlr+21> leave <--- PC - <__sighndlr+22> ret */ - (*(unsigned long *)(pc - 21) == 0x83ec8b55 - && *(unsigned long *)(pc - 17) == 0xec83f0e4 - && *(unsigned long *)(pc - 13) == 0x1075ff04 - && *(unsigned long *)(pc - 9) == 0xff0c75ff - && *(unsigned long *)(pc - 5) == 0x55ff0875 - && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914)) - { - struct handler_args { - int signo; - siginfo_t *sip; - ucontext_t *ucontext; - } *handler_args = context->cfa; - mctx = &handler_args->ucontext->uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = mctx->gregs[UESP]; - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 4; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; - fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa; - fs->retaddr_column = 8; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} - -#endif diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h index dc5b99e3a85..e466b03d0c9 100644 --- a/gcc/config/i386/sol2.h +++ b/gcc/config/i386/sol2.h @@ -171,5 +171,3 @@ along with GCC; see the file COPYING3. If not see #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "int" - -#define MD_UNWIND_SUPPORT "config/i386/sol2-unwind.h" diff --git a/gcc/config/i386/w32-unwind.h b/gcc/config/i386/w32-unwind.h deleted file mode 100644 index 449e9a9c5d6..00000000000 --- a/gcc/config/i386/w32-unwind.h +++ /dev/null @@ -1,204 +0,0 @@ -/* Definitions for Dwarf2 EH unwind support for Windows32 targets - Copyright (C) 2007, 2009, 2010 - Free Software Foundation, Inc. - Contributed by Pascal Obry - -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 -. */ - - -/* This file implements the md_fallback_frame_state_for routine for - Windows, triggered when the GCC table based unwinding process hits a - frame for which no unwind info has been registered. This typically - occurs when raising an exception from a signal handler, because the - handler is actually called from the OS kernel. - - The basic idea is to detect that we are indeed trying to unwind past a - signal handler and to fill out the GCC internal unwinding structures for - the OS kernel frame as if it had been directly called from the - interrupted context. - - This is all assuming that the code to set the handler asked the kernel - to pass a pointer to such context information. - - There is three main parts. - - 1) The first thing to do is to check if we are in a signal context. If - not we can just return as there is nothing to do. We are probably on - some foreign code for which no unwind frame can be found. If this is - a call from the Windows signal handler, then: - - 2) We must get the signal context information. - - * With the standard exception filter: - - This is on Windows pointed to by an EXCEPTION_POINTERS. We know that - the signal handle will call an UnhandledExceptionFilter with this - parameter. The spec for this routine is: - - LONG WINAPI UnhandledExceptionFilter(struct _EXCEPTION_POINTERS*); - - So the pointer to struct _EXCEPTION_POINTERS must be somewhere on the - stack. - - This was found experimentally to always be at offset 0 of the context - frame in all cases handled by this implementation. - - * With the SEH exception handler: - - In this case the signal context is directly on the stack as the SEH - exception handler has the following prototype: - - DWORD - SEH_error_handler (PEXCEPTION_RECORD ExceptionRecord, - PVOID EstablisherFrame, - PCONTEXT ContextRecord, - PVOID DispatcherContext) - - This was found experimentally to always be at offset 56 of the - context frame in all cases handled by this implementation. - - 3) When we have the signal context we just have to save some registers - and set the return address based on the program counter (Eip). - - Note that this implementation follows closely the same principles as the - GNU/Linux and OSF ones. */ - -#define WIN32_MEAN_AND_LEAN -#include -/* Patterns found experimentally to be on a Windows signal handler */ - -/* In a standard exception filter */ - -#define SIG_PAT1 \ - (pc_[-2] == 0xff && pc_[-1] == 0xd0 /* call %eax */ \ - && pc_[0] == 0x83 && pc_[1] == 0xf8) /* cmp 0xdepl,%eax */ - -#define SIG_PAT2 \ - (pc_[-5] == 0xe8 && pc_[-4] == 0x68 /* call (depl16) */ \ - && pc_[0] == 0xc3) /* ret */ - -/* In a Win32 SEH handler */ - -#define SIG_SEH1 \ - (pc_[-5] == 0xe8 /* call addr */ \ - && pc_[0] == 0x83 && pc_[1] == 0xc4 /* add 0xval,%esp */ \ - && pc_[3] == 0xb8) /* mov 0xval,%eax */ - -#define SIG_SEH2 \ - (pc_[-5] == 0x8b && pc_[-4] == 0x4d /* mov depl(%ebp),%ecx */ \ - && pc_[0] == 0x64 && pc_[1] == 0x8b) /* mov %fs:(0), */ \ - -/* In the GCC alloca (stack probing) */ - -#define SIG_ALLOCA \ - (pc_[-1] == 0x83 /* orl $0x0,(%ecx) */ \ - && pc_[0] == 0x9 && pc_[1] == 0 \ - && pc_[2] == 0x2d && pc_[3] == 0 /* subl $0x1000,%eax */ \ - && pc_[4] == 0x10 && pc_[5] == 0) - - -#define MD_FALLBACK_FRAME_STATE_FOR i386_w32_fallback_frame_state - -static _Unwind_Reason_Code -i386_w32_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) - -{ - void * ctx_ra_ = (void *)(context->ra); /* return address */ - void * ctx_cfa_ = (void *)(context->cfa); /* context frame address */ - unsigned char * pc_ = (unsigned char *) ctx_ra_; - - /* In the test below we look for two specific patterns found - experimentally to be in the Windows signal handler. */ - if (SIG_PAT1 || SIG_PAT2 || SIG_SEH1 || SIG_SEH2) - { - PEXCEPTION_POINTERS weinfo_; - PCONTEXT proc_ctx_; - long new_cfa_; - - if (SIG_SEH1) - proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 56)); - else if (SIG_SEH2) - proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 8)); - else - { - weinfo_ = (PEXCEPTION_POINTERS) (*(int*)ctx_cfa_); - proc_ctx_ = weinfo_->ContextRecord; - } - - /* The new context frame address is the stack pointer. */ - new_cfa_ = proc_ctx_->Esp; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column(); - fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; - - /* Restore registers. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)&proc_ctx_->Eax - new_cfa_; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[3].loc.offset = (long)&proc_ctx_->Ebx - new_cfa_; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long)&proc_ctx_->Ecx - new_cfa_; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[2].loc.offset = (long)&proc_ctx_->Edx - new_cfa_; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[6].loc.offset = (long)&proc_ctx_->Esi - new_cfa_; - fs->regs.reg[7].how = REG_SAVED_OFFSET; - fs->regs.reg[7].loc.offset = (long)&proc_ctx_->Edi - new_cfa_; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[5].loc.offset = (long)&proc_ctx_->Ebp - new_cfa_; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long)&proc_ctx_->Eip - new_cfa_; - fs->retaddr_column = 8; - fs->signal_frame = 1; - - return _URC_NO_REASON; - } - - /* Unwinding through _alloca, propagating from a trap triggered by - one of it's probes prior to the real SP adjustment. The only - operations of interest performed is "pushl %ecx", followed by - ecx clobbering. */ - else if (SIG_ALLOCA) - { - /* Only one push between entry in _alloca and the probe trap. */ - long new_cfa_ = (long) ctx_cfa_ + 4; - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column(); - fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; - - /* The saved value of %ecx is at CFA - 4 */ - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = -4; - - /* and what is stored at the CFA is the return address. */ - fs->retaddr_column = 8; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = 0; - fs->signal_frame = 1; - - return _URC_NO_REASON; - } - else - return _URC_END_OF_STACK; -} diff --git a/gcc/config/ia64/linux-unwind.h b/gcc/config/ia64/linux-unwind.h deleted file mode 100644 index 93f762de573..00000000000 --- a/gcc/config/ia64/linux-unwind.h +++ /dev/null @@ -1,199 +0,0 @@ -/* DWARF2 EH unwinding support for IA64 Linux. - Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. - - 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 - . */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-ia64.c for the structs. */ - -/* This works only for glibc-2.3 and later, because sigcontext is different - in glibc-2.2.4. */ - -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) -#include -#include - -#define IA64_GATE_AREA_START 0xa000000000000100LL -#define IA64_GATE_AREA_END 0xa000000000030000LL - -#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state - -static _Unwind_Reason_Code -ia64_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - if (context->rp >= IA64_GATE_AREA_START - && context->rp < IA64_GATE_AREA_END) - { - struct sigframe { - char scratch[16]; - unsigned long sig_number; - struct siginfo *info; - struct sigcontext *sc; - } *frame_ = (struct sigframe *)context->psp; - struct sigcontext *sc = frame_->sc; - - /* Restore scratch registers in case the unwinder needs to - refer to a value stored in one of them. */ - { - int i; - - for (i = 2; i < 4; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - for (i = 8; i < 12; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - for (i = 14; i < 32; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - } - - context->fpsr_loc = &(sc->sc_ar_fpsr); - context->signal_pfs_loc = &(sc->sc_ar_pfs); - context->lc_loc = &(sc->sc_ar_lc); - context->unat_loc = &(sc->sc_ar_unat); - context->br_loc[0] = &(sc->sc_br[0]); - context->br_loc[6] = &(sc->sc_br[6]); - context->br_loc[7] = &(sc->sc_br[7]); - context->pr = sc->sc_pr; - context->psp = sc->sc_gr[12]; - context->gp = sc->sc_gr[1]; - /* Signal frame doesn't have an associated reg. stack frame - other than what we adjust for below. */ - fs -> no_reg_stack_frame = 1; - - if (sc->sc_rbs_base) - { - /* Need to switch from alternate register backing store. */ - long ndirty, loadrs = sc->sc_loadrs >> 16; - unsigned long alt_bspstore = context->bsp - loadrs; - unsigned long bspstore; - unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); - - ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, - (unsigned long *) context->bsp); - bspstore = (unsigned long) - ia64_rse_skip_regs (ar_bsp, -ndirty); - ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, - sc->sc_ar_rnat); - } - - /* Don't touch the branch registers o.t. b0, b6 and b7. - The kernel doesn't pass the preserved branch registers - in the sigcontext but leaves them intact, so there's no - need to do anything with them here. */ - { - unsigned long sof = sc->sc_cfm & 0x7f; - context->bsp = (unsigned long) - ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); - } - - /* Account for use of br.ret to resume execution of user code. */ - fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; - fs->curr.reg[UNW_REG_RP].val - = (unsigned long)&(sc->sc_ip) - context->psp; - fs->curr.reg[UNW_REG_RP].when = -1; - - fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_SPREL; - fs->curr.reg[UNW_REG_PFS].val - = (unsigned long)&(sc->sc_cfm) - context->psp; - fs ->curr.reg[UNW_REG_PFS].when = -1; - - return _URC_NO_REASON; - } - return _URC_END_OF_STACK; -} - -#define MD_HANDLE_UNWABI ia64_handle_unwabi - -#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's') -#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i') -#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's') -#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i') - -static void -ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs) -{ - if (fs->unwabi == ABI_MARKER_LINUX_SIGTRAMP - || fs->unwabi == ABI_MARKER_OLD_LINUX_SIGTRAMP) - { - struct sigframe { - char scratch[16]; - unsigned long sig_number; - struct siginfo *info; - struct sigcontext *sc; - } *frame = (struct sigframe *)context->psp; - struct sigcontext *sc = frame->sc; - - /* Restore scratch registers in case the unwinder needs to - refer to a value stored in one of them. */ - { - int i; - - for (i = 2; i < 4; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - for (i = 8; i < 12; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - for (i = 14; i < 32; i++) - context->ireg[i - 2].loc = &sc->sc_gr[i]; - } - - context->signal_pfs_loc = &(sc->sc_ar_pfs); - context->lc_loc = &(sc->sc_ar_lc); - context->unat_loc = &(sc->sc_ar_unat); - context->br_loc[0] = &(sc->sc_br[0]); - context->br_loc[6] = &(sc->sc_br[6]); - context->br_loc[7] = &(sc->sc_br[7]); - context->pr = sc->sc_pr; - context->gp = sc->sc_gr[1]; - /* Signal frame doesn't have an associated reg. stack frame - other than what we adjust for below. */ - fs -> no_reg_stack_frame = 1; - - if (sc->sc_rbs_base) - { - /* Need to switch from alternate register backing store. */ - long ndirty, loadrs = sc->sc_loadrs >> 16; - unsigned long alt_bspstore = context->bsp - loadrs; - unsigned long bspstore; - unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); - - ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, - (unsigned long *) context->bsp); - bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty); - ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, - sc->sc_ar_rnat); - } - - /* Don't touch the branch registers o.t. b0, b6 and b7. - The kernel doesn't pass the preserved branch registers - in the sigcontext but leaves them intact, so there's no - need to do anything with them here. */ - { - unsigned long sof = sc->sc_cfm & 0x7f; - context->bsp = (unsigned long) - ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); - } - - /* The use of br.ret to resume execution of user code is already - accounted for in the unwind ABI. */ - } -} -#endif /* glibc-2.3 or better */ diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h index e6370ea3492..00b0ddba1a0 100644 --- a/gcc/config/ia64/linux.h +++ b/gcc/config/ia64/linux.h @@ -77,8 +77,6 @@ do { \ #undef LINK_EH_SPEC #define LINK_EH_SPEC "" -#define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h" - /* Put all *tf routines in libgcc. */ #undef LIBGCC2_HAS_TF_MODE #define LIBGCC2_HAS_TF_MODE 1 diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c index f935a0ca3e4..061bd4b8980 100644 --- a/gcc/config/ia64/unwind-ia64.c +++ b/gcc/config/ia64/unwind-ia64.c @@ -1,7 +1,7 @@ /* Subroutines needed for unwinding IA-64 standard format stack frame info for exception handling. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, - 2009 Free Software Foundation, Inc. + 2009, 2011 Free Software Foundation, Inc. Contributed by Andrew MacLeod Andrew Haley David Mosberger-Tang @@ -1767,9 +1767,7 @@ _Unwind_GetBSP (struct _Unwind_Context *context) return (_Unwind_Ptr) context->bsp; } -#ifdef MD_UNWIND_SUPPORT -#include MD_UNWIND_SUPPORT -#endif +#include "md-unwind-support.h" static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) diff --git a/gcc/config/ia64/vms-unwind.h b/gcc/config/ia64/vms-unwind.h deleted file mode 100644 index 41c76ae768c..00000000000 --- a/gcc/config/ia64/vms-unwind.h +++ /dev/null @@ -1,307 +0,0 @@ -/* DWARF2 EH unwinding support for IA64 VMS. - Copyright (C) 2005-2009 Free Software Foundation, Inc. - - 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 - . */ - -#include -#include -#include - -#define __int64 long long -#include - -#include -#include - -#define DYN$C_SSENTRY 66 -/* ??? would rather get the proper header file. */ - -#define MD_FALLBACK_FRAME_STATE_FOR ia64_vms_fallback_frame_state - -extern INVO_CONTEXT_BLK * LIB$I64_CREATE_INVO_CONTEXT (void); - -extern int LIB$I64_IS_EXC_DISPATCH_FRAME (void *); -extern int LIB$I64_IS_AST_DISPATCH_FRAME (void *); - -extern int LIB$I64_INIT_INVO_CONTEXT (INVO_CONTEXT_BLK *, int, int); -extern int LIB$I64_GET_CURR_INVO_CONTEXT (INVO_CONTEXT_BLK *); -extern int LIB$I64_GET_PREV_INVO_CONTEXT (INVO_CONTEXT_BLK *); - -typedef unsigned long ulong; -typedef unsigned int uint; -typedef unsigned long uw_reg; -typedef uw_reg * uw_loc; - -typedef char fp_reg[16]; - -#define DENOTES_VMS_DISPATCHER_FRAME(icb) \ -(LIB$I64_IS_EXC_DISPATCH_FRAME (&(icb)->libicb$ih_pc)) - -#define DENOTES_BOTTOM_OF_STACK(icb) ((icb)->libicb$v_bottom_of_stack) - -#define FAIL_IF(COND) \ - do { if (COND) { context->rp = 0; return _URC_END_OF_STACK; } } while (0) -/* Clearing context->rp is required to prevent the ia64 gcc unwinder from - attempting to keep on walking the call chain. */ - -static int -ia64_vms_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - int i, status; - - INVO_CONTEXT_BLK local_icb; - INVO_CONTEXT_BLK *icb = &local_icb; - - CHFCTX * chfctx; - CHF$MECH_ARRAY * chfmech; - CHF64$SIGNAL_ARRAY *chfsig64; - INTSTK * intstk; - - static int eh_debug = -1; - int try_bs_copy = 0; - /* Non zero to attempt copy of alternate backing store contents for - dirty partition in interrupted context. ??? Alpha code, only activated - on specific request via specific bit in EH_DEBUG. */ - - if (eh_debug == -1) - { - char * EH_DEBUG = getenv ("EH_DEBUG"); - const uint try_bs_copy_mask = (1 << 16); - - eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0; - - /* Fetch and clear the try_bs_copy bit. */ - try_bs_copy = (uint)eh_debug & try_bs_copy_mask; - eh_debug &= ~try_bs_copy_mask; - } - - /* We're called to attempt unwinding through a frame for which no unwind - info is available, typical of an operating system exception dispatcher - frame. The code below knows how to handle this case, and only this one, - returning a failure code if it finds it is not in this situation. - - Note that we're called from deep down in the exception propagation call - chain, possibly below an exception dispatcher but for a frame above it - like some os entry point. */ - - if (eh_debug) - printf ("FALLBACK - ctxt->rp=0x%lx, sp=0x%lx, psp=0x%lx, bsp=0x%lx\n", - context->rp, context->sp, context->psp, context->bsp); - - /* Step 0 : - ------------------------------------------------------------------------- - VMS-unwind up until we reach a VMS dispatcher frame corresponding to the - context we are trying to unwind through. Fail if get past this context or - if we reach the bottom of stack along the way. - ------------------------------------------------------------------------- - */ - - status = LIB$I64_INIT_INVO_CONTEXT (icb, LIBICB$K_INVO_CONTEXT_VERSION, 0); - FAIL_IF (status == 0); - - status = LIB$I64_GET_CURR_INVO_CONTEXT (icb); - - /* Beware: we might be unwinding through nested condition handlers, so the - dispatcher frame we seek might not be the first one on the way up. Loop - thus. */ - do { - - /* Seek the next dispatcher frame up the "current" point. Stop if we - either get past the target context or hit the bottom-of-stack along - the way. */ - status = LIB$I64_GET_PREV_INVO_CONTEXT (icb); - FAIL_IF (status == 0); - FAIL_IF ((uw_reg)icb->libicb$ih_sp > (uw_reg)context->psp - || DENOTES_BOTTOM_OF_STACK (icb)); - - if (eh_debug) - printf ("frame%s sp @ 0x%llx, pc @ 0x%llx bsp=0x%llx\n", - DENOTES_VMS_DISPATCHER_FRAME (icb) ? " (dispatcher)" : "", - icb->libicb$ih_sp, icb->libicb$ih_pc, icb->libicb$ih_bsp); - - /* Continue until the target frame is found. */ - } while ((uw_reg)icb->libicb$ih_bsp != (uw_reg)context->bsp); - - /* If this is not a dispatcher frame, this is certainly a frame for a leaf - subprogram. Use default unwind information. */ - if (! DENOTES_VMS_DISPATCHER_FRAME (icb)) - return _URC_END_OF_STACK; - - /* At this point, we know we are really trying to unwind past an exception - dispatcher frame, and have it described in ICB. Proceed. */ - - /* Step 1 : - ------------------------------------------------------------------------ - We have the VMS dispatcher frame ICB handy and know we are trying to - unwind past it. Fetch pointers to useful datastructures from there, then - unwind one step further up to the interrupted user context from which - some required values will be easily accessible. - ------------------------------------------------------------------------ - */ - - chfctx = icb->libicb$ph_chfctx_addr; - FAIL_IF (chfctx == 0); - - chfmech = (CHF$MECH_ARRAY *)chfctx->chfctx$q_mcharglst; - FAIL_IF (chfmech == 0); - - chfsig64 = (CHF64$SIGNAL_ARRAY *)chfmech->chf$ph_mch_sig64_addr; - FAIL_IF (chfsig64 == 0); - - intstk = (INTSTK *)chfmech->chf$q_mch_esf_addr; - FAIL_IF (intstk == 0 || intstk->intstk$b_subtype == DYN$C_SSENTRY); - - status = LIB$I64_GET_PREV_INVO_CONTEXT (icb); - FAIL_IF (status == 0); - - if (eh_debug) - printf ("User frame, " - "chfmech @ 0x%lx, chfsig64 @ 0x%lx, intstk @ 0x%lx\n", - (ulong)chfmech, (ulong)chfsig64, (ulong)intstk); - - /* Step 2 : - ------------------------------------------------------------------------ - Point the GCC context locations/values required for further unwinding at - their corresponding locations/values in the datastructures at hand. - ------------------------------------------------------------------------ - */ - - /* Static General Register locations, including scratch registers in case - the unwinder needs to refer to a value stored in one of them. */ - { - uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_regbase; - - for (i = 2; i <= 3; i++) - context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; - for (i = 8; i <= 11; i++) - context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; - for (i = 14; i <= 31; i++) - context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; - } - - /* Static Floating Point Register locations, as available from the - mechargs array, which happens to include all the to be preserved - ones + others. */ - { - fp_reg * ctxregs; - - ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf2; - for (i = 2; i <= 5 ; i++) - context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 2]; - - ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf12; - for (i = 12; i <= 31 ; i++) - context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 12]; - } - - /* Relevant application register locations. */ - - context->fpsr_loc = (uw_loc)&intstk->intstk$q_fpsr; - context->lc_loc = (uw_loc)&intstk->intstk$q_lc; - context->unat_loc = (uw_loc)&intstk->intstk$q_unat; - - /* Branch register locations. */ - - { - uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_b0; - - for (i = 0; i < 8; i++) - context->br_loc[i] = (uw_loc)&ctxregs[i]; - } - - /* Necessary register values. */ - - /* ??? Still unclear if we need to account for possible flushes to an - alternate backing store (maybe the unwinding performed above did the - trick already) and how this would be handled. Blind alpha tentative - below for experimentation purposes in malfunctioning cases. */ - { - ulong q_bsp = (ulong) intstk->intstk$q_bsp; - ulong q_bspstore = (ulong) intstk->intstk$q_bspstore; - ulong q_bspbase = (ulong) intstk->intstk$q_bspbase; - ulong ih_bspbase = (ulong) icb->libicb$ih_bspbase; - - if (eh_debug) - printf ("q_bspstore = 0x%lx, q_bsp = 0x%lx, q_bspbase = 0x%lx\n" - "ih_bspbase = 0x%lx\n", - q_bspstore, q_bsp, q_bspbase, ih_bspbase); - - /* We witness many situations where q_bspbase is set while ih_bspbase is - null, and every attempt made with q_bspbase badly failed while doing - nothing resulted in proper behavior. */ - if (q_bspstore < q_bsp && ih_bspbase && try_bs_copy) - { - ulong dirty_size = q_bsp - q_bspstore; - ulong q_rnat = (ulong) intstk->intstk$q_rnat; - - if (eh_debug) - printf ("Attempting an alternate backing store copy ...\n"); - - ia64_copy_rbs - (context, q_bspstore, ih_bspbase, dirty_size, q_rnat); - /* Not clear if these are the proper arguments here. This is what - looked the closest to what is performed in the Linux case. */ - } - - } - - context->bsp = (uw_reg)intstk->intstk$q_bsp; - fs->no_reg_stack_frame = 1; - - context->pr = (uw_reg)intstk->intstk$q_preds; - context->gp = (uw_reg)intstk->intstk$q_gp; - - /* We're directly setting up the "context" for a VMS exception handler. - The "previous SP" for it is the SP upon the handler's entry, that is - the SP at the condition/interruption/exception point. */ - context->psp = (uw_reg)icb->libicb$ih_sp; - - /* Previous Frame State location. What eventually ends up in pfs_loc is - installed with ar.pfs = pfs_loc; br.ret; so setup to target intstk->q_ifs - to have the interrupted context restored and not that of its caller if - we happen to have a handler in the interrupted context itself. */ - fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_PSPREL; - fs->curr.reg[UNW_REG_PFS].val - = (uw_reg)&intstk->intstk$q_ifs - (uw_reg)context->psp; - fs->curr.reg[UNW_REG_PFS].when = -1; - - /* If we need to unwind further up, past the interrupted context, we need to - hand out the interrupted context's pfs, still. */ - context->signal_pfs_loc = (uw_loc) &intstk->intstk$q_pfs; - - /* Finally, rules for RP . */ - { - uw_reg * post_sigarray - = (uw_reg *)chfsig64 + 1 + chfsig64->chf64$l_sig_args; - - uw_reg * ih_pc_loc = post_sigarray - 2; - - fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_PSPREL; - fs->curr.reg[UNW_REG_RP].val - = (uw_reg)ih_pc_loc - (uw_reg)context->psp; - fs->curr.reg[UNW_REG_RP].when = -1; - } - - return _URC_NO_REASON; -} - diff --git a/gcc/config/ia64/vms.h b/gcc/config/ia64/vms.h index 777fa34d9a9..5d87e711856 100644 --- a/gcc/config/ia64/vms.h +++ b/gcc/config/ia64/vms.h @@ -185,8 +185,6 @@ typedef struct crtl_name_spec /* Define this to be nonzero if static stack checking is supported. */ #define STACK_CHECK_STATIC_BUILTIN 1 -#define MD_UNWIND_SUPPORT "config/ia64/vms-unwind.h" - #define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L) #define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) (!UNW_IVMS_MODE (HEADER)) diff --git a/gcc/config/m68k/linux-unwind.h b/gcc/config/m68k/linux-unwind.h deleted file mode 100644 index 053c15558ca..00000000000 --- a/gcc/config/m68k/linux-unwind.h +++ /dev/null @@ -1,158 +0,0 @@ -/* DWARF2 EH unwinding support for Linux/m68k. - Copyright (C) 2006, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. - Don't use this at all if inhibit_libc is used. */ - -#ifndef inhibit_libc - -#include - -/* is unfortunately broken right now. */ -struct uw_ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - unsigned long uc_filler[80]; - __sigset_t uc_sigmask; -}; - -#define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state - -#ifdef __mcoldfire__ -#define M68K_FP_SIZE 8 -#else -#define M68K_FP_SIZE 12 -#endif - -static _Unwind_Reason_Code -m68k_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned short *pc = context->ra; - long cfa; - - /* moveq #__NR_sigreturn,%d0; trap #0 */ - if (pc[0] == 0x7077 && pc[1] == 0x4e40) - { - struct sigcontext *sc; - - /* Context is passed as the 3rd argument. */ - sc = *(struct sigcontext **) (context->cfa + 8); - - cfa = sc->sc_usp; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 15; - fs->regs.cfa_offset = cfa - (long) context->cfa; - - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long) &sc->sc_d0 - cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[1].loc.offset = (long) &sc->sc_d1 - cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; - fs->regs.reg[8].loc.offset = (long) &sc->sc_a0 - cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; - fs->regs.reg[9].loc.offset = (long) &sc->sc_a1 - cfa; - -#ifdef __uClinux__ - fs->regs.reg[13].how = REG_SAVED_OFFSET; - fs->regs.reg[13].loc.offset = (long) &sc->sc_a5 - cfa; -#endif - - fs->regs.reg[24].how = REG_SAVED_OFFSET; - fs->regs.reg[24].loc.offset = (long) &sc->sc_pc - cfa; - -#ifndef __uClinux__ - if (*(int *) sc->sc_fpstate) - { - int *fpregs = (int *) sc->sc_fpregs; - - fs->regs.reg[16].how = REG_SAVED_OFFSET; - fs->regs.reg[16].loc.offset = (long) &fpregs[0] - cfa; - fs->regs.reg[17].how = REG_SAVED_OFFSET; - fs->regs.reg[17].loc.offset = (long) &fpregs[M68K_FP_SIZE/4] - cfa; - } -#elif defined __mcffpu__ -# error Implement this when uClinux kernel is ported to an FPU architecture -#endif - } -#ifdef __mcoldfire__ - /* move.l #__NR_rt_sigreturn,%d0; trap #0 */ - else if (pc[0] == 0x203c && pc[1] == 0x0000 && - pc[2] == 0x00ad && pc[3] == 0x4e40) -#else - /* moveq #~__NR_rt_sigreturn,%d0; not.b %d0; trap #0 */ - else if (pc[0] == 0x7052 && pc[1] == 0x4600 && pc[2] == 0x4e40) -#endif - { - struct uw_ucontext *uc; - greg_t *gregs; - int i; - - /* Context is passed as the 3rd argument. */ - uc = *(struct uw_ucontext **) (context->cfa + 8); - - gregs = uc->uc_mcontext.gregs; - cfa = gregs[15]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 15; - fs->regs.cfa_offset = cfa - (long) context->cfa; - - /* register %d0-%d7/%a0-%a6 */ - for (i = 0; i <= 14; i++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = (long) &gregs[i] - cfa; - } - - /* return address */ - fs->regs.reg[24].how = REG_SAVED_OFFSET; - fs->regs.reg[24].loc.offset = (long) &gregs[16] - cfa; - -#define uc_fpstate uc_filler[0] - - if (uc->uc_fpstate) - { - long fpregs = (long) uc->uc_mcontext.fpregs.f_fpregs; - - /* register %fp0-%fp7 */ - for (i = 16; i <= 23; i++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = fpregs - cfa; - fpregs += M68K_FP_SIZE; - } - } - } - else - return _URC_END_OF_STACK; - - fs->retaddr_column = 24; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} -#endif /* ifdef inhibit_libc */ diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h index 6c07e261a6c..70738d221bf 100644 --- a/gcc/config/m68k/linux.h +++ b/gcc/config/m68k/linux.h @@ -235,5 +235,3 @@ along with GCC; see the file COPYING3. If not see #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE BITS_PER_WORD - -#define MD_UNWIND_SUPPORT "config/m68k/linux-unwind.h" diff --git a/gcc/config/mips/linux-unwind.h b/gcc/config/mips/linux-unwind.h deleted file mode 100644 index 02f7cd54c5a..00000000000 --- a/gcc/config/mips/linux-unwind.h +++ /dev/null @@ -1,120 +0,0 @@ -/* DWARF2 EH unwinding support for MIPS Linux. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - -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 -. */ - -#ifndef inhibit_libc -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#include -#include - -/* The third parameter to the signal handler points to something with - * this structure defined in asm/ucontext.h, but the name clashes with - * struct ucontext from sys/ucontext.h so this private copy is used. */ -typedef struct _sig_ucontext { - unsigned long uc_flags; - struct _sig_ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; -} _sig_ucontext_t; - -#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state - -static _Unwind_Reason_Code -mips_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - u_int32_t *pc = (u_int32_t *) context->ra; - struct sigcontext *sc; - _Unwind_Ptr new_cfa, reg_offset; - int i; - - /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ - /* 0000000c syscall */ - /* or */ - /* 24021017 li v0, 0x1017 (sigreturn) */ - /* 0000000c syscall */ - if (pc[1] != 0x0000000c) - return _URC_END_OF_STACK; -#if _MIPS_SIM == _ABIO32 - if (pc[0] == (0x24020000 | __NR_sigreturn)) - { - struct sigframe { - u_int32_t ass[4]; /* Argument save space for o32. */ - u_int32_t trampoline[2]; - struct sigcontext sigctx; - } *rt_ = context->cfa; - sc = &rt_->sigctx; - } - else -#endif - if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) - { - struct rt_sigframe { - u_int32_t ass[4]; /* Argument save space for o32. */ - u_int32_t trampoline[2]; - struct siginfo info; - _sig_ucontext_t uc; - } *rt_ = context->cfa; - sc = &rt_->uc.uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = (_Unwind_Ptr) sc; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = STACK_POINTER_REGNUM; - fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; - - /* On o32 Linux, the register save slots in the sigcontext are - eight bytes. We need the lower half of each register slot, - so slide our view of the structure back four bytes. */ -#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__ - reg_offset = 4; -#else - reg_offset = 0; -#endif - - for (i = 0; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = (_Unwind_Ptr)&(sc->sc_regs[i]) + reg_offset - new_cfa; - } - /* "PC & -2" points to the faulting instruction, but the unwind code - searches for "(ADDR & -2) - 1". (See MASK_RETURN_ADDR for the source - of the -2 mask.) Adding 2 here ensures that "(ADDR & -2) - 1" is the - address of the second byte of the faulting instruction. - - Note that setting fs->signal_frame would not work. As the comment - above MASK_RETURN_ADDR explains, MIPS unwinders must earch for an - odd-valued address. */ - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_VAL_OFFSET; - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset - = (_Unwind_Ptr)(sc->sc_pc) + 2 - new_cfa; - fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; - - return _URC_NO_REASON; -} -#endif diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h index aef37bd8f58..544a99f2d0b 100644 --- a/gcc/config/mips/linux.h +++ b/gcc/config/mips/linux.h @@ -99,8 +99,6 @@ along with GCC; see the file COPYING3. If not see %{!shared: \ %{profile:-lc_p} %{!profile:-lc}}" -#define MD_UNWIND_SUPPORT "config/mips/linux-unwind.h" - #ifdef HAVE_AS_NO_SHARED /* Default to -mno-shared for non-PIC. */ # define NO_SHARED_SPECS \ diff --git a/gcc/config/pa/hpux-unwind.h b/gcc/config/pa/hpux-unwind.h deleted file mode 100644 index 92061ec3677..00000000000 --- a/gcc/config/pa/hpux-unwind.h +++ /dev/null @@ -1,361 +0,0 @@ -/* DWARF2 EH unwinding support for PA HP-UX. - Copyright (C) 2005, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -/* Don't use this if inhibit_libc is set. - The build for this target will fail trying to include missing headers. */ -#ifndef inhibit_libc -#include -#include -#include - -/* FIXME: We currently ignore the high halves of general, space and - control registers on PA 2.0 machines for applications using the - 32-bit runtime. We don't restore space registers or the floating - point status registers. */ - -#define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state - -/* HP-UX 10.X doesn't define GetSSReg. */ -#ifndef GetSSReg -#define GetSSReg(ssp, ss_reg) \ - ((UseWideRegs (ssp)) \ - ? (ssp)->ss_wide.ss_32.ss_reg ## _lo \ - : (ssp)->ss_narrow.ss_reg) -#endif - -#if TARGET_64BIT -#define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg)) -#else -#define GetSSRegAddr(ssp, ss_reg) \ - ((UseWideRegs (ssp)) \ - ? (long) &((ssp)->ss_wide.ss_32.ss_reg ## _lo) \ - : (long) &((ssp)->ss_narrow.ss_reg)) -#endif - -#define UPDATE_FS_FOR_SAR(FS, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa - -#define UPDATE_FS_FOR_GR(FS, GRN, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa - -#define UPDATE_FS_FOR_FR(FS, FRN, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa; - -#define UPDATE_FS_FOR_PC(FS, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa - -/* Extract bit field from word using HP's numbering (MSB = 0). */ -#define GET_FIELD(X, FROM, TO) \ - ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) - -static inline int -sign_extend (int x, int len) -{ - int signbit = (1 << (len - 1)); - int mask = (signbit << 1) - 1; - return ((x & mask) ^ signbit) - signbit; -} - -/* Extract a 17-bit signed constant from branch instructions. */ -static inline int -extract_17 (unsigned word) -{ - return sign_extend (GET_FIELD (word, 19, 28) - | GET_FIELD (word, 29, 29) << 10 - | GET_FIELD (word, 11, 15) << 11 - | (word & 0x1) << 16, 17); -} - -/* Extract a 22-bit signed constant from branch instructions. */ -static inline int -extract_22 (unsigned word) -{ - return sign_extend (GET_FIELD (word, 19, 28) - | GET_FIELD (word, 29, 29) << 10 - | GET_FIELD (word, 11, 15) << 11 - | GET_FIELD (word, 6, 10) << 16 - | (word & 0x1) << 21, 22); -} - -static _Unwind_Reason_Code -pa_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - static long cpu; - unsigned int *pc = (unsigned int *) context->ra; - - if (pc == 0) - return _URC_END_OF_STACK; - - /* Check for relocation of the return value. */ - if (!TARGET_64BIT - && *(pc + 0) == 0x2fd01224 /* fstd,ma fr4,8(sp) */ - && *(pc + 1) == 0x0fd9109d /* ldw -4(sp),ret1 */ - && *(pc + 2) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */ - pc += 3; - else if (!TARGET_64BIT - && *(pc + 0) == 0x27d01224 /* fstw,ma fr4,8(sp) */ - && *(pc + 1) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */ - pc += 2; - else if (!TARGET_64BIT - && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */ - && *(pc + 1) == 0x0fdd1299 /* stw ret1,-4(sp) */ - && *(pc + 2) == 0x2fd13024) /* fldd,mb -8(sp),fr4 */ - pc += 3; - else if (!TARGET_64BIT - && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */ - && *(pc + 1) == 0x27d13024) /* fldw,mb -8(sp),fr4 */ - pc += 2; - - /* Check if the return address points to an export stub (PA 1.1 or 2.0). */ - if ((!TARGET_64BIT - && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */ - && *(pc + 1) == 0x004010a1 /* ldsid (rp),r1 */ - && *(pc + 2) == 0x00011820 /* mtsp r1,sr0 */ - && *(pc + 3) == 0xe0400002) /* be,n 0(sr0,rp) */ - || - (!TARGET_64BIT - && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */ - && *(pc + 1) == 0xe840d002)) /* bve,n (rp) */ - { - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 30; - fs->regs.cfa_offset = 0; - - fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = -24; - - /* Update context to describe the stub frame. */ - uw_update_context (context, fs); - - /* Set up fs to describe the FDE for the caller of this stub. */ - return uw_frame_state_for (context, fs); - } - /* Check if the return address points to a relocation stub. */ - else if (!TARGET_64BIT - && *(pc + 0) == 0x0fd11082 /* ldw -8(sp),rp */ - && (*(pc + 1) == 0xe840c002 /* bv,n r0(rp) */ - || *(pc + 1) == 0xe840d002)) /* bve,n (rp) */ - { - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 30; - fs->regs.cfa_offset = 0; - - fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = -8; - - /* Update context to describe the stub frame. */ - uw_update_context (context, fs); - - /* Set up fs to describe the FDE for the caller of this stub. */ - return uw_frame_state_for (context, fs); - } - - /* Check if the return address is an export stub as signal handlers - may return via an export stub. */ - if (!TARGET_64BIT - && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */ - && *(pc + 1) == 0x08000240 /* nop */ - && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */ - && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */ - && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */ - && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */ - /* Extract target address from PA 1.x 17-bit branch. */ - pc += extract_17 (*pc) + 2; - else if (!TARGET_64BIT - && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */ - && *(pc + 1) == 0x08000240 /* nop */ - && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */ - && *(pc + 3) == 0xe840d002) /* bve,n (rp) */ - /* Extract target address from PA 2.0 22-bit branch. */ - pc += extract_22 (*pc) + 2; - - /* Now check if the return address is one of the signal handler - returns, _sigreturn or _sigsetreturn. */ - if ((TARGET_64BIT - && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */ - && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */ - && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */ - && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */ - && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */ - || - (TARGET_64BIT - && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */ - && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */ - && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */ - && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */ - && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */ - || - (!TARGET_64BIT - && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */ - && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */ - && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */ - && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */ - && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */ - || - (!TARGET_64BIT - && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */ - && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */ - && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */ - && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */ - { - /* The previous stack pointer is saved at (long *)SP - 1. The - ucontext structure is offset from the start of the previous - frame by the siglocal_misc structure. */ - struct siglocalx *sl = (struct siglocalx *) - (*((long *) context->cfa - 1)); - mcontext_t *mc = &(sl->sl_uc.uc_mcontext); - - long new_cfa = GetSSReg (mc, ss_sp); - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 30; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - UPDATE_FS_FOR_GR (fs, 1, 1); - UPDATE_FS_FOR_GR (fs, 2, 2); - UPDATE_FS_FOR_GR (fs, 3, 3); - UPDATE_FS_FOR_GR (fs, 4, 4); - UPDATE_FS_FOR_GR (fs, 5, 5); - UPDATE_FS_FOR_GR (fs, 6, 6); - UPDATE_FS_FOR_GR (fs, 7, 7); - UPDATE_FS_FOR_GR (fs, 8, 8); - UPDATE_FS_FOR_GR (fs, 9, 9); - UPDATE_FS_FOR_GR (fs, 10, 10); - UPDATE_FS_FOR_GR (fs, 11, 11); - UPDATE_FS_FOR_GR (fs, 12, 12); - UPDATE_FS_FOR_GR (fs, 13, 13); - UPDATE_FS_FOR_GR (fs, 14, 14); - UPDATE_FS_FOR_GR (fs, 15, 15); - UPDATE_FS_FOR_GR (fs, 16, 16); - UPDATE_FS_FOR_GR (fs, 17, 17); - UPDATE_FS_FOR_GR (fs, 18, 18); - UPDATE_FS_FOR_GR (fs, 19, 19); - UPDATE_FS_FOR_GR (fs, 20, 20); - UPDATE_FS_FOR_GR (fs, 21, 21); - UPDATE_FS_FOR_GR (fs, 22, 22); - UPDATE_FS_FOR_GR (fs, 23, 23); - UPDATE_FS_FOR_GR (fs, 24, 24); - UPDATE_FS_FOR_GR (fs, 25, 25); - UPDATE_FS_FOR_GR (fs, 26, 26); - UPDATE_FS_FOR_GR (fs, 27, 27); - UPDATE_FS_FOR_GR (fs, 28, 28); - UPDATE_FS_FOR_GR (fs, 29, 29); - UPDATE_FS_FOR_GR (fs, 30, 30); - UPDATE_FS_FOR_GR (fs, 31, 31); - - if (TARGET_64BIT) - { - UPDATE_FS_FOR_FR (fs, 4, 32); - UPDATE_FS_FOR_FR (fs, 5, 33); - UPDATE_FS_FOR_FR (fs, 6, 34); - UPDATE_FS_FOR_FR (fs, 7, 35); - UPDATE_FS_FOR_FR (fs, 8, 36); - UPDATE_FS_FOR_FR (fs, 9, 37); - UPDATE_FS_FOR_FR (fs, 10, 38); - UPDATE_FS_FOR_FR (fs, 11, 39); - UPDATE_FS_FOR_FR (fs, 12, 40); - UPDATE_FS_FOR_FR (fs, 13, 41); - UPDATE_FS_FOR_FR (fs, 14, 42); - UPDATE_FS_FOR_FR (fs, 15, 43); - UPDATE_FS_FOR_FR (fs, 16, 44); - UPDATE_FS_FOR_FR (fs, 17, 45); - UPDATE_FS_FOR_FR (fs, 18, 46); - UPDATE_FS_FOR_FR (fs, 19, 47); - UPDATE_FS_FOR_FR (fs, 20, 48); - UPDATE_FS_FOR_FR (fs, 21, 49); - UPDATE_FS_FOR_FR (fs, 22, 50); - UPDATE_FS_FOR_FR (fs, 23, 51); - UPDATE_FS_FOR_FR (fs, 24, 52); - UPDATE_FS_FOR_FR (fs, 25, 53); - UPDATE_FS_FOR_FR (fs, 26, 54); - UPDATE_FS_FOR_FR (fs, 27, 55); - UPDATE_FS_FOR_FR (fs, 28, 56); - UPDATE_FS_FOR_FR (fs, 29, 57); - UPDATE_FS_FOR_FR (fs, 30, 58); - UPDATE_FS_FOR_FR (fs, 31, 59); - - UPDATE_FS_FOR_SAR (fs, 60); - } - else - { - UPDATE_FS_FOR_FR (fs, 4, 32); - UPDATE_FS_FOR_FR (fs, 5, 34); - UPDATE_FS_FOR_FR (fs, 6, 36); - UPDATE_FS_FOR_FR (fs, 7, 38); - UPDATE_FS_FOR_FR (fs, 8, 40); - UPDATE_FS_FOR_FR (fs, 9, 44); - UPDATE_FS_FOR_FR (fs, 10, 44); - UPDATE_FS_FOR_FR (fs, 11, 46); - UPDATE_FS_FOR_FR (fs, 12, 48); - UPDATE_FS_FOR_FR (fs, 13, 50); - UPDATE_FS_FOR_FR (fs, 14, 52); - UPDATE_FS_FOR_FR (fs, 15, 54); - - if (!cpu) - cpu = sysconf (_SC_CPU_VERSION); - - /* PA-RISC 1.0 only has 16 floating point registers. */ - if (cpu != CPU_PA_RISC1_0) - { - UPDATE_FS_FOR_FR (fs, 16, 56); - UPDATE_FS_FOR_FR (fs, 17, 58); - UPDATE_FS_FOR_FR (fs, 18, 60); - UPDATE_FS_FOR_FR (fs, 19, 62); - UPDATE_FS_FOR_FR (fs, 20, 64); - UPDATE_FS_FOR_FR (fs, 21, 66); - UPDATE_FS_FOR_FR (fs, 22, 68); - UPDATE_FS_FOR_FR (fs, 23, 70); - UPDATE_FS_FOR_FR (fs, 24, 72); - UPDATE_FS_FOR_FR (fs, 25, 74); - UPDATE_FS_FOR_FR (fs, 26, 76); - UPDATE_FS_FOR_FR (fs, 27, 78); - UPDATE_FS_FOR_FR (fs, 28, 80); - UPDATE_FS_FOR_FR (fs, 29, 82); - UPDATE_FS_FOR_FR (fs, 30, 84); - UPDATE_FS_FOR_FR (fs, 31, 86); - } - - UPDATE_FS_FOR_SAR (fs, 88); - } - - fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; - UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN); - fs->signal_frame = 1; - - return _URC_NO_REASON; - } - - return _URC_END_OF_STACK; -} -#endif /* inhibit_libc */ diff --git a/gcc/config/pa/linux-unwind.h b/gcc/config/pa/linux-unwind.h deleted file mode 100644 index a0560e97445..00000000000 --- a/gcc/config/pa/linux-unwind.h +++ /dev/null @@ -1,141 +0,0 @@ -/* DWARF2 EH unwinding support for PA Linux. - Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. - -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 -. */ - - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -/* Don't use this if inhibit_libc is set. - The build for this target will fail trying to include missing headers. */ -#ifndef inhibit_libc -#include -#include - -/* Unfortunately, because of various bugs and changes to the kernel, - we have several cases to deal with. - - In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should - point directly at the beginning of the trampoline and struct rt_sigframe. - - In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and - (CONTEXT)->ra points at the 4th word in the trampoline structure. This - is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4. - - To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes - to get the beginning of the signal frame, and then check offsets 0, 4 - and 5 to see if we found the beginning of the trampoline. This will - tell us how to locate the sigcontext structure. - - Note that with a 2.4 64-bit kernel, the signal context is not properly - passed back to userspace so the unwind will not work correctly. */ - -#define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state - -static _Unwind_Reason_Code -pa32_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned long sp = (unsigned long)context->ra & ~63; - unsigned int *pc = (unsigned int *)sp; - unsigned long off; - _Unwind_Ptr new_cfa; - int i; - struct sigcontext *sc; - struct rt_sigframe { - struct siginfo info; - struct ucontext uc; - } *frame; - - /* rt_sigreturn trampoline: - 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) - 3414015a ldi __NR_rt_sigreturn, %r20 - e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 - 08000240 nop */ - - if (pc[0] == 0x34190000 || pc[0] == 0x34190002) - off = 4*4; - else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) - { - pc += 4; - off = 10 * 4; - } - else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) - { - pc += 5; - off = 10 * 4; - } - else - { - /* We may have to unwind through an alternate signal stack. - We assume that the alignment of the alternate signal stack - is BIGGEST_ALIGNMENT (i.e., that it has been allocated using - malloc). As a result, we can't distinguish trampolines - used prior to 2.6.5-rc2-pa4. However after 2.6.5-rc2-pa4, - the return address of a signal trampoline will be on an odd - word boundary and we can then determine the frame offset. */ - sp = (unsigned long)context->ra; - pc = (unsigned int *)sp; - if ((pc[0] == 0x34190000 || pc[0] == 0x34190002) && (sp & 4)) - off = 5 * 4; - else - return _URC_END_OF_STACK; - } - - if (pc[1] != 0x3414015a - || pc[2] != 0xe4008200 - || pc[3] != 0x08000240) - return _URC_END_OF_STACK; - - frame = (struct rt_sigframe *)(sp + off); - sc = &frame->uc.uc_mcontext; - - new_cfa = sc->sc_gr[30]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 30; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - for (i = 1; i <= 31; i++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa; - } - for (i = 4; i <= 31; i++) - { - /* FP regs have left and right halves */ - fs->regs.reg[2*i+24].how = REG_SAVED_OFFSET; - fs->regs.reg[2*i+24].loc.offset - = (long)&sc->sc_fr[i] - new_cfa; - fs->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET; - fs->regs.reg[2*i+24+1].loc.offset - = (long)&sc->sc_fr[i] + 4 - new_cfa; - } - fs->regs.reg[88].how = REG_SAVED_OFFSET; - fs->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa; - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; - fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset - = (long) &sc->sc_iaoq[0] - new_cfa; - fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; - fs->signal_frame = 1; - return _URC_NO_REASON; -} -#endif /* inhibit_libc */ diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h index f167e133eb5..4d91be86dfd 100644 --- a/gcc/config/pa/pa-hpux.h +++ b/gcc/config/pa/pa-hpux.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for HP-UX. - Copyright (C) 1991, 1995, 1996, 2002, 2003, 2004, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1991, 1995, 1996, 2002, 2003, 2004, 2007, 2008, 2009, + 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -115,5 +115,3 @@ along with GCC; see the file COPYING3. If not see compatibility with the HP-UX unwind library. */ #undef TARGET_HPUX_UNWIND_LIBRARY #define TARGET_HPUX_UNWIND_LIBRARY 1 - -#define MD_UNWIND_SUPPORT "config/pa/hpux-unwind.h" diff --git a/gcc/config/pa/pa32-linux.h b/gcc/config/pa/pa32-linux.h index 8d80a210003..01aa1c4b103 100644 --- a/gcc/config/pa/pa32-linux.h +++ b/gcc/config/pa/pa32-linux.h @@ -1,5 +1,5 @@ /* Definitions for PA_RISC with ELF-32 format - Copyright (C) 2000, 2002, 2004, 2006, 2007, 2010 + Copyright (C) 2000, 2002, 2004, 2006, 2007, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -63,5 +63,3 @@ call_ ## FUNC (void) \ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE BITS_PER_WORD - -#define MD_UNWIND_SUPPORT "config/pa/linux-unwind.h" diff --git a/gcc/config/rs6000/darwin-unwind.h b/gcc/config/rs6000/darwin-unwind.h deleted file mode 100644 index 9fdc115be5a..00000000000 --- a/gcc/config/rs6000/darwin-unwind.h +++ /dev/null @@ -1,30 +0,0 @@ -/* DWARF2 EH unwinding support for Darwin. - Copyright (C) 2004, 2009 Free Software Foundation, Inc. - - 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 - . */ - -extern bool _Unwind_fallback_frame_state_for - (struct _Unwind_Context *context, _Unwind_FrameState *fs); - -#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS) \ - (_Unwind_fallback_frame_state_for (CONTEXT, FS) \ - ? _URC_NO_REASON : _URC_END_OF_STACK) diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index b1fe2eb05b5..82971ae0e32 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -381,10 +381,6 @@ extern int darwin_emit_branch_islands; #include #endif -#if !defined(__LP64__) && !defined(DARWIN_LIBSYSTEM_HAS_UNWIND) -#define MD_UNWIND_SUPPORT "config/rs6000/darwin-unwind.h" -#endif - /* True, iff we're generating fast turn around debugging code. When true, we arrange for function prologues to start with 5 nops so that gdb may insert code to redirect them, and for data to be diff --git a/gcc/config/rs6000/linux-unwind.h b/gcc/config/rs6000/linux-unwind.h deleted file mode 100644 index a16df97e97e..00000000000 --- a/gcc/config/rs6000/linux-unwind.h +++ /dev/null @@ -1,355 +0,0 @@ -/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - 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 - . */ - -#define R_LR 65 -#define R_CR2 70 -#define R_VR0 77 -#define R_VRSAVE 109 -#define R_VSCR 110 - -struct gcc_vregs -{ - __attribute__ ((vector_size (16))) int vr[32]; -#ifdef __powerpc64__ - unsigned int pad1[3]; - unsigned int vscr; - unsigned int vsave; - unsigned int pad2[3]; -#else - unsigned int vsave; - unsigned int pad[2]; - unsigned int vscr; -#endif -}; - -struct gcc_regs -{ - unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long orig_gpr3; - unsigned long ctr; - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long softe; - unsigned long trap; - unsigned long dar; - unsigned long dsisr; - unsigned long result; - unsigned long pad1[4]; - double fpr[32]; - unsigned int pad2; - unsigned int fpscr; -#ifdef __powerpc64__ - struct gcc_vregs *vp; -#else - unsigned int pad3[2]; -#endif - struct gcc_vregs vregs; -}; - -struct gcc_ucontext -{ -#ifdef __powerpc64__ - unsigned long pad[28]; -#else - unsigned long pad[12]; -#endif - struct gcc_regs *regs; - struct gcc_regs rsave; -}; - -#ifdef __powerpc64__ - -enum { SIGNAL_FRAMESIZE = 128 }; - -/* If PC is at a sigreturn trampoline, return a pointer to the - regs. Otherwise return NULL. */ - -static struct gcc_regs * -get_regs (struct _Unwind_Context *context) -{ - const unsigned int *pc = context->ra; - - /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ - /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ - if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002) - return NULL; - if (pc[1] == 0x38000077) - { - struct sigframe { - char gap[SIGNAL_FRAMESIZE]; - unsigned long pad[7]; - struct gcc_regs *regs; - } *frame = (struct sigframe *) context->cfa; - return frame->regs; - } - else if (pc[1] == 0x380000AC) - { - /* This works for 2.4 kernels, but not for 2.6 kernels with vdso - because pc isn't pointing into the stack. Can be removed when - no one is running 2.4.19 or 2.4.20, the first two ppc64 - kernels released. */ - const struct rt_sigframe_24 { - int tramp[6]; - void *pinfo; - struct gcc_ucontext *puc; - } *frame24 = (const struct rt_sigframe_24 *) context->ra; - - /* Test for magic value in *puc of vdso. */ - if ((long) frame24->puc != -21 * 8) - return frame24->puc->regs; - else - { - /* This works for 2.4.21 and later kernels. */ - struct rt_sigframe { - char gap[SIGNAL_FRAMESIZE]; - struct gcc_ucontext uc; - unsigned long pad[2]; - int tramp[6]; - void *pinfo; - struct gcc_ucontext *puc; - } *frame = (struct rt_sigframe *) context->cfa; - return frame->uc.regs; - } - } - return NULL; -} - -#else /* !__powerpc64__ */ - -enum { SIGNAL_FRAMESIZE = 64 }; - -static struct gcc_regs * -get_regs (struct _Unwind_Context *context) -{ - const unsigned int *pc = context->ra; - - /* li r0, 0x7777; sc (sigreturn old) */ - /* li r0, 0x0077; sc (sigreturn new) */ - /* li r0, 0x6666; sc (rt_sigreturn old) */ - /* li r0, 0x00AC; sc (rt_sigreturn new) */ - if (pc[1] != 0x44000002) - return NULL; - if (pc[0] == 0x38007777 || pc[0] == 0x38000077) - { - struct sigframe { - char gap[SIGNAL_FRAMESIZE]; - unsigned long pad[7]; - struct gcc_regs *regs; - } *frame = (struct sigframe *) context->cfa; - return frame->regs; - } - else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC) - { - struct rt_sigframe { - char gap[SIGNAL_FRAMESIZE + 16]; - char siginfo[128]; - struct gcc_ucontext uc; - } *frame = (struct rt_sigframe *) context->cfa; - return frame->uc.regs; - } - return NULL; -} -#endif - -/* Find an entry in the process auxiliary vector. The canonical way to - test for VMX is to look at AT_HWCAP. */ - -static long -ppc_linux_aux_vector (long which) -{ - /* __libc_stack_end holds the original stack passed to a process. */ - extern long *__libc_stack_end; - long argc; - char **argv; - char **envp; - struct auxv - { - long a_type; - long a_val; - } *auxp; - - /* The Linux kernel puts argc first on the stack. */ - argc = __libc_stack_end[0]; - /* Followed by argv, NULL terminated. */ - argv = (char **) __libc_stack_end + 1; - /* Followed by environment string pointers, NULL terminated. */ - envp = argv + argc + 1; - while (*envp++) - continue; - /* Followed by the aux vector, zero terminated. */ - for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp) - if (auxp->a_type == which) - return auxp->a_val; - return 0; -} - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state - -static _Unwind_Reason_Code -ppc_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - static long hwcap = 0; - struct gcc_regs *regs = get_regs (context); - long new_cfa; - int i; - - if (regs == NULL) - return _URC_END_OF_STACK; - - new_cfa = regs->gpr[STACK_POINTER_REGNUM]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = STACK_POINTER_REGNUM; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - for (i = 0; i < 32; i++) - if (i != STACK_POINTER_REGNUM) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; - } - - fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET; - /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit - libgcc loc.offset needs to point to the low 32 bits of regs->ccr. */ - fs->regs.reg[R_CR2].loc.offset = (long) ®s->ccr - new_cfa - + sizeof (long) - 4; - - fs->regs.reg[R_LR].how = REG_SAVED_OFFSET; - fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa; - - fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; - fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; - fs->retaddr_column = ARG_POINTER_REGNUM; - fs->signal_frame = 1; - - if (hwcap == 0) - { - hwcap = ppc_linux_aux_vector (16); - /* These will already be set if we found AT_HWCAP. A nonzero - value stops us looking again if for some reason we couldn't - find AT_HWCAP. */ -#ifdef __powerpc64__ - hwcap |= 0xc0000000; -#else - hwcap |= 0x80000000; -#endif - } - - /* If we have a FPU... */ - if (hwcap & 0x08000000) - for (i = 0; i < 32; i++) - { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; - } - - /* If we have a VMX unit... */ - if (hwcap & 0x10000000) - { - struct gcc_vregs *vregs; -#ifdef __powerpc64__ - vregs = regs->vp; -#else - vregs = ®s->vregs; -#endif - if (regs->msr & (1 << 25)) - { - for (i = 0; i < 32; i++) - { - fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET; - fs->regs.reg[i + R_VR0].loc.offset - = (long) &vregs->vr[i] - new_cfa; - } - - fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET; - fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa; - } - - fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET; - fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa; - } - - /* If we have SPE register high-parts... we check at compile-time to - avoid expanding the code for all other PowerPC. */ -#ifdef __SPE__ - for (i = 0; i < 32; i++) - { - fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET; - fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset - = (long) ®s->vregs - new_cfa + 4 * i; - } -#endif - - return _URC_NO_REASON; -} - -#define MD_FROB_UPDATE_CONTEXT frob_update_context - -static void -frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED) -{ - const unsigned int *pc = (const unsigned int *) context->ra; - - /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't - have S flag in it. */ -#ifdef __powerpc64__ - /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ - /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ - if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE - && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) - && pc[2] == 0x44000002) - _Unwind_SetSignalFrame (context, 1); -#else - /* li r0, 0x7777; sc (sigreturn old) */ - /* li r0, 0x0077; sc (sigreturn new) */ - /* li r0, 0x6666; sc (rt_sigreturn old) */ - /* li r0, 0x00AC; sc (rt_sigreturn new) */ - if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 - || pc[0] == 0x38006666 || pc[0] == 0x380000AC) - && pc[1] == 0x44000002) - _Unwind_SetSignalFrame (context, 1); -#endif - -#ifdef __powerpc64__ - if (fs->regs.reg[2].how == REG_UNSAVED) - { - /* If the current unwind info (FS) does not contain explicit info - saving R2, then we have to do a minor amount of code reading to - figure out if it was saved. The big problem here is that the - code that does the save/restore is generated by the linker, so - we have no good way to determine at compile time what to do. */ - unsigned int *insn - = (unsigned int *) _Unwind_GetGR (context, R_LR); - if (insn && *insn == 0xE8410028) - _Unwind_SetGRPtr (context, 2, context->cfa + 40); - } -#endif -} diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index 305b621e7e2..336727428bc 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -113,8 +113,6 @@ #define TARGET_POSIX_IO -#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h" - #ifdef TARGET_LIBC_PROVIDES_SSP /* ppc32 glibc provides __stack_chk_guard in -0x7008(2). */ #define TARGET_THREAD_SSP_OFFSET -0x7008 diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 5a26d120a46..972f353061a 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -539,8 +539,6 @@ extern int dot_symbols; #define USE_LD_AS_NEEDED 1 #endif -#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h" - #ifdef TARGET_LIBC_PROVIDES_SSP /* ppc32 glibc provides __stack_chk_guard in -0x7008(2), ppc64 glibc provides it at -0x7010(13). */ diff --git a/gcc/config/s390/linux-unwind.h b/gcc/config/s390/linux-unwind.h deleted file mode 100644 index 558087fad94..00000000000 --- a/gcc/config/s390/linux-unwind.h +++ /dev/null @@ -1,130 +0,0 @@ -/* DWARF2 EH unwinding support for S/390 Linux. - Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#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 char *pc = context->ra; - long new_cfa; - int i; - - typedef struct - { - unsigned long psw_mask; - unsigned long psw_addr; - unsigned long gprs[16]; - unsigned int acrs[16]; - unsigned int fpc; - unsigned int __pad; - double fprs[16]; - } __attribute__ ((__aligned__ (8))) sigregs_; - - sigregs_ *regs; - int *signo; - - /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ - if (pc[0] != 0x0a || (pc[1] != 119 && pc[1] != 173)) - return _URC_END_OF_STACK; - - /* Legacy frames: - old signal mask (8 bytes) - pointer to sigregs (8 bytes) - points always to next location - sigregs - retcode - This frame layout was used on kernels < 2.6.9 for non-RT frames, - and on kernels < 2.4.13 for RT frames as well. Note that we need - to look at RA to detect this layout -- this means that if you use - sa_restorer to install a different signal restorer on a legacy - kernel, unwinding from signal frames will not work. */ - if (context->ra == context->cfa + 16 + sizeof (sigregs_)) - { - regs = (sigregs_ *)(context->cfa + 16); - signo = NULL; - } - - /* New-style RT frame: - retcode + alignment (8 bytes) - siginfo (128 bytes) - ucontext (contains sigregs) */ - else if (pc[1] == 173 /* __NR_rt_sigreturn */) - { - struct ucontext_ - { - unsigned long uc_flags; - struct ucontext_ *uc_link; - unsigned long uc_stack[3]; - sigregs_ uc_mcontext; - } *uc = context->cfa + 8 + 128; - - regs = &uc->uc_mcontext; - signo = context->cfa + sizeof(long); - } - - /* New-style non-RT frame: - old signal mask (8 bytes) - pointer to sigregs (followed by signal number) */ - else - { - regs = *(sigregs_ **)(context->cfa + 8); - signo = (int *)(regs + 1); - } - - new_cfa = regs->gprs[15] + 16*sizeof(long) + 32; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 15; - fs->regs.cfa_offset = - new_cfa - (long) context->cfa + 16*sizeof(long) + 32; - - for (i = 0; i < 16; i++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = - (long)®s->gprs[i] - new_cfa; - } - for (i = 0; i < 16; i++) - { - fs->regs.reg[16+i].how = REG_SAVED_OFFSET; - fs->regs.reg[16+i].loc.offset = - (long)®s->fprs[i] - new_cfa; - } - - /* Load return addr from PSW into dummy register 32. */ - - fs->regs.reg[32].how = REG_SAVED_OFFSET; - fs->regs.reg[32].loc.offset = (long)®s->psw_addr - new_cfa; - fs->retaddr_column = 32; - /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr - after the faulting instruction rather than before it. - Don't set FS->signal_frame in that case. */ - if (!signo || (*signo != 4 && *signo != 5 && *signo != 8)) - fs->signal_frame = 1; - - return _URC_NO_REASON; -} diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h index 7bd90d9d3ac..e5385eca313 100644 --- a/gcc/config/s390/linux.h +++ b/gcc/config/s390/linux.h @@ -79,8 +79,6 @@ along with GCC; see the file COPYING3. If not see #define TARGET_ASM_FILE_END file_end_indicate_exec_stack -#define MD_UNWIND_SUPPORT "config/s390/linux-unwind.h" - #ifdef TARGET_LIBC_PROVIDES_SSP /* s390 glibc provides __stack_chk_guard in 0x14(tp), s390x glibc provides it at 0x28(tp). */ diff --git a/gcc/config/s390/tpf-unwind.h b/gcc/config/s390/tpf-unwind.h deleted file mode 100644 index 33fd5f5c8c5..00000000000 --- a/gcc/config/s390/tpf-unwind.h +++ /dev/null @@ -1,252 +0,0 @@ -/* 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 -. */ - -#include - -/* 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; -} - diff --git a/gcc/config/s390/tpf.h b/gcc/config/s390/tpf.h index c5e86e4a17a..e4a1b50b6ec 100644 --- a/gcc/config/s390/tpf.h +++ b/gcc/config/s390/tpf.h @@ -118,8 +118,6 @@ along with GCC; see the file COPYING3. If not see %{!shared:-shared} \ %(entry_spec)" -#define MD_UNWIND_SUPPORT "config/s390/tpf-unwind.h" - /* IBM copies these libraries over with these names. */ #define MATH_LIBRARY "CLBM" #define LIBSTDCXX "CPP1" diff --git a/gcc/config/sh/linux-unwind.h b/gcc/config/sh/linux-unwind.h deleted file mode 100644 index 94ed95d55e1..00000000000 --- a/gcc/config/sh/linux-unwind.h +++ /dev/null @@ -1,255 +0,0 @@ -/* DWARF2 EH unwinding support for SH Linux. - Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. - -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 -. */ - - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. - Don't use this at all if inhibit_libc is used. */ - -#ifndef inhibit_libc - -#include -#include -#include "insn-constants.h" - -# if defined (__SH5__) -#define SH_DWARF_FRAME_GP0 0 -#define SH_DWARF_FRAME_FP0 77 -#define SH_DWARF_FRAME_BT0 68 -#define SH_DWARF_FRAME_PR_MEDIA 18 -#define SH_DWARF_FRAME_SR 65 -#define SH_DWARF_FRAME_FPSCR 76 -#else -#define SH_DWARF_FRAME_GP0 0 -#define SH_DWARF_FRAME_FP0 25 -#define SH_DWARF_FRAME_XD0 87 -#define SH_DWARF_FRAME_PR 17 -#define SH_DWARF_FRAME_GBR 18 -#define SH_DWARF_FRAME_MACH 20 -#define SH_DWARF_FRAME_MACL 21 -#define SH_DWARF_FRAME_PC 16 -#define SH_DWARF_FRAME_SR 22 -#define SH_DWARF_FRAME_FPUL 23 -#define SH_DWARF_FRAME_FPSCR 24 -#endif /* defined (__SH5__) */ - -#if defined (__SH5__) - -#define MD_FALLBACK_FRAME_STATE_FOR shmedia_fallback_frame_state - -static _Unwind_Reason_Code -shmedia_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - long new_cfa; - int i, r; - - /* movi 0x10,r9; shori 0x77,r9; trapa r9; nop (sigreturn) */ - /* movi 0x10,r9; shori 0xad,r9; trapa r9; nop (rt_sigreturn) */ - if ((*(unsigned long *) (pc-1) == 0xcc004090) - && (*(unsigned long *) (pc+3) == 0xc801dc90) - && (*(unsigned long *) (pc+7) == 0x6c91fff0) - && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) - sc = context->cfa; - else if ((*(unsigned long *) (pc-1) == 0xcc004090) - && (*(unsigned long *) (pc+3) == 0xc802b490) - && (*(unsigned long *) (pc+7) == 0x6c91fff0) - && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) - { - struct rt_sigframe { - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - } *rt_ = context->cfa; - /* The void * cast is necessary to avoid an aliasing warning. - The aliasing warning is correct, but should not be a problem - because it does not alias anything. */ - sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = sc->sc_regs[15]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 15; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - for (i = 0; i < 63; i++) - { - if (i == 15) - continue; - - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = (long)&(sc->sc_regs[i]) - new_cfa; - } - - fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset - = (long)&(sc->sc_sr) - new_cfa; - - r = SH_DWARF_FRAME_BT0; - for (i = 0; i < 8; i++) - { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; - fs->regs.reg[r+i].loc.offset - = (long)&(sc->sc_tregs[i]) - new_cfa; - } - - r = SH_DWARF_FRAME_FP0; - for (i = 0; i < 32; i++) - { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; - fs->regs.reg[r+i].loc.offset - = (long)&(sc->sc_fpregs[i]) - new_cfa; - } - - fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset - = (long)&(sc->sc_fpscr) - new_cfa; - - /* We use the slot for the zero register to save return address. */ - fs->regs.reg[63].how = REG_SAVED_OFFSET; - fs->regs.reg[63].loc.offset - = (long)&(sc->sc_pc) - new_cfa; - fs->retaddr_column = 63; - fs->signal_frame = 1; - return _URC_NO_REASON; -} - -#else /* defined (__SH5__) */ - -#define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state - -static _Unwind_Reason_Code -sh_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - long new_cfa; - int i; -#if defined (__SH3E__) || defined (__SH4__) - int r; -#endif - - /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77 (sigreturn) */ - /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad (rt_sigreturn) */ - /* Newer kernel uses pad instructions to avoid an SH-4 core bug. */ - /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; - or r0,r0; 1: .short 0x77 (sigreturn) */ - /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; - or r0,r0; 1: .short 0xad (rt_sigreturn) */ - if (((*(unsigned short *) (pc+0) == 0x9300) - && (*(unsigned short *) (pc+2) == 0xc310) - && (*(unsigned short *) (pc+4) == 0x0077)) - || (((*(unsigned short *) (pc+0) == 0x9305) - && (*(unsigned short *) (pc+2) == 0xc310) - && (*(unsigned short *) (pc+14) == 0x0077)))) - sc = context->cfa; - else if (((*(unsigned short *) (pc+0) == 0x9300) - && (*(unsigned short *) (pc+2) == 0xc310) - && (*(unsigned short *) (pc+4) == 0x00ad)) - || (((*(unsigned short *) (pc+0) == 0x9305) - && (*(unsigned short *) (pc+2) == 0xc310) - && (*(unsigned short *) (pc+14) == 0x00ad)))) - { - struct rt_sigframe { - struct siginfo info; - struct ucontext uc; - } *rt_ = context->cfa; - /* The void * cast is necessary to avoid an aliasing warning. - The aliasing warning is correct, but should not be a problem - because it does not alias anything. */ - sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; - } - else - return _URC_END_OF_STACK; - - new_cfa = sc->sc_regs[15]; - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = 15; - fs->regs.cfa_offset = new_cfa - (long) context->cfa; - - for (i = 0; i < 15; i++) - { - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = (long)&(sc->sc_regs[i]) - new_cfa; - } - - fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset - = (long)&(sc->sc_pr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset - = (long)&(sc->sc_sr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset - = (long)&(sc->sc_gbr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset - = (long)&(sc->sc_mach) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset - = (long)&(sc->sc_macl) - new_cfa; - -#if defined (__SH3E__) || defined (__SH4__) - r = SH_DWARF_FRAME_FP0; - for (i = 0; i < 16; i++) - { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; - fs->regs.reg[r+i].loc.offset - = (long)&(sc->sc_fpregs[i]) - new_cfa; - } - - r = SH_DWARF_FRAME_XD0; - for (i = 0; i < 8; i++) - { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; - fs->regs.reg[r+i].loc.offset - = (long)&(sc->sc_xfpregs[2*i]) - new_cfa; - } - - fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset - = (long)&(sc->sc_fpul) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset - = (long)&(sc->sc_fpscr) - new_cfa; -#endif - - fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET; - fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset - = (long)&(sc->sc_pc) - new_cfa; - fs->retaddr_column = SH_DWARF_FRAME_PC; - fs->signal_frame = 1; - return _URC_NO_REASON; -} -#endif /* defined (__SH5__) */ - -#endif /* inhibit_libc */ diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h index fc954fe9863..edfd99be652 100644 --- a/gcc/config/sh/linux.h +++ b/gcc/config/sh/linux.h @@ -114,8 +114,6 @@ along with GCC; see the file COPYING3. If not see } \ } while (0) -#define MD_UNWIND_SUPPORT "config/sh/linux-unwind.h" - /* For SH3 and SH4, we use a slot of the unwind frame which correspond to a fake register number 16 as a placeholder for the return address in MD_FALLBACK_FRAME_STATE_FOR and its content will be read with diff --git a/gcc/config/sparc/linux-unwind.h b/gcc/config/sparc/linux-unwind.h deleted file mode 100644 index adfef6ec29d..00000000000 --- a/gcc/config/sparc/linux-unwind.h +++ /dev/null @@ -1,202 +0,0 @@ -/* DWARF2 EH unwinding support for SPARC Linux. - Copyright 2004, 2005, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#if defined(__arch64__) - -/* 64-bit SPARC version */ -#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state - -static _Unwind_Reason_Code -sparc64_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned int *pc = context->ra; - long this_cfa = (long) context->cfa; - long new_cfa, ra_location, shifted_ra_location; - long regs_off, fpu_save_off; - long fpu_save; - int i; - - if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ - || pc[1] != 0x91d0206d) /* ta 0x6d */ - return _URC_END_OF_STACK; - - regs_off = 192 + 128; - fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4); - - new_cfa = *(long *)(this_cfa + regs_off + (14 * 8)); - new_cfa += 2047; /* Stack bias */ - fpu_save = *(long *)(this_cfa + fpu_save_off); - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = new_cfa - this_cfa; - - for (i = 1; i < 16; i++) - { - /* We never restore %sp as everything is purely CFA-based. */ - if ((unsigned int) i == __builtin_dwarf_sp_column ()) - continue; - - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = this_cfa + regs_off + (i * 8) - new_cfa; - } - for (i = 0; i < 16; i++) - { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 16].loc.offset - = this_cfa + (i * 8) - new_cfa; - } - if (fpu_save) - { - for (i = 0; i < 64; i++) - { - if (i > 32 && (i & 0x1)) - continue; - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 32].loc.offset - = fpu_save + (i * 4) - new_cfa; - } - } - - /* State the rules to find the kernel's code "return address", which is - the address of the active instruction when the signal was caught. - On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we - need to preventively subtract it from the purported return address. */ - ra_location = this_cfa + regs_off + 17 * 8; - shifted_ra_location = this_cfa + regs_off + 19 * 8; /* Y register */ - *(long *)shifted_ra_location = *(long *)ra_location - 8; - fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} - -#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context - -static void -sparc64_frob_update_context (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - /* The column of %sp contains the old CFA, not the old value of %sp. - The CFA offset already comprises the stack bias so, when %sp is the - CFA register, we must avoid counting the stack bias twice. Do not - do that for signal frames as the offset is artificial for them. */ - if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () - && fs->regs.cfa_how == CFA_REG_OFFSET - && fs->regs.cfa_offset != 0 - && !fs->signal_frame) - context->cfa -= 2047; -} - -#else - -/* 32-bit SPARC version */ -#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state - -static _Unwind_Reason_Code -sparc_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned int *pc = context->ra; - int this_cfa = (int) context->cfa; - int new_cfa, ra_location, shifted_ra_location; - int regs_off, fpu_save_off; - int fpu_save; - int old_style, i; - - if (pc[1] != 0x91d02010) /* ta 0x10 */ - return _URC_END_OF_STACK; - - if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ - old_style = 1; - else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ - old_style = 0; - else - return _URC_END_OF_STACK; - - if (old_style) - { - regs_off = 96; - fpu_save_off = regs_off + (4 * 4) + (16 * 4); - } - else - { - regs_off = 96 + 128; - fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4); - } - - new_cfa = *(int *)(this_cfa + regs_off + (4 * 4) + (14 * 4)); - fpu_save = *(int *)(this_cfa + fpu_save_off); - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = new_cfa - this_cfa; - - for (i = 1; i < 16; i++) - { - /* We never restore %sp as everything is purely CFA-based. */ - if ((unsigned int) i == __builtin_dwarf_sp_column ()) - continue; - - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset - = this_cfa + regs_off + (4 * 4) + (i * 4) - new_cfa; - } - for (i = 0; i < 16; i++) - { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 16].loc.offset - = this_cfa + (i * 4) - new_cfa; - } - if (fpu_save) - { - for (i = 0; i < 32; i++) - { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 32].loc.offset - = fpu_save + (i * 4) - new_cfa; - } - } - - /* State the rules to find the kernel's code "return address", which is - the address of the active instruction when the signal was caught. - On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we - need to preventively subtract it from the purported return address. */ - ra_location = this_cfa + regs_off + 4; - shifted_ra_location = this_cfa + regs_off + 3 * 4; /* Y register */ - *(int *)shifted_ra_location = *(int *)ra_location - 8; - fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} - -#endif diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index f8e16dd6926..a9b630e6184 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -141,8 +141,6 @@ do { \ /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 -#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h" - /* Linux currently uses RMO in uniprocessor mode, which is equivalent to TMO, and TMO in multiprocessor mode. But they reserve the right to change their minds. */ diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index 27ff696f0f2..7f8b37891cf 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -261,8 +261,6 @@ do { \ /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 -#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h" - /* Linux currently uses RMO in uniprocessor mode, which is equivalent to TMO, and TMO in multiprocessor mode. But they reserve the right to change their minds. */ diff --git a/gcc/config/sparc/sol2-unwind.h b/gcc/config/sparc/sol2-unwind.h deleted file mode 100644 index f8b99027247..00000000000 --- a/gcc/config/sparc/sol2-unwind.h +++ /dev/null @@ -1,419 +0,0 @@ -/* DWARF2 EH unwinding support for SPARC Solaris. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#include -#include -#include - -#if defined(__arch64__) - -#define IS_SIGHANDLER sparc64_is_sighandler - -static int -sparc64_is_sighandler (unsigned int *pc, unsigned int *savpc, int *nframes) -{ - if (/* Solaris 8 - single-threaded - ---------------------------- - : add %g5, %o7, %o2 - : ldx [ %o2 + 0xfa0 ], %g5 - : sra %i0, 0, %o0 - : sllx %o0, 3, %g4 - : ldx [ %g4 + %g5 ], %l0 - : call %l0 - : mov %i2, %o2 - : cmp %i3, 8 <--- PC */ - ( pc[-7] == 0x9401400f - && pc[-6] == 0xca5aafa0 - && pc[-5] == 0x913e2000 - && pc[-4] == 0x892a3003 - && pc[-3] == 0xe0590005 - && pc[-2] == 0x9fc40000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x80a6e008) - - || /* Solaris 9 - single-threaded - ---------------------------- - The pattern changes slightly in different versions of the - operating system, so we skip the comparison against pc[-6] for - Solaris 9. - - : sra %i0, 0, %l1 - - Solaris 9 5/02: - : ldx [ %o2 + 0xf68 ], %g5 - Solaris 9 9/05: - : ldx [ %o2 + 0xe50 ], %g5 - - : sllx %l1, 3, %g4 - : mov %l1, %o0 - : ldx [ %g4 + %g5 ], %l0 - : call %l0 - : mov %i2, %o2 - : cmp %l1, 8 <--- PC */ - ( pc[-7] == 0xa33e2000 - /* skip pc[-6] */ - && pc[-5] == 0x892c7003 - && pc[-4] == 0x90100011 - && pc[-3] == 0xe0590005 - && pc[-2] == 0x9fc40000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x80a46008)) - { - /* We need to move up one frame: - - <-- context->cfa - sigacthandler - - */ - *nframes = 1; - return 1; - } - - if (/* Solaris 8+ - multi-threaded - ---------------------------- - <__sighndlr>: save %sp, -176, %sp - <__sighndlr+4>: mov %i0, %o0 - <__sighndlr+8>: mov %i1, %o1 - <__sighndlr+12>: call %i3 - <__sighndlr+16>: mov %i2, %o2 - <__sighndlr+20>: ret <--- PC - <__sighndlr+24>: restore */ - pc[-5] == 0x9de3bf50 - && pc[-4] == 0x90100018 - && pc[-3] == 0x92100019 - && pc[-2] == 0x9fc6c000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x81c7e008 - && pc[ 1] == 0x81e80000) - { - if (/* Solaris 8 /usr/lib/sparcv9/libthread.so.1 - ------------------------------------------ - Before patch 108827-08: - : st %g4, [ %i1 + 0x1c ] - - Since patch 108827-08: - : st %l0, [ %i4 + 0x10 ] */ - savpc[-1] == 0xc826601c - || savpc[-1] == 0xe0272010) - { - /* We need to move up three frames: - - <-- context->cfa - __sighndlr - sigacthandler - - */ - *nframes = 2; - } - else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+ - ---------------------------------------------------------- */ - { - /* We need to move up three frames: - - <-- context->cfa - __sighndlr - call_user_handler - sigacthandler - - */ - *nframes = 3; - } - return 1; - } - - return 0; -} - -#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state - -#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context - -static void -sparc64_frob_update_context (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - /* The column of %sp contains the old CFA, not the old value of %sp. - The CFA offset already comprises the stack bias so, when %sp is the - CFA register, we must avoid counting the stack bias twice. Do not - do that for signal frames as the offset is artificial for them. */ - if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () - && fs->regs.cfa_how == CFA_REG_OFFSET - && fs->regs.cfa_offset != 0 - && !fs->signal_frame) - context->cfa -= STACK_BIAS; -} - -#else - -#define IS_SIGHANDLER sparc_is_sighandler - -static int -sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) -{ - if (/* Solaris 8, 9 - single-threaded - ------------------------------- - The pattern changes slightly in different versions of the operating - system, so we skip the comparison against pc[-6]. - - : add %o1, %o7, %o3 - : mov %i1, %o1 - - : ld [ %o3 + ], %o2 - - : sll %i0, 2, %o0 - : ld [ %o0 + %o2 ], %l0 - : mov %i0, %o0 - : call %l0 - : mov %i2, %o2 - : cmp %i0, 8 <--- PC */ - pc[-8] == 0x9602400f - && pc[-7] == 0x92100019 - /* skip pc[-6] */ - && pc[-5] == 0x912e2002 - && pc[-4] == 0xe002000a - && pc[-3] == 0x90100018 - && pc[-2] == 0x9fc40000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x80a62008) - { - /* Need to move up one frame: - - <-- context->cfa - sigacthandler - - */ - *nframes = 1; - return 1; - } - - if (/* Solaris 8 - multi-threaded - --------------------------- - <__libthread_segvhdlr+212>: clr %o2 - <__libthread_segvhdlr+216>: ld [ %fp + -28 ], %l0 - <__libthread_segvhdlr+220>: mov %i4, %o0 - <__libthread_segvhdlr+224>: mov %i1, %o1 - <__libthread_segvhdlr+228>: call %l0 - <__libthread_segvhdlr+232>: mov %i2, %o2 - <__libthread_segvhdlr+236>: ret <--- PC - <__libthread_segvhdlr+240>: restore - <__libthread_segvhdlr+244>: cmp %o1, 0 */ - pc[-6] == 0x94102000 - && pc[-5] == 0xe007bfe4 - && pc[-4] == 0x9010001c - && pc[-3] == 0x92100019 - && pc[-2] == 0x9fc40000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x81c7e008 - && pc[ 1] == 0x81e80000 - && pc[ 2] == 0x80a26000) - { - /* Need to move up one frame: - - <-- context->cfa - __libthread_segvhdlr - - */ - *nframes = 1; - return 1; - } - - if(/* Solaris 8+ - multi-threaded - ---------------------------- - <__sighndlr>: save %sp, -96, %sp - <__sighndlr+4>: mov %i0, %o0 - <__sighndlr+8>: mov %i1, %o1 - <__sighndlr+12>: call %i3 - <__sighndlr+16>: mov %i2, %o2 - <__sighndlr+20>: ret <--- PC - <__sighndlr+24>: restore */ - pc[-5] == 0x9de3bfa0 - && pc[-4] == 0x90100018 - && pc[-3] == 0x92100019 - && pc[-2] == 0x9fc6c000 - && pc[-1] == 0x9410001a - && pc[ 0] == 0x81c7e008 - && pc[ 1] == 0x81e80000) - { - if (/* Solaris 8 /usr/lib/libthread.so.1 - ---------------------------------- - : mov %i0, %o0 */ - savpc[-1] == 0x90100018) - { - /* We need to move up two frames: - - <-- context->cfa - __sighndlr - sigacthandler - - */ - *nframes = 2; - } - else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+ - -------------------------------------------------- */ - { - /* We need to move up three frames: - - <-- context->cfa - __sighndlr - call_user_handler - sigacthandler - - */ - *nframes = 3; - } - return 1; - } - - return 0; -} - -#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state - -#endif - -static _Unwind_Reason_Code -MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - void *pc = context->ra; - struct frame *fp = (struct frame *) context->cfa; - int nframes; - void *this_cfa = context->cfa; - long new_cfa; - void *ra_location, *shifted_ra_location; - mcontext_t *mctx; - int i; - - /* Deal with frame-less function from which a signal was raised. */ - if (_Unwind_IsSignalFrame (context)) - { - /* The CFA is by definition unmodified in this case. */ - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = 0; - - /* This is the canonical RA column. */ - fs->retaddr_column = 15; - - return _URC_NO_REASON; - } - - if (IS_SIGHANDLER (pc, (unsigned int *)fp->fr_savpc, &nframes)) - { - struct handler_args { - struct frame frwin; - ucontext_t ucontext; - } *handler_args; - ucontext_t *ucp; - - /* context->cfa points into the frame after the saved frame pointer and - saved pc (struct frame). - - The ucontext_t structure is in the kernel frame after a struct - frame. Since the frame sizes vary even within OS releases, we - need to walk the stack to get there. */ - - for (i = 0; i < nframes; i++) - fp = (struct frame *) ((char *)fp->fr_savfp + STACK_BIAS); - - handler_args = (struct handler_args *) fp; - ucp = &handler_args->ucontext; - mctx = &ucp->uc_mcontext; - } - - /* Exit if the pattern at the return address does not match the - previous three patterns. */ - else - return _URC_END_OF_STACK; - - new_cfa = mctx->gregs[REG_SP]; - /* The frame address is %sp + STACK_BIAS in 64-bit mode. */ - new_cfa += STACK_BIAS; - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = __builtin_dwarf_sp_column (); - fs->regs.cfa_offset = new_cfa - (long) this_cfa; - - /* Restore global and out registers (in this order) from the - ucontext_t structure, uc_mcontext.gregs field. */ - for (i = 1; i < 16; i++) - { - /* We never restore %sp as everything is purely CFA-based. */ - if ((unsigned int) i == __builtin_dwarf_sp_column ()) - continue; - - /* First the global registers and then the out registers. */ - fs->regs.reg[i].how = REG_SAVED_OFFSET; - fs->regs.reg[i].loc.offset = (long)&mctx->gregs[REG_Y + i] - new_cfa; - } - - /* Just above the stack pointer there are 16 extended words in which - the register window (in and local registers) was saved. */ - for (i = 0; i < 16; i++) - { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 16].loc.offset = i*sizeof(long); - } - - /* Check whether we need to restore FPU registers. */ - if (mctx->fpregs.fpu_qcnt) - { - for (i = 0; i < 32; i++) - { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 32].loc.offset - = (long)&mctx->fpregs.fpu_fr.fpu_regs[i] - new_cfa; - } - -#ifdef __arch64__ - /* For 64-bit, fpu_fr.fpu_dregs contains 32 instead of 16 doubles. */ - for (i = 32; i < 64; i++) - { - if (i > 32 && (i & 1)) - continue; - - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; - fs->regs.reg[i + 32].loc.offset - = (long)&mctx->fpregs.fpu_fr.fpu_dregs[i/2] - new_cfa; - } -#endif - } - - /* State the rules to find the kernel's code "return address", which is - the address of the active instruction when the signal was caught. - On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we - need to preventively subtract it from the purported return address. */ - ra_location = &mctx->gregs[REG_PC]; - shifted_ra_location = &mctx->gregs[REG_Y]; - *(void **)shifted_ra_location = *(void **)ra_location - 8; - fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[0].loc.offset = (long)shifted_ra_location - new_cfa; - fs->signal_frame = 1; - - return _URC_NO_REASON; -} diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index ddc7c4db68a..c99b02f8fe3 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -196,5 +196,3 @@ along with GCC; see the file COPYING3. If not see /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 - -#define MD_UNWIND_SUPPORT "config/sparc/sol2-unwind.h" diff --git a/gcc/config/xtensa/linux-unwind.h b/gcc/config/xtensa/linux-unwind.h deleted file mode 100644 index 32e93497287..00000000000 --- a/gcc/config/xtensa/linux-unwind.h +++ /dev/null @@ -1,97 +0,0 @@ -/* DWARF2 EH unwinding support for Xtensa. - Copyright (C) 2008, 2009 Free Software Foundation, Inc. - -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 -. */ - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2-xtensa.c for the structs. - Don't use this at all if inhibit_libc is used. */ - -#ifndef inhibit_libc - -#include -#include - -/* Encoded bytes for Xtensa instructions: - movi a2, __NR_rt_sigreturn - syscall - entry (first byte only) - Some of the bytes are endian-dependent. */ - -#define MOVI_BYTE0 0x22 -#define MOVI_BYTE2 225 /* __NR_rt_sigreturn */ -#define SYSC_BYTE0 0 -#define SYSC_BYTE2 0 - -#ifdef __XTENSA_EB__ -#define MOVI_BYTE1 0x0a -#define SYSC_BYTE1 0x05 -#define ENTRY_BYTE 0x6c -#else -#define MOVI_BYTE1 0xa0 -#define SYSC_BYTE1 0x50 -#define ENTRY_BYTE 0x36 -#endif - -#define MD_FALLBACK_FRAME_STATE_FOR xtensa_fallback_frame_state - -static _Unwind_Reason_Code -xtensa_fallback_frame_state (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - unsigned char *pc = context->ra; - struct sigcontext *sc; - - struct rt_sigframe { - struct siginfo info; - struct ucontext uc; - } *rt_; - - /* movi a2, __NR_rt_sigreturn; syscall */ - if (pc[0] != MOVI_BYTE0 - || pc[1] != MOVI_BYTE1 - || pc[2] != MOVI_BYTE2 - || pc[3] != SYSC_BYTE0 - || pc[4] != SYSC_BYTE1 - || pc[5] != SYSC_BYTE2) - return _URC_END_OF_STACK; - - rt_ = context->sp; - sc = &rt_->uc.uc_mcontext; - fs->signal_regs = (_Unwind_Word *) sc->sc_a; - - /* If the signal arrived just before an ENTRY instruction, find the return - address and pretend the signal arrived before executing the CALL. */ - if (*(unsigned char *) sc->sc_pc == ENTRY_BYTE) - { - unsigned callinc = (sc->sc_ps >> 16) & 3; - fs->signal_ra = ((sc->sc_a[callinc << 2] & XTENSA_RA_FIELD_MASK) - | context->ra_high_bits) - 3; - } - else - fs->signal_ra = sc->sc_pc; - - fs->signal_frame = 1; - return _URC_NO_REASON; -} - -#endif /* ifdef inhibit_libc */ diff --git a/gcc/config/xtensa/linux.h b/gcc/config/xtensa/linux.h index d058d16015d..f5caeb7a603 100644 --- a/gcc/config/xtensa/linux.h +++ b/gcc/config/xtensa/linux.h @@ -64,5 +64,3 @@ along with GCC; see the file COPYING3. If not see #undef DBX_REGISTER_NUMBER -#define MD_UNWIND_SUPPORT "config/xtensa/linux-unwind.h" - diff --git a/gcc/config/xtensa/unwind-dw2-xtensa.c b/gcc/config/xtensa/unwind-dw2-xtensa.c index 9544f65ab78..54daf7637ce 100644 --- a/gcc/config/xtensa/unwind-dw2-xtensa.c +++ b/gcc/config/xtensa/unwind-dw2-xtensa.c @@ -1,6 +1,6 @@ /* DWARF2 exception handling and frame unwinding for Xtensa. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009 + 2007, 2008, 2009, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -208,9 +208,7 @@ _Unwind_GetTextRelBase (struct _Unwind_Context *context) return (_Unwind_Ptr) context->bases.tbase; } -#ifdef MD_UNWIND_SUPPORT -#include MD_UNWIND_SUPPORT -#endif +#include "md-unwind-support.h" /* Extract any interesting information from the CIE for the translation unit F belongs to. Return a pointer to the byte after the augmentation, diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b28a27ed6c9..e248b817695 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001, -@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -3373,11 +3373,6 @@ of bytes that the format occupies, @var{addr} is the @code{SYMBOL_REF} to be emitted. @end defmac -@defmac MD_UNWIND_SUPPORT -A string specifying a file to be #include'd in unwind-dw2.c. The file -so included typically defines @code{MD_FALLBACK_FRAME_STATE_FOR}. -@end defmac - @defmac MD_FALLBACK_FRAME_STATE_FOR (@var{context}, @var{fs}) This macro allows the target to add CPU and operating system specific code to the call-frame unwinder for use when there is no unwind data diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 2b8511d2dec..528ac136616 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -1,5 +1,5 @@ @c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001, -@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -3361,11 +3361,6 @@ of bytes that the format occupies, @var{addr} is the @code{SYMBOL_REF} to be emitted. @end defmac -@defmac MD_UNWIND_SUPPORT -A string specifying a file to be #include'd in unwind-dw2.c. The file -so included typically defines @code{MD_FALLBACK_FRAME_STATE_FOR}. -@end defmac - @defmac MD_FALLBACK_FRAME_STATE_FOR (@var{context}, @var{fs}) This macro allows the target to add CPU and operating system specific code to the call-frame unwinder for use when there is no unwind data diff --git a/gcc/system.h b/gcc/system.h index e39a6f928e9..d08166135fa 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -763,7 +763,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; /* Target macros only used for code built for the target, that have moved to libgcc-tm.h or have never been present elsewhere. */ - #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX + #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX \ + MD_UNWIND_SUPPORT /* Other obsolete target macros, or macros that used to be in target headers and were not used, and may be obsolete or may never have diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 25990b4e73b..19da29982b6 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -333,9 +333,7 @@ _Unwind_GetTextRelBase (struct _Unwind_Context *context) } #endif -#ifdef MD_UNWIND_SUPPORT -#include MD_UNWIND_SUPPORT -#endif +#include "md-unwind-support.h" /* Extract any interesting information from the CIE for the translation unit F belongs to. Return a pointer to the byte after the augmentation, diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 4141890af33..5a4fec5139d 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,48 @@ +2011-06-03 Rainer Orth + + * config/alpha/linux-unwind.h: Move from ../gcc/config/alpha. + * config/alpha/osf5-unwind.h: Move from ../gcc/config/alpha. + * config/alpha/vms-unwind.h: Move from ../gcc/config/alpha. + * config/bfin/linux-unwind.h: Move from ../gcc/config/bfin. + * config/i386/linux-unwind.h: Move from ../gcc/config/i386. + * config/i386/sol2-unwind.h: Move from ../gcc/config/i386. + * config/i386/w32-unwind.h: Move from ../gcc/config/i386. + Wrap in !__MINGW64__. + * config/ia64/linux-unwind.h: Move from ../gcc/config/ia64. + * config/ia64/vms-unwind.h: Move from ../gcc/config/ia64. + * config/m68k/linux-unwind.h: Move from ../gcc/config/m68k. + * config/mips/linux-unwind.h: Move from ../gcc/config/mips. + * config/pa/hpux-unwind.h: Move from ../gcc/config/pa. + * config/pa/linux-unwind.h: Move from ../gcc/config/pa. + * config/rs6000/darwin-unwind.h: Move from ../gcc/config/rs6000. + Wrap in !__LP64__. + * config/rs6000/linux-unwind.h: Move from ../gcc/config/rs6000. + * config/s390/linux-unwind.h: Move from ../gcc/config/s390. + * config/s390/tpf-unwind.h: Move from ../gcc/config/s390. + * config/sh/linux-unwind.h: Move from ../gcc/config/sh. + * config/sparc/linux-unwind.h: Move from ../gcc/config/sparc. + * config/sparc/sol2-unwind.h: Move from ../gcc/config/sparc. + * config/xtensa/linux-unwind.h: Move from ../gcc/config/xtensa. + * config/no-unwind.h: New file. + * config.host (md_unwind_header): Document. + Define. + (alpha*-*-linux*, alpha*-dec-osf5.1*, alpha64-dec-*vms*, + alpha*-dec-*vms*, bfin*-uclinux*, bfin*-linux-uclibc*, + hppa*-*-linux*, hppa[12]*-*-hpux10*, hppa*64*-*-hpux11*, + hppa[12]*-*-hpux11*): Set md_unwind_header. + (i[34567]86-*-linux*): Handle i[34567]86-*-kopensolaris*-gnu. + Set md_unwind_header. + (x86_64-*-linux*, i[34567]86-*-solaris2*): Set md_unwind_header. + (i[34567]86-*-cygwin*): Split from i[34567]86-*-mingw*. + (i[34567]86-*-mingw*, ia64*-*-linux*, ia64-hp-*vms*, + m68k-*-uclinux*, m68k-*-linux*, mips64*-*-linux*, mips*-*-linux*, + powerpc-*-darwin*, powerpc-*-linux*, s390-*-linux*, + s390x-*-linux*, s390x-ibm-tpf*, sh*-*-linux*, sparc-*-linux*, + sparc*-*-solaris2*, sparc64-*-linux*, xtensa*-*-linux*): Set + md_unwind_header. + * configure.ac: Link md-unwind-support.h to $md_unwind_header. + * configure: Regenerate. + 2011-06-03 Rainer Orth * config.host (mips-sgi-irix[56]*): Restrict to mips-sgi-irix6.5*. diff --git a/libgcc/config.host b/libgcc/config.host index fa16613835a..c44ddd7b09a 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -50,6 +50,8 @@ # If either is set, EXTRA_PARTS and # EXTRA_MULTILIB_PARTS inherited from the GCC # subdirectory will be ignored. +# md_unwind_header The name of a header file defining +# MD_FALLBACK_FRAME_STATE_FOR. # tmake_file A list of machine-description-specific # makefile-fragments, if different from # "$cpu_type/t-$cpu_type". @@ -57,6 +59,7 @@ asm_hidden_op=.hidden extra_parts= tmake_file= +md_unwind_header=no-unwind.h # Set default cpu_type so it can be updated in each machine entry. cpu_type=`echo ${host} | sed 's/-.*$//'` @@ -210,6 +213,7 @@ case ${host} in alpha*-*-linux*) tmake_file="${tmake_file} alpha/t-crtfm" extra_parts="$extra_parts crtfastmath.o" + md_unwind_header=alpha/linux-unwind.h ;; alpha*-*-freebsd*) ;; @@ -225,12 +229,15 @@ alpha*-dec-osf5.1*) ;; esac extra_parts="${extra_parts} qrnnd.o crtfastmath.o gthr-posix.o" + md_unwind_header=alpha/osf5-unwind.h ;; alpha64-dec-*vms*) tmake_file="vms/t-vms vms/t-vms64 alpha/t-vms" + md_unwind_header=alpha/vms-unwind.h ;; alpha*-dec-*vms*) tmake_file="vms/t-vms alpha/t-vms" + md_unwind_header=alpha/vms-unwind.h ;; arm-wrs-vxworks) ;; @@ -261,11 +268,13 @@ avr-*-*) bfin*-elf*) ;; bfin*-uclinux*) + md_unwind_header=bfin/linux-unwind.h ;; bfin*-linux-uclibc*) # No need to build crtbeginT.o on uClibc systems. Should probably # be moved to the OS specific section above. extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + md_unwind_header=bfin/linux-unwind.h ;; bfin*-*) ;; @@ -289,12 +298,16 @@ h8300-*-elf*) hppa*64*-*-linux*) ;; hppa*-*-linux*) + md_unwind_header=pa/pa32-linux.h ;; hppa[12]*-*-hpux10*) + md_unwind_header=pa/hpux-unwind.h ;; hppa*64*-*-hpux11*) + md_unwind_header=pa/hpux-unwind.h ;; hppa[12]*-*-hpux11*) + md_unwind_header=pa/hpux-unwind.h ;; i[34567]86-*-darwin*) ;; @@ -319,13 +332,15 @@ i[34567]86-*-openbsd2.*|i[34567]86-*openbsd3.[0123]) ;; i[34567]86-*-openbsd*) ;; -i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i[34567]86-*-gnu*) +i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu) extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o" tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm" + md_unwind_header=i386/linux-unwind.h ;; x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu) extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o" tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm" + md_unwind_header=i386/linux-unwind.h ;; i[34567]86-pc-msdosdjgpp*) ;; @@ -347,13 +362,19 @@ i[34567]86-*-rtems*) i[34567]86-*-solaris2*) tmake_file="$tmake_file i386/t-crtfm" extra_parts="$extra_parts crtfastmath.o" + md_unwind_header=i386/sol2-unwind.h ;; i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae) ;; -i[34567]86-*-cygwin* | i[34567]86-*-mingw*) +i[34567]86-*-cygwin*) extra_parts="crtbegin.o crtend.o crtfastmath.o" tmake_file="i386/t-cygming i386/t-crtfm" ;; +i[34567]86-*-mingw*) + extra_parts="crtbegin.o crtend.o crtfastmath.o" + tmake_file="i386/t-cygming i386/t-crtfm" + md_unwind_header=i386/w32-unwind.h + ;; x86_64-*-mingw*) ;; i[34567]86-*-interix3*) @@ -369,11 +390,13 @@ ia64*-*-freebsd*) ia64*-*-linux*) extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o" tmake_file="ia64/t-ia64 t-softfp ia64/t-fprules-softfp ia64/t-softfp-compat" + md_unwind_header=ia64/linux-unwind.h ;; ia64*-*-hpux*) ;; ia64-hp-*vms*) tmake_file="vms/t-vms vms/t-vms64 ia64/t-vms" + md_unwind_header=ia64/vms-unwind.h ;; iq2000*-*-elf*) ;; @@ -400,10 +423,12 @@ m68k*-*-netbsdelf*) m68k*-*-openbsd*) ;; m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux with uClibc + md_unwind_header=m68k/linux-unwind.h ;; -m68k-*-linux*) # Motorola m68k's running GNU/Linux +m68k-*-linux*) # Motorola m68k's running GNU/Linux # with ELF format using glibc 2 # aka the GNU/Linux C library 6. + md_unwind_header=m68k/linux-unwind.h ;; m68k-*-rtems*) ;; @@ -421,10 +446,12 @@ mips*-*-netbsd*) # NetBSD/mips, either endian. mips64*-*-linux*) extra_parts="$extra_parts crtfastmath.o" tmake_file="{$tmake_file} mips/t-crtfm" + md_unwind_header=mips/linux-unwind.h ;; mips*-*-linux*) # Linux MIPS, either endian. extra_parts="$extra_parts crtfastmath.o" tmake_file="{$tmake_file} mips/t-crtfm" + md_unwind_header=mips/linux-unwind.h ;; mips*-*-openbsd*) ;; @@ -469,6 +496,15 @@ pdp11-*-*) picochip-*-*) ;; powerpc-*-darwin*) + case ${host} in + *-*-darwin9* | *-*-darwin[12][0-9]*) + # libSystem contains unwind information for signal frames since + # Darwin 9. + ;; + *) + md_unwind_header=rs6000/darwin-unwind.h + ;; + esac ;; powerpc64-*-darwin*) ;; @@ -495,6 +531,7 @@ powerpc-*-rtems*) ;; powerpc-*-linux* | powerpc64-*-linux*) tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp" + md_unwind_header=rs6000/linux-unwind.h ;; powerpc-wrs-vxworks|powerpc-wrs-vxworksae) ;; @@ -518,12 +555,15 @@ rx-*-elf) ;; s390-*-linux*) tmake_file="${tmake_file} s390/t-crtstuff s390/t-linux s390/32/t-floattodi" + md_unwind_header=s390/linux-unwind.h ;; s390x-*-linux*) tmake_file="${tmake_file} s390/t-crtstuff s390/t-linux" + md_unwind_header=s390/linux-unwind.h ;; s390x-ibm-tpf*) tmake_file="${tmake_file} s390/t-crtstuff s390/t-tpf" + md_unwind_header-s390/tpf-unwind.h ;; score-*-elf) ;; @@ -534,6 +574,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ case ${host} in sh*-*-linux*) tmake_file="${tmake_file} sh/t-linux" + md_unwind_header=sh/unwind-linux.h ;; esac ;; @@ -559,6 +600,7 @@ sparc-*-elf*) sparc-*-linux*) # SPARC's running GNU/Linux, libc6 extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} t-crtfm" + md_unwind_header=sparc/linux.h ;; sparc-*-rtems* | sparc64-*-rtems* ) tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems" @@ -567,6 +609,7 @@ sparc-*-rtems* | sparc64-*-rtems* ) sparc*-*-solaris2*) tmake_file="$tmake_file t-crtfm" extra_parts="$extra_parts crtfastmath.o" + md_unwind_header=sparc/sol2-unwind.h ;; sparc64-*-elf*) tmake_file="${tmake_file} t-crtin t-crtfm" @@ -579,6 +622,7 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*) sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} t-crtfm" + md_unwind_header=sparc/linux-unwind.h ;; sparc64-*-netbsd*) ;; @@ -601,6 +645,7 @@ xstormy16-*-elf) xtensa*-*-elf*) ;; xtensa*-*-linux*) + md_unwind_header=xtensa/linux-unwind.h ;; am33_2.0-*-linux*) extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" diff --git a/libgcc/config/alpha/linux-unwind.h b/libgcc/config/alpha/linux-unwind.h new file mode 100644 index 00000000000..e43aacfd00b --- /dev/null +++ b/libgcc/config/alpha/linux-unwind.h @@ -0,0 +1,78 @@ +/* DWARF2 EH unwinding support for Alpha Linux. + Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state + +static _Unwind_Reason_Code +alpha_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + struct sigcontext *sc; + long new_cfa, i; + + if (pc[0] != 0x47fe0410 /* mov $30,$16 */ + || pc[2] != 0x00000083 /* callsys */) + return _URC_END_OF_STACK; + if (context->cfa == 0) + return _URC_END_OF_STACK; + if (pc[1] == 0x201f0067) /* lda $0,NR_sigreturn */ + sc = context->cfa; + else if (pc[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */ + { + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + sc = &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + new_cfa = sc->sc_regs[30]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 30; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + for (i = 0; i < 30; ++i) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (long)&sc->sc_regs[i] - new_cfa; + } + for (i = 0; i < 31; ++i) + { + fs->regs.reg[i+32].how = REG_SAVED_OFFSET; + fs->regs.reg[i+32].loc.offset + = (long)&sc->sc_fpregs[i] - new_cfa; + } + fs->regs.reg[64].how = REG_SAVED_OFFSET; + fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa; + fs->retaddr_column = 64; + return _URC_NO_REASON; +} diff --git a/libgcc/config/alpha/osf5-unwind.h b/libgcc/config/alpha/osf5-unwind.h new file mode 100644 index 00000000000..c649099349e --- /dev/null +++ b/libgcc/config/alpha/osf5-unwind.h @@ -0,0 +1,329 @@ +/* DWARF2 EH unwinding support for Alpha Tru64. + Copyright (C) 2010 Free Software Foundation, Inc. + +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. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* This file implements the MD_FALLBACK_FRAME_STATE_FOR macro, triggered when + the GCC table based unwinding process hits a frame for which no unwind info + has been registered. This typically occurs when raising an exception from a + signal handler, because the handler is actually called from the OS kernel. + + The basic idea is to detect that we are indeed trying to unwind past a + signal handler and to fill out the GCC internal unwinding structures for + the OS kernel frame as if it had been directly called from the interrupted + context. + + This is all assuming that the code to set the handler asked the kernel to + pass a pointer to such context information. */ + +/* -------------------------------------------------------------------------- + -- Basic principles of operation: + -------------------------------------------------------------------------- + + 1/ We first need a way to detect if we are trying to unwind past a signal + handler. + + The typical method that is used on most platforms is to look at the code + around the return address we have and check if it matches the OS code + calling a handler. To determine what this code is expected to be, get a + breakpoint into a real signal handler and look at the code around the + return address. Depending on the library versions the pattern of the + signal handler is different; this is the reason why we check against more + than one pattern. + + On this target, the return address is right after the call and every + instruction is 4 bytes long. For the simple case of a null dereference in + a single-threaded app, it went like: + + # Check that we indeed have something we expect: the instruction right + # before the return address is within a __sigtramp function and is a call. + + [... run gdb and break at the signal handler entry ...] + + (gdb) x /i $ra-4 + <__sigtramp+160>: jsr ra,(a3),0x3ff800d0ed4 <_fpdata+36468> + + # Look at the code around that return address, and eventually observe a + # significantly large chunk of *constant* code right before the call: + + (gdb) x /10i $ra-44 + <__sigtramp+120>: lda gp,-27988(gp) + <__sigtramp+124>: ldq at,-18968(gp) + <__sigtramp+128>: lda t0,-1 + <__sigtramp+132>: stq t0,0(at) + <__sigtramp+136>: ldq at,-18960(gp) + <__sigtramp+140>: ldl t1,8(at) + <__sigtramp+144>: ldq at,-18960(gp) + <__sigtramp+148>: stl t1,12(at) + <__sigtramp+152>: ldq at,-18960(gp) + <__sigtramp+156>: stl t0,8(at) + + # The hexadecimal equivalent that we will have to match is: + + (gdb) x /10x $ra-44 + <__sigtramp+120>: 0x23bd92ac 0xa79db5e8 0x203fffff 0xb43c0000 + <__sigtramp+136>: 0xa79db5f0 0xa05c0008 0xa79db5f0 0xb05c000c + <__sigtramp+152>: 0xa79db5f0 0xb03c0008 + + The problem observed on this target with this approach is that although + we found a constant set of instruction patterns there were some + gp-related offsets that made the machine code to differ from one + installation to another. This problem could have been overcome by masking + these offsets, but we found that it would be simpler and more efficient to + check whether the return address was part of a signal handler, by comparing + it against some expected code offset from __sigtramp. + + # Check that we indeed have something we expect: the instruction + # right before the return address is within a __sigtramp + # function and is a call. We also need to obtain the offset + # between the return address and the start address of __sigtramp. + + [... run gdb and break at the signal handler entry ...] + + (gdb) x /2i $ra-4 + <__sigtramp+160>: jsr ra,(a3),0x3ff800d0ed4 <_fpdata+36468> + <__sigtramp+164>: ldah gp,16381(ra) + + (gdb) p (long)$ra - (long)&__sigtramp + $2 = 164 + + -------------------------------------------------------------------------- + + 2/ Once we know we are going through a signal handler, we need a way to + retrieve information about the interrupted run-time context. + + On this platform, the third handler's argument is a pointer to a structure + describing this context (struct sigcontext *). We unfortunately have no + direct way to transfer this value here, so a couple of tricks are required + to compute it. + + As documented at least in some header files (e.g. sys/machine/context.h), + the structure the handler gets a pointer to is located on the stack. As of + today, while writing this macro, we have unfortunately not been able to + find a detailed description of the full stack layout at handler entry time, + so we'll have to resort to empirism :) + + When unwinding here, we have the handler's CFA at hand, as part of the + current unwinding context which is one of our arguments. We presume that + for each call to a signal handler by the same kernel routine, the context's + structure location on the stack is always at the same offset from the + handler's CFA, and we compute that offset from bare observation: + + For the simple case of a bare null dereference in a single-threaded app, + computing the offset was done using GNAT like this: + + # Break on the first handler's instruction, before the prologue to have the + # CFA in $sp, and get there: + + (gdb) b *&__gnat_error_handler + Breakpoint 1 at 0x120016090: file init.c, line 378. + + (gdb) r + Program received signal SIGSEGV, Segmentation fault. + + (gdb) c + Breakpoint 1, __gnat_error_handler (sig=..., sip=..., context=...) + + # The displayed argument value are meaningless because we stopped before + # their final "homing". We know they are passed through $a0, $a1 and $a2 + # from the ABI, though, so ... + + # Observe that $sp and the context pointer are in the same (stack) area, + # and compute the offset: + + (gdb) p /x $sp + $2 = 0x11fffbc80 + + (gdb) p /x $a2 + $3 = 0x11fffbcf8 + + (gdb) p /x (long)$a2 - (long)$sp + $4 = 0x78 + + -------------------------------------------------------------------------- + + 3/ Once we know we are unwinding through a signal handler and have the + address of the structure describing the interrupted context at hand, we + have to fill the internal frame-state/unwind-context structures properly + to allow the unwinding process to proceed. + + Roughly, we are provided with an *unwinding* CONTEXT, describing the state + of some point P in the call chain we are unwinding through. The macro we + implement has to fill a "frame state" structure FS that describe the P's + caller state, by way of *rules* to compute its CFA, return address, and + **saved** registers *locations*. + + For the case we are going to deal with, the caller is some kernel code + calling a signal handler, and: + + o The saved registers are all in the interrupted run-time context, + + o The CFA is the stack pointer value when the kernel code is entered, that + is, the stack pointer value at the interruption point, also part of the + interrupted run-time context. + + o We want the return address to appear as the address of the active + instruction at the interruption point, so that the unwinder proceeds as + if the interruption had been a regular call. This address is also part + of the interrupted run-time context. + + -- + + Also, note that there is an important difference between the return address + we need to claim for the kernel frame and the value of the return address + register at the interruption point. + + The latter might be required to be able to unwind past the interrupted + routine, for instance if it is interrupted before saving the incoming + register value in its own frame, which may typically happen during stack + probes for stack-checking purposes. + + It is then essential that the rules stated to locate the kernel frame + return address don't clobber the rules describing where is saved the return + address register at the interruption point, so some scratch register state + entry should be used for the former. We have DWARF_ALT_FRAME_RETURN_COLUMN + at hand exactly for that purpose. + + -------------------------------------------------------------------------- + + 4/ Depending on the context (single-threaded or multi-threaded app, ...), + the code calling the handler and the handler-cfa to interrupted-context + offset might change, so we use a simple generic data structure to track + the possible variants. */ + +/* This is the structure to wrap information about each possible sighandler + caller we may have to identify. */ + +typedef struct { + /* Expected return address when being called from a sighandler. */ + void *ra_value; + + /* Offset to get to the sigcontext structure from the handler's CFA + when the pattern matches. */ + int cfa_to_context_offset; + +} sighandler_call_t; + +/* Helper macro for MD_FALLBACK_FRAME_STATE_FOR below. + + Look at RA to see if it matches within a sighandler caller. + Set SIGCTX to the corresponding sigcontext structure (computed from + CFA) if it does, or to 0 otherwise. */ + +#define COMPUTE_SIGCONTEXT_FOR(RA,CFA,SIGCTX) \ +do { \ + /* Define and register the applicable patterns. */ \ + extern void __sigtramp (void); \ + \ + sighandler_call_t sighandler_calls [] = { \ + {__sigtramp + 164, 0x78} \ + }; \ + \ + int n_patterns_to_match \ + = sizeof (sighandler_calls) / sizeof (sighandler_call_t); \ + \ + int pn; /* pattern number */ \ + \ + int match = 0; /* Did last pattern match ? */ \ + \ + /* Try to match each pattern in turn. */ \ + for (pn = 0; !match && pn < n_patterns_to_match; pn ++) \ + match = ((RA) == sighandler_calls[pn].ra_value); \ + \ + (SIGCTX) = (struct sigcontext *) \ + (match ? ((CFA) + sighandler_calls[pn - 1].cfa_to_context_offset) : 0); \ +} while (0); + +#include + +#define REG_SP 30 /* hard reg for stack pointer */ +#define REG_RA 26 /* hard reg for return address */ + +#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state + +static _Unwind_Reason_Code +alpha_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* Return address and CFA of the frame we're attempting to unwind through, + possibly a signal handler. */ + void *ctx_ra = (void *)context->ra; + void *ctx_cfa = (void *)context->cfa; + + /* CFA of the intermediate abstract kernel frame between the interrupted + code and the signal handler, if we're indeed unwinding through a signal + handler. */ + void *k_cfa; + + /* Pointer to the sigcontext structure pushed by the kernel when we're + unwinding through a signal handler. */ + struct sigcontext *sigctx; + int i; + + COMPUTE_SIGCONTEXT_FOR (ctx_ra, ctx_cfa, sigctx); + + if (sigctx == 0) + return _URC_END_OF_STACK; + + /* The kernel frame's CFA is exactly the stack pointer value at the + interruption point. */ + k_cfa = (void *) sigctx->sc_regs [REG_SP]; + + /* State the rules to compute the CFA we have the value of: use the + previous CFA and offset by the difference between the two. See + uw_update_context_1 for the supporting details. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = k_cfa - ctx_cfa; + + /* Fill the internal frame_state structure with information stating + where each register of interest in the saved context can be found + from the CFA. */ + + /* The general registers are in sigctx->sc_regs. Leave out r31, which + is read-as-zero. It makes no sense restoring it, and we are going to + use the state entry for the kernel return address rule below. + + This loop must cover at least all the callee-saved registers, and + we just don't bother specializing the set here. */ + for (i = 0; i <= 30; i ++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (void *) &sigctx->sc_regs[i] - (void *) k_cfa; + } + + /* Ditto for the floating point registers in sigctx->sc_fpregs. */ + for (i = 0; i <= 31; i ++) + { + fs->regs.reg[32+i].how = REG_SAVED_OFFSET; + fs->regs.reg[32+i].loc.offset + = (void *) &sigctx->sc_fpregs[i] - (void *) k_cfa; + } + + /* State the rules to find the kernel's code "return address", which + is the address of the active instruction when the signal was caught, + in sigctx->sc_pc. Use DWARF_ALT_FRAME_RETURN_COLUMN since the return + address register is a general register and should be left alone. */ + fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset + = (void *) &sigctx->sc_pc - (void *) k_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} diff --git a/libgcc/config/alpha/vms-unwind.h b/libgcc/config/alpha/vms-unwind.h new file mode 100644 index 00000000000..71cb7b87920 --- /dev/null +++ b/libgcc/config/alpha/vms-unwind.h @@ -0,0 +1,293 @@ +/* Fallback frame unwinding for Alpha/VMS. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2009, 2010, 2011 + Free Software Foundation, Inc. + + 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 + . */ + +#include +#include +#include +#include +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR alpha_vms_fallback_frame_state + +typedef void * ADDR; +typedef unsigned long long REG; +typedef PDSCDEF * PV; + +#define REG_AT(addr) (*(REG *)(addr)) +#define ADDR_AT(addr) (*(ADDR *)(addr)) + +/* Compute pointer to procedure descriptor (Procedure Value) from Frame + Pointer FP, according to the rules in [ABI-3.5.1 Current Procedure]. */ +#define PV_FOR(FP) \ + (((FP) != 0) \ + ? (((REG_AT (FP) & 0x7) == 0) ? *(PDSCDEF **)(FP) : (PDSCDEF *)(FP)) : 0) + +extern int SYS$GL_CALL_HANDL; +/* This is actually defined as a "long", but in system code where longs + are always 4bytes while GCC longs might be 8bytes. */ + +#define UPDATE_FS_FOR_CFA_GR(FS, GRN, LOC, CFA) \ +do { \ +(FS)->regs.reg[GRN].how = REG_SAVED_OFFSET; \ +(FS)->regs.reg[GRN].loc.offset = (_Unwind_Sword) ((REG) (LOC) - (REG) (CFA)); \ +} while (0); + +#define GIVEUP_ON_FAILURE(STATUS) \ + { if ((((STATUS) & 1) != 1)) return _URC_END_OF_STACK; } +#define DENOTES_EXC_DISPATCHER(PV) ((PV) == (ADDR) (REG) SYS$GL_CALL_HANDL) + +#define RA_COLUMN (DWARF_ALT_FRAME_RETURN_COLUMN) + +static int +alpha_vms_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + static int eh_debug = -1; + + /* Our goal is to update FS to reflect the state one step up CONTEXT, that + is: the CFA, return address and *saved* registers locations associated + with the function designated by CONTEXT->ra. We are called when the + libgcc unwinder has not found any dwarf FDE for this address, which + typically happens when trying to propagate a language exception through a + signal global vector or frame based handler. + + The CONTEXT->reg[] entries reflect the state/location of register saves + so designate values live at the CONTEXT->ra point. Of precious value to + us here is the frame pointer (r29), which gets us a procedure value. */ + + PV pv = (context->reg[29] != 0) ? PV_FOR (ADDR_AT (context->reg[29])) : 0; + + int pkind = pv ? pv->pdsc$w_flags & 0xf : 0; + /* VMS procedure kind, as indicated by the procedure descriptor. We only + know how to deal with FP_STACK or FP_REGISTER here. */ + + ADDR new_cfa = 0; + /* CFA we will establish for the caller, computed in different ways, + e.g. depending whether we cross an exception dispatcher frame. */ + + CHFCTX *chfctx = 0; + /* Pointer to the VMS CHF context associated with an exception dispatcher + frame, if we happen to come across one. */ + + int i,j; + + if (eh_debug == -1) + { + char * eh_debug_env = getenv ("EH_DEBUG"); + eh_debug = eh_debug_env ? atoi (eh_debug_env) : 0; + } + + if (eh_debug) + printf ("MD_FALLBACK running ...\n"); + + /* We only know how to deal with stack or reg frame procedures, so give + up if we're handed anything else. */ + if (pkind != PDSC$K_KIND_FP_STACK && pkind != PDSC$K_KIND_FP_REGISTER) + return _URC_END_OF_STACK; + + if (eh_debug) + printf ("FALLBACK: CTX FP = 0x%p, PV = 0x%p, EN = 0x%llx, RA = 0x%p\n", + ADDR_AT (context->reg[29]), pv, pv->pdsc$q_entry, context->ra); + + fs->retaddr_column = RA_COLUMN; + + /* If PV designates a VMS exception vector or condition handler, we need to + do as if the caller was the signaling point and estabish the state of the + intermediate VMS code (CFA, RA and saved register locations) as if it was + a single regular function. This requires special processing. + + The datastructures available from an condition dispatcher frame (signal + context) do not contain the values of most callee-saved registers, so + whathever PV designates, we need to account for the registers it saves. + + Besides, we need to express all the locations with respect to a + consistent CFA value, so we compute this first. */ + + if (DENOTES_EXC_DISPATCHER (pv)) + { + /* The CFA to establish is the signaling point's stack pointer. We + compute it using the system invocation context unwinding services and + save the CHF context data pointer along the way for later uses. */ + + INVO_CONTEXT_BLK icb; + int status, invo_handle; + + if (eh_debug) + printf ("FALLBACK: SYS$HANDLER\n"); + + icb.libicb$q_ireg [29] = REG_AT (context->reg[29]); + icb.libicb$q_ireg [30] = 0; + invo_handle = LIB$GET_INVO_HANDLE (&icb); + + status = LIB$GET_INVO_CONTEXT (invo_handle, &icb); + GIVEUP_ON_FAILURE (status); + + chfctx = (CHFCTX *) icb.libicb$ph_chfctx_addr; + + status = LIB$GET_PREV_INVO_CONTEXT (&icb); + GIVEUP_ON_FAILURE (status); + + new_cfa = (ADDR) icb.libicb$q_ireg[30]; + } + else + { + /* The CFA to establish is the SP value on entry of the procedure + designated by PV, which we compute as the corresponding frame base + register value + frame size. Note that the frame base may differ + from CONTEXT->cfa, typically if the caller has performed dynamic + stack allocations. */ + + int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; + ADDR base_addr = ADDR_AT (context->reg[base_reg]); + + new_cfa = base_addr + pv->pdsc$l_size; + } + + /* State to compute the caller's CFA by adding an offset to the current + one in CONTEXT. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - context->cfa; + + /* Regular unwind first, accounting for the register saves performed by + the procedure designated by PV. */ + + switch (pkind) + { + case PDSC$K_KIND_FP_STACK: + { + /* The saved registers are all located in the Register Save Area, + except for the procedure value register (R27) found at the frame + base address. */ + + int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; + ADDR base_addr = ADDR_AT (context->reg[base_reg]); + ADDR rsa_addr = base_addr + pv->pdsc$w_rsa_offset; + + if (eh_debug) + printf ("FALLBACK: STACK frame procedure\n"); + + UPDATE_FS_FOR_CFA_GR (fs, 27, base_addr, new_cfa); + + /* The first RSA entry is for the return address register, R26. */ + + UPDATE_FS_FOR_CFA_GR (fs, 26, rsa_addr, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, rsa_addr, new_cfa); + + /* The following entries are for registers marked as saved according + to ireg_mask. */ + for (i = 0, j = 0; i < 32; i++) + if ((1 << i) & pv->pdsc$l_ireg_mask) + UPDATE_FS_FOR_CFA_GR (fs, i, rsa_addr + 8 * ++j, new_cfa); + + /* ??? floating point registers ? */ + + break; + } + + case PDSC$K_KIND_FP_REGISTER: + { + if (eh_debug) + printf ("FALLBACK: REGISTER frame procedure\n"); + + fs->regs.reg[RA_COLUMN].how = REG_SAVED_REG; + fs->regs.reg[RA_COLUMN].loc.reg = pv->pdsc$b_save_ra; + + fs->regs.reg[29].how = REG_SAVED_REG; + fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; + + break; + } + + default: + /* Should never reach here. */ + return _URC_END_OF_STACK; + } + + /* If PV designates an exception dispatcher, we have to adjust the return + address column to get at the signal occurrence point, and account for + what the CHF context contains. */ + + if (DENOTES_EXC_DISPATCHER (pv)) + { + /* The PC of the instruction causing the condition is available from the + signal argument vector. Extra saved register values are available + from the mechargs array. */ + + CHF$SIGNAL_ARRAY *sigargs + = (CHF$SIGNAL_ARRAY *) chfctx->chfctx$q_sigarglst; + + CHF$MECH_ARRAY *mechargs + = (CHF$MECH_ARRAY *) chfctx->chfctx$q_mcharglst; + + ADDR condpc_addr + = &((int *)(&sigargs->chf$l_sig_name)) [sigargs->chf$is_sig_args-2]; + + ADDR rei_frame_addr = (void *) mechargs->chf$q_mch_esf_addr; + + /* Adjust the return address location. */ + + UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, condpc_addr, new_cfa); + + /* The frame pointer at the condition point is available from the + chf context directly. */ + + UPDATE_FS_FOR_CFA_GR (fs, 29, &chfctx->chfctx$q_expt_fp, new_cfa); + + /* Registers available from the mechargs array. */ + + UPDATE_FS_FOR_CFA_GR (fs, 0, &mechargs->chf$q_mch_savr0, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 1, &mechargs->chf$q_mch_savr1, new_cfa); + + UPDATE_FS_FOR_CFA_GR (fs, 16, &mechargs->chf$q_mch_savr16, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 17, &mechargs->chf$q_mch_savr17, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 18, &mechargs->chf$q_mch_savr18, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 19, &mechargs->chf$q_mch_savr19, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 20, &mechargs->chf$q_mch_savr20, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 21, &mechargs->chf$q_mch_savr21, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 22, &mechargs->chf$q_mch_savr22, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 23, &mechargs->chf$q_mch_savr23, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 24, &mechargs->chf$q_mch_savr24, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 25, &mechargs->chf$q_mch_savr25, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 26, &mechargs->chf$q_mch_savr26, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 27, &mechargs->chf$q_mch_savr27, new_cfa); + UPDATE_FS_FOR_CFA_GR (fs, 28, &mechargs->chf$q_mch_savr28, new_cfa); + + /* Registers R2 to R7 are available from the rei frame pointer. */ + + for (i = 2; i <= 7; i ++) + UPDATE_FS_FOR_CFA_GR (fs, i, rei_frame_addr+(i - 2)*8, new_cfa); + + /* ??? floating point registers ? */ + } + + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + + + diff --git a/libgcc/config/bfin/linux-unwind.h b/libgcc/config/bfin/linux-unwind.h new file mode 100644 index 00000000000..88c8285632d --- /dev/null +++ b/libgcc/config/bfin/linux-unwind.h @@ -0,0 +1,164 @@ +/* DWARF2 EH unwinding support for Blackfin. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + Don't use this at all if inhibit_libc is used. */ + +#ifndef inhibit_libc + +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR bfin_fallback_frame_state + +static _Unwind_Reason_Code +bfin_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + + /* P0=__NR_rt_sigreturn (X); EXCPT 0x0; */ + if (*(unsigned short *)pc == 0xe128 + && *(unsigned short *)(pc + 2) == 0x00ad + && *(unsigned short *)(pc + 4) == 0x00a0) + { + struct rt_sigframe { + int sig; + struct siginfo *pinfo; + void *puc; + char retcode[8]; + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + + /* The void * cast is necessary to avoid an aliasing warning. + The aliasing warning is correct, but should not be a problem + because it does not alias anything. */ + sc = (struct sigcontext *)(void *)&rt_->uc.uc_mcontext.gregs; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->sc_usp; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 14; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&sc->sc_r0 - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&sc->sc_r1 - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&sc->sc_r2 - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&sc->sc_r3 - new_cfa; + fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.reg[4].loc.offset = (long)&sc->sc_r4 - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&sc->sc_r5 - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&sc->sc_r6 - new_cfa; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&sc->sc_r7 - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&sc->sc_p0 - new_cfa; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long)&sc->sc_p1 - new_cfa; + fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.reg[10].loc.offset = (long)&sc->sc_p2 - new_cfa; + fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.reg[11].loc.offset = (long)&sc->sc_p3 - new_cfa; + fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.reg[12].loc.offset = (long)&sc->sc_p4 - new_cfa; + fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.reg[13].loc.offset = (long)&sc->sc_p5 - new_cfa; + + fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.reg[15].loc.offset = (long)&sc->sc_fp - new_cfa; + fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.reg[16].loc.offset = (long)&sc->sc_i0 - new_cfa; + fs->regs.reg[17].how = REG_SAVED_OFFSET; + fs->regs.reg[17].loc.offset = (long)&sc->sc_i1 - new_cfa; + fs->regs.reg[18].how = REG_SAVED_OFFSET; + fs->regs.reg[18].loc.offset = (long)&sc->sc_i2 - new_cfa; + fs->regs.reg[19].how = REG_SAVED_OFFSET; + fs->regs.reg[19].loc.offset = (long)&sc->sc_i3 - new_cfa; + fs->regs.reg[20].how = REG_SAVED_OFFSET; + fs->regs.reg[20].loc.offset = (long)&sc->sc_b0 - new_cfa; + fs->regs.reg[21].how = REG_SAVED_OFFSET; + fs->regs.reg[21].loc.offset = (long)&sc->sc_b1 - new_cfa; + fs->regs.reg[22].how = REG_SAVED_OFFSET; + fs->regs.reg[22].loc.offset = (long)&sc->sc_b2 - new_cfa; + fs->regs.reg[23].how = REG_SAVED_OFFSET; + fs->regs.reg[23].loc.offset = (long)&sc->sc_b3 - new_cfa; + fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.reg[24].loc.offset = (long)&sc->sc_l0 - new_cfa; + fs->regs.reg[25].how = REG_SAVED_OFFSET; + fs->regs.reg[25].loc.offset = (long)&sc->sc_l1 - new_cfa; + fs->regs.reg[26].how = REG_SAVED_OFFSET; + fs->regs.reg[26].loc.offset = (long)&sc->sc_l2 - new_cfa; + fs->regs.reg[27].how = REG_SAVED_OFFSET; + fs->regs.reg[27].loc.offset = (long)&sc->sc_l3 - new_cfa; + fs->regs.reg[28].how = REG_SAVED_OFFSET; + fs->regs.reg[28].loc.offset = (long)&sc->sc_m0 - new_cfa; + fs->regs.reg[29].how = REG_SAVED_OFFSET; + fs->regs.reg[29].loc.offset = (long)&sc->sc_m1 - new_cfa; + fs->regs.reg[30].how = REG_SAVED_OFFSET; + fs->regs.reg[30].loc.offset = (long)&sc->sc_m2 - new_cfa; + fs->regs.reg[31].how = REG_SAVED_OFFSET; + fs->regs.reg[31].loc.offset = (long)&sc->sc_m3 - new_cfa; + /* FIXME: Handle A0, A1, CC. */ + fs->regs.reg[35].how = REG_SAVED_OFFSET; + fs->regs.reg[35].loc.offset = (long)&sc->sc_rets - new_cfa; + fs->regs.reg[36].how = REG_SAVED_OFFSET; + fs->regs.reg[36].loc.offset = (long)&sc->sc_pc - new_cfa; + fs->regs.reg[37].how = REG_SAVED_OFFSET; + fs->regs.reg[37].loc.offset = (long)&sc->sc_retx - new_cfa; + + fs->regs.reg[40].how = REG_SAVED_OFFSET; + fs->regs.reg[40].loc.offset = (long)&sc->sc_astat - new_cfa; + fs->regs.reg[41].how = REG_SAVED_OFFSET; + fs->regs.reg[41].loc.offset = (long)&sc->sc_seqstat - new_cfa; + + fs->regs.reg[44].how = REG_SAVED_OFFSET; + fs->regs.reg[44].loc.offset = (long)&sc->sc_lt0 - new_cfa; + fs->regs.reg[45].how = REG_SAVED_OFFSET; + fs->regs.reg[45].loc.offset = (long)&sc->sc_lt1 - new_cfa; + fs->regs.reg[46].how = REG_SAVED_OFFSET; + fs->regs.reg[46].loc.offset = (long)&sc->sc_lc0 - new_cfa; + fs->regs.reg[47].how = REG_SAVED_OFFSET; + fs->regs.reg[47].loc.offset = (long)&sc->sc_lc1 - new_cfa; + fs->regs.reg[48].how = REG_SAVED_OFFSET; + fs->regs.reg[48].loc.offset = (long)&sc->sc_lb0 - new_cfa; + fs->regs.reg[49].how = REG_SAVED_OFFSET; + fs->regs.reg[49].loc.offset = (long)&sc->sc_lb1 - new_cfa; + fs->retaddr_column = 35; + + return _URC_NO_REASON; +} + +#endif /* ifdef inhibit_libc */ diff --git a/libgcc/config/i386/linux-unwind.h b/libgcc/config/i386/linux-unwind.h new file mode 100644 index 00000000000..de44823e053 --- /dev/null +++ b/libgcc/config/i386/linux-unwind.h @@ -0,0 +1,197 @@ +/* DWARF2 EH unwinding support for AMD x86-64 and x86. + Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 + Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + Don't use this at all if inhibit_libc is used. */ + +#ifndef inhibit_libc + +#ifdef __x86_64__ + +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state + +static _Unwind_Reason_Code +x86_64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + + /* movq __NR_rt_sigreturn, %rax ; syscall */ + if (*(unsigned char *)(pc+0) == 0x48 + && *(unsigned long *)(pc+1) == 0x050f0000000fc0c7) + { + struct ucontext *uc_ = context->cfa; + /* The void * cast is necessary to avoid an aliasing warning. + The aliasing warning is correct, but should not be a problem + because it does not alias anything. */ + sc = (struct sigcontext *) (void *) &uc_->uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->rsp; + fs->regs.cfa_how = CFA_REG_OFFSET; + /* Register 7 is rsp */ + fs->regs.cfa_reg = 7; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&sc->rax - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&sc->rdx - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&sc->rcx - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&sc->rbx - new_cfa; + fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.reg[4].loc.offset = (long)&sc->rsi - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&sc->rdi - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&sc->rbp - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&sc->r8 - new_cfa; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long)&sc->r9 - new_cfa; + fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.reg[10].loc.offset = (long)&sc->r10 - new_cfa; + fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.reg[11].loc.offset = (long)&sc->r11 - new_cfa; + fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.reg[12].loc.offset = (long)&sc->r12 - new_cfa; + fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.reg[13].loc.offset = (long)&sc->r13 - new_cfa; + fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.reg[14].loc.offset = (long)&sc->r14 - new_cfa; + fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.reg[15].loc.offset = (long)&sc->r15 - new_cfa; + fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa; + fs->retaddr_column = 16; + fs->signal_frame = 1; + return _URC_NO_REASON; +} + +#else /* ifdef __x86_64__ */ + +/* There's no sys/ucontext.h for glibc 2.0, so no + signal-turned-exceptions for them. There's also no configure-run for + the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the + target libc version macro should be enough. */ +#if defined __GLIBC__ && !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) + +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state + +static _Unwind_Reason_Code +x86_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + + /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ + if (*(unsigned short *)(pc+0) == 0xb858 + && *(unsigned int *)(pc+2) == 119 + && *(unsigned short *)(pc+6) == 0x80cd) + sc = context->cfa + 4; + /* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ + else if (*(unsigned char *)(pc+0) == 0xb8 + && *(unsigned int *)(pc+1) == 173 + && *(unsigned short *)(pc+5) == 0x80cd) + { + struct rt_sigframe { + int sig; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + /* The void * cast is necessary to avoid an aliasing warning. + The aliasing warning is correct, but should not be a problem + because it does not alias anything. */ + sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->esp; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 4; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&sc->eax - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&sc->ebx - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&sc->ecx - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&sc->edx - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&sc->esi - new_cfa; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&sc->edi - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&sc->ebp - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&sc->eip - new_cfa; + fs->retaddr_column = 8; + fs->signal_frame = 1; + return _URC_NO_REASON; +} + +#define MD_FROB_UPDATE_CONTEXT x86_frob_update_context + +/* Fix up for kernels that have vDSO, but don't have S flag in it. */ + +static void +x86_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs ATTRIBUTE_UNUSED) +{ + unsigned char *pc = context->ra; + + /* movl $__NR_rt_sigreturn,%eax ; {int $0x80 | syscall} */ + if (*(unsigned char *)(pc+0) == 0xb8 + && *(unsigned int *)(pc+1) == 173 + && (*(unsigned short *)(pc+5) == 0x80cd + || *(unsigned short *)(pc+5) == 0x050f)) + _Unwind_SetSignalFrame (context, 1); +} + +#endif /* not glibc 2.0 */ +#endif /* ifdef __x86_64__ */ +#endif /* ifdef inhibit_libc */ diff --git a/libgcc/config/i386/sol2-unwind.h b/libgcc/config/i386/sol2-unwind.h new file mode 100644 index 00000000000..d93b60c781c --- /dev/null +++ b/libgcc/config/i386/sol2-unwind.h @@ -0,0 +1,289 @@ +/* DWARF2 EH unwinding support for AMD x86-64 and x86. + Copyright (C) 2009, 2010 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include +#include + +#ifdef __x86_64__ + +#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state + +static _Unwind_Reason_Code +x86_64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + mcontext_t *mctx; + long new_cfa; + + if (/* Solaris 10+ + ------------ + <__sighndlr+0>: push %rbp + <__sighndlr+1>: mov %rsp,%rbp + <__sighndlr+4>: callq *%rcx + <__sighndlr+6>: leaveq <--- PC + <__sighndlr+7>: retq */ + *(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855) + + /* We need to move up three frames: + + <-- context->cfa + __sighndlr + call_user_handler + sigacthandler + + + context->cfa points into the frame after the saved frame pointer and + saved pc (struct frame). + + The ucontext_t structure is in the kernel frame after the signal + number and a siginfo_t *. Since the frame sizes vary even within + Solaris 10 updates, we need to walk the stack to get there. */ + { + struct frame *fp = (struct frame *) context->cfa - 1; + struct handler_args { + int signo; + siginfo_t *sip; + ucontext_t ucontext; + } *handler_args; + ucontext_t *ucp; + + /* Next frame: __sighndlr frame pointer. */ + fp = (struct frame *) fp->fr_savfp; + /* call_user_handler frame pointer. */ + fp = (struct frame *) fp->fr_savfp; + /* sigacthandler frame pointer. */ + fp = (struct frame *) fp->fr_savfp; + + /* The argument area precedes the struct frame. */ + handler_args = (struct handler_args *) (fp + 1); + ucp = &handler_args->ucontext; + mctx = &ucp->uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = mctx->gregs[REG_RSP]; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 7; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa; + fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa; + fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa; + fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa; + fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa; + fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa; + fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa; + fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa; + fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa; + fs->retaddr_column = 16; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#else + +#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state + +static _Unwind_Reason_Code +x86_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + mcontext_t *mctx; + long new_cfa; + + if (/* Solaris 8 - single-threaded + ---------------------------- + : mov 0x10(%ebp),%esi + : push %esi + : pushl 0xc(%ebp) + : mov 0x8(%ebp),%ecx + : push %ecx + : mov offset(%ebx),%eax + : call *(%eax,%ecx,4) + : add $0xc,%esp <--- PC + : push %esi ... */ + (*(unsigned long *)(pc - 20) == 0x5610758b + && *(unsigned long *)(pc - 16) == 0x8b0c75ff + && *(unsigned long *)(pc - 12) == 0x8b51084d + && *(unsigned char *)(pc - 8) == 0x83 + && *(unsigned long *)(pc - 4) == 0x8814ff00 + && *(unsigned long *)(pc - 0) == 0x560cc483) + + || /* Solaris 8 - multi-threaded + --------------------------- + <__sighndlr+0>: push %ebp + <__sighndlr+1>: mov %esp,%ebp + <__sighndlr+3>: pushl 0x10(%ebp) + <__sighndlr+6>: pushl 0xc(%ebp) + <__sighndlr+9>: pushl 0x8(%ebp) + <__sighndlr+12>: call *0x14(%ebp) + <__sighndlr+15>: leave <--- PC */ + (*(unsigned long *)(pc - 15) == 0xffec8b55 + && *(unsigned long *)(pc - 11) == 0x75ff1075 + && *(unsigned long *)(pc - 7) == 0x0875ff0c + && *(unsigned long *)(pc - 3) == 0xc91455ff) + + || /* Solaris 9 - single-threaded + ---------------------------- + : mov 0x244(%ebx),%ecx + : mov 0x8(%ebp),%eax + : mov (%ecx,%eax,4),%ecx + : pushl 0x10(%ebp) + : pushl 0xc(%ebp) + : push %eax + : call *%ecx + : add $0xc,%esp <--- PC + : pushl 0x10(%ebp) */ + (*(unsigned long *)(pc - 21) == 0x2448b8b + && *(unsigned long *)(pc - 17) == 0x458b0000 + && *(unsigned long *)(pc - 13) == 0x810c8b08 + && *(unsigned long *)(pc - 9) == 0xff1075ff + && *(unsigned long *)(pc - 5) == 0xff500c75 + && *(unsigned long *)(pc - 1) == 0xcc483d1) + + || /* Solaris 9 - multi-threaded, Solaris 10 + --------------------------------------- + <__sighndlr+0>: push %ebp + <__sighndlr+1>: mov %esp,%ebp + <__sighndlr+3>: pushl 0x10(%ebp) + <__sighndlr+6>: pushl 0xc(%ebp) + <__sighndlr+9>: pushl 0x8(%ebp) + <__sighndlr+12>: call *0x14(%ebp) + <__sighndlr+15>: add $0xc,%esp <--- PC + <__sighndlr+18>: leave + <__sighndlr+19>: ret */ + (*(unsigned long *)(pc - 15) == 0xffec8b55 + && *(unsigned long *)(pc - 11) == 0x75ff1075 + && *(unsigned long *)(pc - 7) == 0x0875ff0c + && *(unsigned long *)(pc - 3) == 0x831455ff + && *(unsigned long *)(pc + 1) == 0xc3c90cc4) + + || /* Solaris 11 before snv_125 + -------------------------- + <__sighndlr+0> push %ebp + <__sighndlr+1> mov %esp,%ebp + <__sighndlr+4> pushl 0x10(%ebp) + <__sighndlr+6> pushl 0xc(%ebp) + <__sighndlr+9> pushl 0x8(%ebp) + <__sighndlr+12> call *0x14(%ebp) + <__sighndlr+15> add $0xc,%esp + <__sighndlr+18> leave <--- PC + <__sighndlr+19> ret */ + (*(unsigned long *)(pc - 18) == 0xffec8b55 + && *(unsigned long *)(pc - 14) == 0x7fff107f + && *(unsigned long *)(pc - 10) == 0x0875ff0c + && *(unsigned long *)(pc - 6) == 0x83145fff + && *(unsigned long *)(pc - 1) == 0xc3c90cc4) + + || /* Solaris 11 since snv_125 + ------------------------- + <__sighndlr+0> push %ebp + <__sighndlr+1> mov %esp,%ebp + <__sighndlr+3> and $0xfffffff0,%esp + <__sighndlr+6> sub $0x4,%esp + <__sighndlr+9> pushl 0x10(%ebp) + <__sighndlr+12> pushl 0xc(%ebp) + <__sighndlr+15> pushl 0x8(%ebp) + <__sighndlr+18> call *0x14(%ebp) + <__sighndlr+21> leave <--- PC + <__sighndlr+22> ret */ + (*(unsigned long *)(pc - 21) == 0x83ec8b55 + && *(unsigned long *)(pc - 17) == 0xec83f0e4 + && *(unsigned long *)(pc - 13) == 0x1075ff04 + && *(unsigned long *)(pc - 9) == 0xff0c75ff + && *(unsigned long *)(pc - 5) == 0x55ff0875 + && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914)) + { + struct handler_args { + int signo; + siginfo_t *sip; + ucontext_t *ucontext; + } *handler_args = context->cfa; + mctx = &handler_args->ucontext->uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = mctx->gregs[UESP]; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 4; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + /* The SVR4 register numbering macros aren't usable in libgcc. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa; + fs->retaddr_column = 8; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#endif diff --git a/libgcc/config/i386/w32-unwind.h b/libgcc/config/i386/w32-unwind.h new file mode 100644 index 00000000000..d77b8e3bd9a --- /dev/null +++ b/libgcc/config/i386/w32-unwind.h @@ -0,0 +1,208 @@ +/* Definitions for Dwarf2 EH unwind support for Windows32 targets + Copyright (C) 2007, 2009, 2010, 2011 + Free Software Foundation, Inc. + Contributed by Pascal Obry + +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 +. */ + + +/* This file implements the md_fallback_frame_state_for routine for + Windows, triggered when the GCC table based unwinding process hits a + frame for which no unwind info has been registered. This typically + occurs when raising an exception from a signal handler, because the + handler is actually called from the OS kernel. + + The basic idea is to detect that we are indeed trying to unwind past a + signal handler and to fill out the GCC internal unwinding structures for + the OS kernel frame as if it had been directly called from the + interrupted context. + + This is all assuming that the code to set the handler asked the kernel + to pass a pointer to such context information. + + There is three main parts. + + 1) The first thing to do is to check if we are in a signal context. If + not we can just return as there is nothing to do. We are probably on + some foreign code for which no unwind frame can be found. If this is + a call from the Windows signal handler, then: + + 2) We must get the signal context information. + + * With the standard exception filter: + + This is on Windows pointed to by an EXCEPTION_POINTERS. We know that + the signal handle will call an UnhandledExceptionFilter with this + parameter. The spec for this routine is: + + LONG WINAPI UnhandledExceptionFilter(struct _EXCEPTION_POINTERS*); + + So the pointer to struct _EXCEPTION_POINTERS must be somewhere on the + stack. + + This was found experimentally to always be at offset 0 of the context + frame in all cases handled by this implementation. + + * With the SEH exception handler: + + In this case the signal context is directly on the stack as the SEH + exception handler has the following prototype: + + DWORD + SEH_error_handler (PEXCEPTION_RECORD ExceptionRecord, + PVOID EstablisherFrame, + PCONTEXT ContextRecord, + PVOID DispatcherContext) + + This was found experimentally to always be at offset 56 of the + context frame in all cases handled by this implementation. + + 3) When we have the signal context we just have to save some registers + and set the return address based on the program counter (Eip). + + Note that this implementation follows closely the same principles as the + GNU/Linux and OSF ones. */ + +#ifndef __MINGW64__ + +#define WIN32_MEAN_AND_LEAN +#include +/* Patterns found experimentally to be on a Windows signal handler */ + +/* In a standard exception filter */ + +#define SIG_PAT1 \ + (pc_[-2] == 0xff && pc_[-1] == 0xd0 /* call %eax */ \ + && pc_[0] == 0x83 && pc_[1] == 0xf8) /* cmp 0xdepl,%eax */ + +#define SIG_PAT2 \ + (pc_[-5] == 0xe8 && pc_[-4] == 0x68 /* call (depl16) */ \ + && pc_[0] == 0xc3) /* ret */ + +/* In a Win32 SEH handler */ + +#define SIG_SEH1 \ + (pc_[-5] == 0xe8 /* call addr */ \ + && pc_[0] == 0x83 && pc_[1] == 0xc4 /* add 0xval,%esp */ \ + && pc_[3] == 0xb8) /* mov 0xval,%eax */ + +#define SIG_SEH2 \ + (pc_[-5] == 0x8b && pc_[-4] == 0x4d /* mov depl(%ebp),%ecx */ \ + && pc_[0] == 0x64 && pc_[1] == 0x8b) /* mov %fs:(0), */ \ + +/* In the GCC alloca (stack probing) */ + +#define SIG_ALLOCA \ + (pc_[-1] == 0x83 /* orl $0x0,(%ecx) */ \ + && pc_[0] == 0x9 && pc_[1] == 0 \ + && pc_[2] == 0x2d && pc_[3] == 0 /* subl $0x1000,%eax */ \ + && pc_[4] == 0x10 && pc_[5] == 0) + + +#define MD_FALLBACK_FRAME_STATE_FOR i386_w32_fallback_frame_state + +static _Unwind_Reason_Code +i386_w32_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) + +{ + void * ctx_ra_ = (void *)(context->ra); /* return address */ + void * ctx_cfa_ = (void *)(context->cfa); /* context frame address */ + unsigned char * pc_ = (unsigned char *) ctx_ra_; + + /* In the test below we look for two specific patterns found + experimentally to be in the Windows signal handler. */ + if (SIG_PAT1 || SIG_PAT2 || SIG_SEH1 || SIG_SEH2) + { + PEXCEPTION_POINTERS weinfo_; + PCONTEXT proc_ctx_; + long new_cfa_; + + if (SIG_SEH1) + proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 56)); + else if (SIG_SEH2) + proc_ctx_ = (PCONTEXT) (*(int*)(ctx_cfa_ + 8)); + else + { + weinfo_ = (PEXCEPTION_POINTERS) (*(int*)ctx_cfa_); + proc_ctx_ = weinfo_->ContextRecord; + } + + /* The new context frame address is the stack pointer. */ + new_cfa_ = proc_ctx_->Esp; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column(); + fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; + + /* Restore registers. */ + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)&proc_ctx_->Eax - new_cfa_; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (long)&proc_ctx_->Ebx - new_cfa_; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long)&proc_ctx_->Ecx - new_cfa_; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (long)&proc_ctx_->Edx - new_cfa_; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (long)&proc_ctx_->Esi - new_cfa_; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (long)&proc_ctx_->Edi - new_cfa_; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (long)&proc_ctx_->Ebp - new_cfa_; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long)&proc_ctx_->Eip - new_cfa_; + fs->retaddr_column = 8; + fs->signal_frame = 1; + + return _URC_NO_REASON; + } + + /* Unwinding through _alloca, propagating from a trap triggered by + one of it's probes prior to the real SP adjustment. The only + operations of interest performed is "pushl %ecx", followed by + ecx clobbering. */ + else if (SIG_ALLOCA) + { + /* Only one push between entry in _alloca and the probe trap. */ + long new_cfa_ = (long) ctx_cfa_ + 4; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column(); + fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; + + /* The saved value of %ecx is at CFA - 4 */ + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = -4; + + /* and what is stored at the CFA is the return address. */ + fs->retaddr_column = 8; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = 0; + fs->signal_frame = 1; + + return _URC_NO_REASON; + } + else + return _URC_END_OF_STACK; +} + +#endif /* !__MINGW64__ */ diff --git a/libgcc/config/ia64/linux-unwind.h b/libgcc/config/ia64/linux-unwind.h new file mode 100644 index 00000000000..93f762de573 --- /dev/null +++ b/libgcc/config/ia64/linux-unwind.h @@ -0,0 +1,199 @@ +/* DWARF2 EH unwinding support for IA64 Linux. + Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. + + 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 + . */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-ia64.c for the structs. */ + +/* This works only for glibc-2.3 and later, because sigcontext is different + in glibc-2.2.4. */ + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) +#include +#include + +#define IA64_GATE_AREA_START 0xa000000000000100LL +#define IA64_GATE_AREA_END 0xa000000000030000LL + +#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state + +static _Unwind_Reason_Code +ia64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + if (context->rp >= IA64_GATE_AREA_START + && context->rp < IA64_GATE_AREA_END) + { + struct sigframe { + char scratch[16]; + unsigned long sig_number; + struct siginfo *info; + struct sigcontext *sc; + } *frame_ = (struct sigframe *)context->psp; + struct sigcontext *sc = frame_->sc; + + /* Restore scratch registers in case the unwinder needs to + refer to a value stored in one of them. */ + { + int i; + + for (i = 2; i < 4; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 8; i < 12; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 14; i < 32; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + } + + context->fpsr_loc = &(sc->sc_ar_fpsr); + context->signal_pfs_loc = &(sc->sc_ar_pfs); + context->lc_loc = &(sc->sc_ar_lc); + context->unat_loc = &(sc->sc_ar_unat); + context->br_loc[0] = &(sc->sc_br[0]); + context->br_loc[6] = &(sc->sc_br[6]); + context->br_loc[7] = &(sc->sc_br[7]); + context->pr = sc->sc_pr; + context->psp = sc->sc_gr[12]; + context->gp = sc->sc_gr[1]; + /* Signal frame doesn't have an associated reg. stack frame + other than what we adjust for below. */ + fs -> no_reg_stack_frame = 1; + + if (sc->sc_rbs_base) + { + /* Need to switch from alternate register backing store. */ + long ndirty, loadrs = sc->sc_loadrs >> 16; + unsigned long alt_bspstore = context->bsp - loadrs; + unsigned long bspstore; + unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); + + ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, + (unsigned long *) context->bsp); + bspstore = (unsigned long) + ia64_rse_skip_regs (ar_bsp, -ndirty); + ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, + sc->sc_ar_rnat); + } + + /* Don't touch the branch registers o.t. b0, b6 and b7. + The kernel doesn't pass the preserved branch registers + in the sigcontext but leaves them intact, so there's no + need to do anything with them here. */ + { + unsigned long sof = sc->sc_cfm & 0x7f; + context->bsp = (unsigned long) + ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); + } + + /* Account for use of br.ret to resume execution of user code. */ + fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; + fs->curr.reg[UNW_REG_RP].val + = (unsigned long)&(sc->sc_ip) - context->psp; + fs->curr.reg[UNW_REG_RP].when = -1; + + fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_SPREL; + fs->curr.reg[UNW_REG_PFS].val + = (unsigned long)&(sc->sc_cfm) - context->psp; + fs ->curr.reg[UNW_REG_PFS].when = -1; + + return _URC_NO_REASON; + } + return _URC_END_OF_STACK; +} + +#define MD_HANDLE_UNWABI ia64_handle_unwabi + +#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's') +#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i') +#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's') +#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i') + +static void +ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + if (fs->unwabi == ABI_MARKER_LINUX_SIGTRAMP + || fs->unwabi == ABI_MARKER_OLD_LINUX_SIGTRAMP) + { + struct sigframe { + char scratch[16]; + unsigned long sig_number; + struct siginfo *info; + struct sigcontext *sc; + } *frame = (struct sigframe *)context->psp; + struct sigcontext *sc = frame->sc; + + /* Restore scratch registers in case the unwinder needs to + refer to a value stored in one of them. */ + { + int i; + + for (i = 2; i < 4; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 8; i < 12; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 14; i < 32; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + } + + context->signal_pfs_loc = &(sc->sc_ar_pfs); + context->lc_loc = &(sc->sc_ar_lc); + context->unat_loc = &(sc->sc_ar_unat); + context->br_loc[0] = &(sc->sc_br[0]); + context->br_loc[6] = &(sc->sc_br[6]); + context->br_loc[7] = &(sc->sc_br[7]); + context->pr = sc->sc_pr; + context->gp = sc->sc_gr[1]; + /* Signal frame doesn't have an associated reg. stack frame + other than what we adjust for below. */ + fs -> no_reg_stack_frame = 1; + + if (sc->sc_rbs_base) + { + /* Need to switch from alternate register backing store. */ + long ndirty, loadrs = sc->sc_loadrs >> 16; + unsigned long alt_bspstore = context->bsp - loadrs; + unsigned long bspstore; + unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); + + ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, + (unsigned long *) context->bsp); + bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty); + ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, + sc->sc_ar_rnat); + } + + /* Don't touch the branch registers o.t. b0, b6 and b7. + The kernel doesn't pass the preserved branch registers + in the sigcontext but leaves them intact, so there's no + need to do anything with them here. */ + { + unsigned long sof = sc->sc_cfm & 0x7f; + context->bsp = (unsigned long) + ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); + } + + /* The use of br.ret to resume execution of user code is already + accounted for in the unwind ABI. */ + } +} +#endif /* glibc-2.3 or better */ diff --git a/libgcc/config/ia64/vms-unwind.h b/libgcc/config/ia64/vms-unwind.h new file mode 100644 index 00000000000..41c76ae768c --- /dev/null +++ b/libgcc/config/ia64/vms-unwind.h @@ -0,0 +1,307 @@ +/* DWARF2 EH unwinding support for IA64 VMS. + Copyright (C) 2005-2009 Free Software Foundation, Inc. + + 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 + . */ + +#include +#include +#include + +#define __int64 long long +#include + +#include +#include + +#define DYN$C_SSENTRY 66 +/* ??? would rather get the proper header file. */ + +#define MD_FALLBACK_FRAME_STATE_FOR ia64_vms_fallback_frame_state + +extern INVO_CONTEXT_BLK * LIB$I64_CREATE_INVO_CONTEXT (void); + +extern int LIB$I64_IS_EXC_DISPATCH_FRAME (void *); +extern int LIB$I64_IS_AST_DISPATCH_FRAME (void *); + +extern int LIB$I64_INIT_INVO_CONTEXT (INVO_CONTEXT_BLK *, int, int); +extern int LIB$I64_GET_CURR_INVO_CONTEXT (INVO_CONTEXT_BLK *); +extern int LIB$I64_GET_PREV_INVO_CONTEXT (INVO_CONTEXT_BLK *); + +typedef unsigned long ulong; +typedef unsigned int uint; +typedef unsigned long uw_reg; +typedef uw_reg * uw_loc; + +typedef char fp_reg[16]; + +#define DENOTES_VMS_DISPATCHER_FRAME(icb) \ +(LIB$I64_IS_EXC_DISPATCH_FRAME (&(icb)->libicb$ih_pc)) + +#define DENOTES_BOTTOM_OF_STACK(icb) ((icb)->libicb$v_bottom_of_stack) + +#define FAIL_IF(COND) \ + do { if (COND) { context->rp = 0; return _URC_END_OF_STACK; } } while (0) +/* Clearing context->rp is required to prevent the ia64 gcc unwinder from + attempting to keep on walking the call chain. */ + +static int +ia64_vms_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + int i, status; + + INVO_CONTEXT_BLK local_icb; + INVO_CONTEXT_BLK *icb = &local_icb; + + CHFCTX * chfctx; + CHF$MECH_ARRAY * chfmech; + CHF64$SIGNAL_ARRAY *chfsig64; + INTSTK * intstk; + + static int eh_debug = -1; + int try_bs_copy = 0; + /* Non zero to attempt copy of alternate backing store contents for + dirty partition in interrupted context. ??? Alpha code, only activated + on specific request via specific bit in EH_DEBUG. */ + + if (eh_debug == -1) + { + char * EH_DEBUG = getenv ("EH_DEBUG"); + const uint try_bs_copy_mask = (1 << 16); + + eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0; + + /* Fetch and clear the try_bs_copy bit. */ + try_bs_copy = (uint)eh_debug & try_bs_copy_mask; + eh_debug &= ~try_bs_copy_mask; + } + + /* We're called to attempt unwinding through a frame for which no unwind + info is available, typical of an operating system exception dispatcher + frame. The code below knows how to handle this case, and only this one, + returning a failure code if it finds it is not in this situation. + + Note that we're called from deep down in the exception propagation call + chain, possibly below an exception dispatcher but for a frame above it + like some os entry point. */ + + if (eh_debug) + printf ("FALLBACK - ctxt->rp=0x%lx, sp=0x%lx, psp=0x%lx, bsp=0x%lx\n", + context->rp, context->sp, context->psp, context->bsp); + + /* Step 0 : + ------------------------------------------------------------------------- + VMS-unwind up until we reach a VMS dispatcher frame corresponding to the + context we are trying to unwind through. Fail if get past this context or + if we reach the bottom of stack along the way. + ------------------------------------------------------------------------- + */ + + status = LIB$I64_INIT_INVO_CONTEXT (icb, LIBICB$K_INVO_CONTEXT_VERSION, 0); + FAIL_IF (status == 0); + + status = LIB$I64_GET_CURR_INVO_CONTEXT (icb); + + /* Beware: we might be unwinding through nested condition handlers, so the + dispatcher frame we seek might not be the first one on the way up. Loop + thus. */ + do { + + /* Seek the next dispatcher frame up the "current" point. Stop if we + either get past the target context or hit the bottom-of-stack along + the way. */ + status = LIB$I64_GET_PREV_INVO_CONTEXT (icb); + FAIL_IF (status == 0); + FAIL_IF ((uw_reg)icb->libicb$ih_sp > (uw_reg)context->psp + || DENOTES_BOTTOM_OF_STACK (icb)); + + if (eh_debug) + printf ("frame%s sp @ 0x%llx, pc @ 0x%llx bsp=0x%llx\n", + DENOTES_VMS_DISPATCHER_FRAME (icb) ? " (dispatcher)" : "", + icb->libicb$ih_sp, icb->libicb$ih_pc, icb->libicb$ih_bsp); + + /* Continue until the target frame is found. */ + } while ((uw_reg)icb->libicb$ih_bsp != (uw_reg)context->bsp); + + /* If this is not a dispatcher frame, this is certainly a frame for a leaf + subprogram. Use default unwind information. */ + if (! DENOTES_VMS_DISPATCHER_FRAME (icb)) + return _URC_END_OF_STACK; + + /* At this point, we know we are really trying to unwind past an exception + dispatcher frame, and have it described in ICB. Proceed. */ + + /* Step 1 : + ------------------------------------------------------------------------ + We have the VMS dispatcher frame ICB handy and know we are trying to + unwind past it. Fetch pointers to useful datastructures from there, then + unwind one step further up to the interrupted user context from which + some required values will be easily accessible. + ------------------------------------------------------------------------ + */ + + chfctx = icb->libicb$ph_chfctx_addr; + FAIL_IF (chfctx == 0); + + chfmech = (CHF$MECH_ARRAY *)chfctx->chfctx$q_mcharglst; + FAIL_IF (chfmech == 0); + + chfsig64 = (CHF64$SIGNAL_ARRAY *)chfmech->chf$ph_mch_sig64_addr; + FAIL_IF (chfsig64 == 0); + + intstk = (INTSTK *)chfmech->chf$q_mch_esf_addr; + FAIL_IF (intstk == 0 || intstk->intstk$b_subtype == DYN$C_SSENTRY); + + status = LIB$I64_GET_PREV_INVO_CONTEXT (icb); + FAIL_IF (status == 0); + + if (eh_debug) + printf ("User frame, " + "chfmech @ 0x%lx, chfsig64 @ 0x%lx, intstk @ 0x%lx\n", + (ulong)chfmech, (ulong)chfsig64, (ulong)intstk); + + /* Step 2 : + ------------------------------------------------------------------------ + Point the GCC context locations/values required for further unwinding at + their corresponding locations/values in the datastructures at hand. + ------------------------------------------------------------------------ + */ + + /* Static General Register locations, including scratch registers in case + the unwinder needs to refer to a value stored in one of them. */ + { + uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_regbase; + + for (i = 2; i <= 3; i++) + context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; + for (i = 8; i <= 11; i++) + context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; + for (i = 14; i <= 31; i++) + context->ireg[i - 2].loc = (uw_loc)&ctxregs[i]; + } + + /* Static Floating Point Register locations, as available from the + mechargs array, which happens to include all the to be preserved + ones + others. */ + { + fp_reg * ctxregs; + + ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf2; + for (i = 2; i <= 5 ; i++) + context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 2]; + + ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf12; + for (i = 12; i <= 31 ; i++) + context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 12]; + } + + /* Relevant application register locations. */ + + context->fpsr_loc = (uw_loc)&intstk->intstk$q_fpsr; + context->lc_loc = (uw_loc)&intstk->intstk$q_lc; + context->unat_loc = (uw_loc)&intstk->intstk$q_unat; + + /* Branch register locations. */ + + { + uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_b0; + + for (i = 0; i < 8; i++) + context->br_loc[i] = (uw_loc)&ctxregs[i]; + } + + /* Necessary register values. */ + + /* ??? Still unclear if we need to account for possible flushes to an + alternate backing store (maybe the unwinding performed above did the + trick already) and how this would be handled. Blind alpha tentative + below for experimentation purposes in malfunctioning cases. */ + { + ulong q_bsp = (ulong) intstk->intstk$q_bsp; + ulong q_bspstore = (ulong) intstk->intstk$q_bspstore; + ulong q_bspbase = (ulong) intstk->intstk$q_bspbase; + ulong ih_bspbase = (ulong) icb->libicb$ih_bspbase; + + if (eh_debug) + printf ("q_bspstore = 0x%lx, q_bsp = 0x%lx, q_bspbase = 0x%lx\n" + "ih_bspbase = 0x%lx\n", + q_bspstore, q_bsp, q_bspbase, ih_bspbase); + + /* We witness many situations where q_bspbase is set while ih_bspbase is + null, and every attempt made with q_bspbase badly failed while doing + nothing resulted in proper behavior. */ + if (q_bspstore < q_bsp && ih_bspbase && try_bs_copy) + { + ulong dirty_size = q_bsp - q_bspstore; + ulong q_rnat = (ulong) intstk->intstk$q_rnat; + + if (eh_debug) + printf ("Attempting an alternate backing store copy ...\n"); + + ia64_copy_rbs + (context, q_bspstore, ih_bspbase, dirty_size, q_rnat); + /* Not clear if these are the proper arguments here. This is what + looked the closest to what is performed in the Linux case. */ + } + + } + + context->bsp = (uw_reg)intstk->intstk$q_bsp; + fs->no_reg_stack_frame = 1; + + context->pr = (uw_reg)intstk->intstk$q_preds; + context->gp = (uw_reg)intstk->intstk$q_gp; + + /* We're directly setting up the "context" for a VMS exception handler. + The "previous SP" for it is the SP upon the handler's entry, that is + the SP at the condition/interruption/exception point. */ + context->psp = (uw_reg)icb->libicb$ih_sp; + + /* Previous Frame State location. What eventually ends up in pfs_loc is + installed with ar.pfs = pfs_loc; br.ret; so setup to target intstk->q_ifs + to have the interrupted context restored and not that of its caller if + we happen to have a handler in the interrupted context itself. */ + fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_PSPREL; + fs->curr.reg[UNW_REG_PFS].val + = (uw_reg)&intstk->intstk$q_ifs - (uw_reg)context->psp; + fs->curr.reg[UNW_REG_PFS].when = -1; + + /* If we need to unwind further up, past the interrupted context, we need to + hand out the interrupted context's pfs, still. */ + context->signal_pfs_loc = (uw_loc) &intstk->intstk$q_pfs; + + /* Finally, rules for RP . */ + { + uw_reg * post_sigarray + = (uw_reg *)chfsig64 + 1 + chfsig64->chf64$l_sig_args; + + uw_reg * ih_pc_loc = post_sigarray - 2; + + fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_PSPREL; + fs->curr.reg[UNW_REG_RP].val + = (uw_reg)ih_pc_loc - (uw_reg)context->psp; + fs->curr.reg[UNW_REG_RP].when = -1; + } + + return _URC_NO_REASON; +} + diff --git a/libgcc/config/m68k/linux-unwind.h b/libgcc/config/m68k/linux-unwind.h new file mode 100644 index 00000000000..053c15558ca --- /dev/null +++ b/libgcc/config/m68k/linux-unwind.h @@ -0,0 +1,158 @@ +/* DWARF2 EH unwinding support for Linux/m68k. + Copyright (C) 2006, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + Don't use this at all if inhibit_libc is used. */ + +#ifndef inhibit_libc + +#include + +/* is unfortunately broken right now. */ +struct uw_ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + unsigned long uc_filler[80]; + __sigset_t uc_sigmask; +}; + +#define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state + +#ifdef __mcoldfire__ +#define M68K_FP_SIZE 8 +#else +#define M68K_FP_SIZE 12 +#endif + +static _Unwind_Reason_Code +m68k_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned short *pc = context->ra; + long cfa; + + /* moveq #__NR_sigreturn,%d0; trap #0 */ + if (pc[0] == 0x7077 && pc[1] == 0x4e40) + { + struct sigcontext *sc; + + /* Context is passed as the 3rd argument. */ + sc = *(struct sigcontext **) (context->cfa + 8); + + cfa = sc->sc_usp; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = cfa - (long) context->cfa; + + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long) &sc->sc_d0 - cfa; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (long) &sc->sc_d1 - cfa; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (long) &sc->sc_a0 - cfa; + fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.reg[9].loc.offset = (long) &sc->sc_a1 - cfa; + +#ifdef __uClinux__ + fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.reg[13].loc.offset = (long) &sc->sc_a5 - cfa; +#endif + + fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.reg[24].loc.offset = (long) &sc->sc_pc - cfa; + +#ifndef __uClinux__ + if (*(int *) sc->sc_fpstate) + { + int *fpregs = (int *) sc->sc_fpregs; + + fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.reg[16].loc.offset = (long) &fpregs[0] - cfa; + fs->regs.reg[17].how = REG_SAVED_OFFSET; + fs->regs.reg[17].loc.offset = (long) &fpregs[M68K_FP_SIZE/4] - cfa; + } +#elif defined __mcffpu__ +# error Implement this when uClinux kernel is ported to an FPU architecture +#endif + } +#ifdef __mcoldfire__ + /* move.l #__NR_rt_sigreturn,%d0; trap #0 */ + else if (pc[0] == 0x203c && pc[1] == 0x0000 && + pc[2] == 0x00ad && pc[3] == 0x4e40) +#else + /* moveq #~__NR_rt_sigreturn,%d0; not.b %d0; trap #0 */ + else if (pc[0] == 0x7052 && pc[1] == 0x4600 && pc[2] == 0x4e40) +#endif + { + struct uw_ucontext *uc; + greg_t *gregs; + int i; + + /* Context is passed as the 3rd argument. */ + uc = *(struct uw_ucontext **) (context->cfa + 8); + + gregs = uc->uc_mcontext.gregs; + cfa = gregs[15]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = cfa - (long) context->cfa; + + /* register %d0-%d7/%a0-%a6 */ + for (i = 0; i <= 14; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long) &gregs[i] - cfa; + } + + /* return address */ + fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.reg[24].loc.offset = (long) &gregs[16] - cfa; + +#define uc_fpstate uc_filler[0] + + if (uc->uc_fpstate) + { + long fpregs = (long) uc->uc_mcontext.fpregs.f_fpregs; + + /* register %fp0-%fp7 */ + for (i = 16; i <= 23; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = fpregs - cfa; + fpregs += M68K_FP_SIZE; + } + } + } + else + return _URC_END_OF_STACK; + + fs->retaddr_column = 24; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} +#endif /* ifdef inhibit_libc */ diff --git a/libgcc/config/mips/linux-unwind.h b/libgcc/config/mips/linux-unwind.h new file mode 100644 index 00000000000..02f7cd54c5a --- /dev/null +++ b/libgcc/config/mips/linux-unwind.h @@ -0,0 +1,120 @@ +/* DWARF2 EH unwinding support for MIPS Linux. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + +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 +. */ + +#ifndef inhibit_libc +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include +#include + +/* The third parameter to the signal handler points to something with + * this structure defined in asm/ucontext.h, but the name clashes with + * struct ucontext from sys/ucontext.h so this private copy is used. */ +typedef struct _sig_ucontext { + unsigned long uc_flags; + struct _sig_ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; +} _sig_ucontext_t; + +#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state + +static _Unwind_Reason_Code +mips_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + u_int32_t *pc = (u_int32_t *) context->ra; + struct sigcontext *sc; + _Unwind_Ptr new_cfa, reg_offset; + int i; + + /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ + /* 0000000c syscall */ + /* or */ + /* 24021017 li v0, 0x1017 (sigreturn) */ + /* 0000000c syscall */ + if (pc[1] != 0x0000000c) + return _URC_END_OF_STACK; +#if _MIPS_SIM == _ABIO32 + if (pc[0] == (0x24020000 | __NR_sigreturn)) + { + struct sigframe { + u_int32_t ass[4]; /* Argument save space for o32. */ + u_int32_t trampoline[2]; + struct sigcontext sigctx; + } *rt_ = context->cfa; + sc = &rt_->sigctx; + } + else +#endif + if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) + { + struct rt_sigframe { + u_int32_t ass[4]; /* Argument save space for o32. */ + u_int32_t trampoline[2]; + struct siginfo info; + _sig_ucontext_t uc; + } *rt_ = context->cfa; + sc = &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = (_Unwind_Ptr) sc; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; + + /* On o32 Linux, the register save slots in the sigcontext are + eight bytes. We need the lower half of each register slot, + so slide our view of the structure back four bytes. */ +#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__ + reg_offset = 4; +#else + reg_offset = 0; +#endif + + for (i = 0; i < 32; i++) { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (_Unwind_Ptr)&(sc->sc_regs[i]) + reg_offset - new_cfa; + } + /* "PC & -2" points to the faulting instruction, but the unwind code + searches for "(ADDR & -2) - 1". (See MASK_RETURN_ADDR for the source + of the -2 mask.) Adding 2 here ensures that "(ADDR & -2) - 1" is the + address of the second byte of the faulting instruction. + + Note that setting fs->signal_frame would not work. As the comment + above MASK_RETURN_ADDR explains, MIPS unwinders must earch for an + odd-valued address. */ + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_VAL_OFFSET; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset + = (_Unwind_Ptr)(sc->sc_pc) + 2 - new_cfa; + fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; + + return _URC_NO_REASON; +} +#endif diff --git a/libgcc/config/no-unwind.h b/libgcc/config/no-unwind.h new file mode 100644 index 00000000000..0ecd78a60de --- /dev/null +++ b/libgcc/config/no-unwind.h @@ -0,0 +1,2 @@ +/* Dummy header for targets without a definition of + MD_FALLBACK_FRAME_STATE_FOR. */ diff --git a/libgcc/config/pa/hpux-unwind.h b/libgcc/config/pa/hpux-unwind.h new file mode 100644 index 00000000000..92061ec3677 --- /dev/null +++ b/libgcc/config/pa/hpux-unwind.h @@ -0,0 +1,361 @@ +/* DWARF2 EH unwinding support for PA HP-UX. + Copyright (C) 2005, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +/* Don't use this if inhibit_libc is set. + The build for this target will fail trying to include missing headers. */ +#ifndef inhibit_libc +#include +#include +#include + +/* FIXME: We currently ignore the high halves of general, space and + control registers on PA 2.0 machines for applications using the + 32-bit runtime. We don't restore space registers or the floating + point status registers. */ + +#define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state + +/* HP-UX 10.X doesn't define GetSSReg. */ +#ifndef GetSSReg +#define GetSSReg(ssp, ss_reg) \ + ((UseWideRegs (ssp)) \ + ? (ssp)->ss_wide.ss_32.ss_reg ## _lo \ + : (ssp)->ss_narrow.ss_reg) +#endif + +#if TARGET_64BIT +#define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg)) +#else +#define GetSSRegAddr(ssp, ss_reg) \ + ((UseWideRegs (ssp)) \ + ? (long) &((ssp)->ss_wide.ss_32.ss_reg ## _lo) \ + : (long) &((ssp)->ss_narrow.ss_reg)) +#endif + +#define UPDATE_FS_FOR_SAR(FS, N) \ + (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa + +#define UPDATE_FS_FOR_GR(FS, GRN, N) \ + (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa + +#define UPDATE_FS_FOR_FR(FS, FRN, N) \ + (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa; + +#define UPDATE_FS_FOR_PC(FS, N) \ + (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa + +/* Extract bit field from word using HP's numbering (MSB = 0). */ +#define GET_FIELD(X, FROM, TO) \ + ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) + +static inline int +sign_extend (int x, int len) +{ + int signbit = (1 << (len - 1)); + int mask = (signbit << 1) - 1; + return ((x & mask) ^ signbit) - signbit; +} + +/* Extract a 17-bit signed constant from branch instructions. */ +static inline int +extract_17 (unsigned word) +{ + return sign_extend (GET_FIELD (word, 19, 28) + | GET_FIELD (word, 29, 29) << 10 + | GET_FIELD (word, 11, 15) << 11 + | (word & 0x1) << 16, 17); +} + +/* Extract a 22-bit signed constant from branch instructions. */ +static inline int +extract_22 (unsigned word) +{ + return sign_extend (GET_FIELD (word, 19, 28) + | GET_FIELD (word, 29, 29) << 10 + | GET_FIELD (word, 11, 15) << 11 + | GET_FIELD (word, 6, 10) << 16 + | (word & 0x1) << 21, 22); +} + +static _Unwind_Reason_Code +pa_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + static long cpu; + unsigned int *pc = (unsigned int *) context->ra; + + if (pc == 0) + return _URC_END_OF_STACK; + + /* Check for relocation of the return value. */ + if (!TARGET_64BIT + && *(pc + 0) == 0x2fd01224 /* fstd,ma fr4,8(sp) */ + && *(pc + 1) == 0x0fd9109d /* ldw -4(sp),ret1 */ + && *(pc + 2) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */ + pc += 3; + else if (!TARGET_64BIT + && *(pc + 0) == 0x27d01224 /* fstw,ma fr4,8(sp) */ + && *(pc + 1) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */ + pc += 2; + else if (!TARGET_64BIT + && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */ + && *(pc + 1) == 0x0fdd1299 /* stw ret1,-4(sp) */ + && *(pc + 2) == 0x2fd13024) /* fldd,mb -8(sp),fr4 */ + pc += 3; + else if (!TARGET_64BIT + && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */ + && *(pc + 1) == 0x27d13024) /* fldw,mb -8(sp),fr4 */ + pc += 2; + + /* Check if the return address points to an export stub (PA 1.1 or 2.0). */ + if ((!TARGET_64BIT + && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */ + && *(pc + 1) == 0x004010a1 /* ldsid (rp),r1 */ + && *(pc + 2) == 0x00011820 /* mtsp r1,sr0 */ + && *(pc + 3) == 0xe0400002) /* be,n 0(sr0,rp) */ + || + (!TARGET_64BIT + && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */ + && *(pc + 1) == 0xe840d002)) /* bve,n (rp) */ + { + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 30; + fs->regs.cfa_offset = 0; + + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = -24; + + /* Update context to describe the stub frame. */ + uw_update_context (context, fs); + + /* Set up fs to describe the FDE for the caller of this stub. */ + return uw_frame_state_for (context, fs); + } + /* Check if the return address points to a relocation stub. */ + else if (!TARGET_64BIT + && *(pc + 0) == 0x0fd11082 /* ldw -8(sp),rp */ + && (*(pc + 1) == 0xe840c002 /* bv,n r0(rp) */ + || *(pc + 1) == 0xe840d002)) /* bve,n (rp) */ + { + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 30; + fs->regs.cfa_offset = 0; + + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = -8; + + /* Update context to describe the stub frame. */ + uw_update_context (context, fs); + + /* Set up fs to describe the FDE for the caller of this stub. */ + return uw_frame_state_for (context, fs); + } + + /* Check if the return address is an export stub as signal handlers + may return via an export stub. */ + if (!TARGET_64BIT + && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */ + && *(pc + 1) == 0x08000240 /* nop */ + && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */ + && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */ + && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */ + && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */ + /* Extract target address from PA 1.x 17-bit branch. */ + pc += extract_17 (*pc) + 2; + else if (!TARGET_64BIT + && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */ + && *(pc + 1) == 0x08000240 /* nop */ + && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */ + && *(pc + 3) == 0xe840d002) /* bve,n (rp) */ + /* Extract target address from PA 2.0 22-bit branch. */ + pc += extract_22 (*pc) + 2; + + /* Now check if the return address is one of the signal handler + returns, _sigreturn or _sigsetreturn. */ + if ((TARGET_64BIT + && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */ + && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */ + && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */ + && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */ + && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */ + || + (TARGET_64BIT + && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */ + && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */ + && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */ + && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */ + && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */ + || + (!TARGET_64BIT + && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */ + && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */ + && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */ + && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */ + && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */ + || + (!TARGET_64BIT + && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */ + && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */ + && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */ + && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */ + { + /* The previous stack pointer is saved at (long *)SP - 1. The + ucontext structure is offset from the start of the previous + frame by the siglocal_misc structure. */ + struct siglocalx *sl = (struct siglocalx *) + (*((long *) context->cfa - 1)); + mcontext_t *mc = &(sl->sl_uc.uc_mcontext); + + long new_cfa = GetSSReg (mc, ss_sp); + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 30; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + UPDATE_FS_FOR_GR (fs, 1, 1); + UPDATE_FS_FOR_GR (fs, 2, 2); + UPDATE_FS_FOR_GR (fs, 3, 3); + UPDATE_FS_FOR_GR (fs, 4, 4); + UPDATE_FS_FOR_GR (fs, 5, 5); + UPDATE_FS_FOR_GR (fs, 6, 6); + UPDATE_FS_FOR_GR (fs, 7, 7); + UPDATE_FS_FOR_GR (fs, 8, 8); + UPDATE_FS_FOR_GR (fs, 9, 9); + UPDATE_FS_FOR_GR (fs, 10, 10); + UPDATE_FS_FOR_GR (fs, 11, 11); + UPDATE_FS_FOR_GR (fs, 12, 12); + UPDATE_FS_FOR_GR (fs, 13, 13); + UPDATE_FS_FOR_GR (fs, 14, 14); + UPDATE_FS_FOR_GR (fs, 15, 15); + UPDATE_FS_FOR_GR (fs, 16, 16); + UPDATE_FS_FOR_GR (fs, 17, 17); + UPDATE_FS_FOR_GR (fs, 18, 18); + UPDATE_FS_FOR_GR (fs, 19, 19); + UPDATE_FS_FOR_GR (fs, 20, 20); + UPDATE_FS_FOR_GR (fs, 21, 21); + UPDATE_FS_FOR_GR (fs, 22, 22); + UPDATE_FS_FOR_GR (fs, 23, 23); + UPDATE_FS_FOR_GR (fs, 24, 24); + UPDATE_FS_FOR_GR (fs, 25, 25); + UPDATE_FS_FOR_GR (fs, 26, 26); + UPDATE_FS_FOR_GR (fs, 27, 27); + UPDATE_FS_FOR_GR (fs, 28, 28); + UPDATE_FS_FOR_GR (fs, 29, 29); + UPDATE_FS_FOR_GR (fs, 30, 30); + UPDATE_FS_FOR_GR (fs, 31, 31); + + if (TARGET_64BIT) + { + UPDATE_FS_FOR_FR (fs, 4, 32); + UPDATE_FS_FOR_FR (fs, 5, 33); + UPDATE_FS_FOR_FR (fs, 6, 34); + UPDATE_FS_FOR_FR (fs, 7, 35); + UPDATE_FS_FOR_FR (fs, 8, 36); + UPDATE_FS_FOR_FR (fs, 9, 37); + UPDATE_FS_FOR_FR (fs, 10, 38); + UPDATE_FS_FOR_FR (fs, 11, 39); + UPDATE_FS_FOR_FR (fs, 12, 40); + UPDATE_FS_FOR_FR (fs, 13, 41); + UPDATE_FS_FOR_FR (fs, 14, 42); + UPDATE_FS_FOR_FR (fs, 15, 43); + UPDATE_FS_FOR_FR (fs, 16, 44); + UPDATE_FS_FOR_FR (fs, 17, 45); + UPDATE_FS_FOR_FR (fs, 18, 46); + UPDATE_FS_FOR_FR (fs, 19, 47); + UPDATE_FS_FOR_FR (fs, 20, 48); + UPDATE_FS_FOR_FR (fs, 21, 49); + UPDATE_FS_FOR_FR (fs, 22, 50); + UPDATE_FS_FOR_FR (fs, 23, 51); + UPDATE_FS_FOR_FR (fs, 24, 52); + UPDATE_FS_FOR_FR (fs, 25, 53); + UPDATE_FS_FOR_FR (fs, 26, 54); + UPDATE_FS_FOR_FR (fs, 27, 55); + UPDATE_FS_FOR_FR (fs, 28, 56); + UPDATE_FS_FOR_FR (fs, 29, 57); + UPDATE_FS_FOR_FR (fs, 30, 58); + UPDATE_FS_FOR_FR (fs, 31, 59); + + UPDATE_FS_FOR_SAR (fs, 60); + } + else + { + UPDATE_FS_FOR_FR (fs, 4, 32); + UPDATE_FS_FOR_FR (fs, 5, 34); + UPDATE_FS_FOR_FR (fs, 6, 36); + UPDATE_FS_FOR_FR (fs, 7, 38); + UPDATE_FS_FOR_FR (fs, 8, 40); + UPDATE_FS_FOR_FR (fs, 9, 44); + UPDATE_FS_FOR_FR (fs, 10, 44); + UPDATE_FS_FOR_FR (fs, 11, 46); + UPDATE_FS_FOR_FR (fs, 12, 48); + UPDATE_FS_FOR_FR (fs, 13, 50); + UPDATE_FS_FOR_FR (fs, 14, 52); + UPDATE_FS_FOR_FR (fs, 15, 54); + + if (!cpu) + cpu = sysconf (_SC_CPU_VERSION); + + /* PA-RISC 1.0 only has 16 floating point registers. */ + if (cpu != CPU_PA_RISC1_0) + { + UPDATE_FS_FOR_FR (fs, 16, 56); + UPDATE_FS_FOR_FR (fs, 17, 58); + UPDATE_FS_FOR_FR (fs, 18, 60); + UPDATE_FS_FOR_FR (fs, 19, 62); + UPDATE_FS_FOR_FR (fs, 20, 64); + UPDATE_FS_FOR_FR (fs, 21, 66); + UPDATE_FS_FOR_FR (fs, 22, 68); + UPDATE_FS_FOR_FR (fs, 23, 70); + UPDATE_FS_FOR_FR (fs, 24, 72); + UPDATE_FS_FOR_FR (fs, 25, 74); + UPDATE_FS_FOR_FR (fs, 26, 76); + UPDATE_FS_FOR_FR (fs, 27, 78); + UPDATE_FS_FOR_FR (fs, 28, 80); + UPDATE_FS_FOR_FR (fs, 29, 82); + UPDATE_FS_FOR_FR (fs, 30, 84); + UPDATE_FS_FOR_FR (fs, 31, 86); + } + + UPDATE_FS_FOR_SAR (fs, 88); + } + + fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; + UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN); + fs->signal_frame = 1; + + return _URC_NO_REASON; + } + + return _URC_END_OF_STACK; +} +#endif /* inhibit_libc */ diff --git a/libgcc/config/pa/linux-unwind.h b/libgcc/config/pa/linux-unwind.h new file mode 100644 index 00000000000..a0560e97445 --- /dev/null +++ b/libgcc/config/pa/linux-unwind.h @@ -0,0 +1,141 @@ +/* DWARF2 EH unwinding support for PA Linux. + Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. + +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 +. */ + + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +/* Don't use this if inhibit_libc is set. + The build for this target will fail trying to include missing headers. */ +#ifndef inhibit_libc +#include +#include + +/* Unfortunately, because of various bugs and changes to the kernel, + we have several cases to deal with. + + In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should + point directly at the beginning of the trampoline and struct rt_sigframe. + + In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and + (CONTEXT)->ra points at the 4th word in the trampoline structure. This + is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4. + + To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes + to get the beginning of the signal frame, and then check offsets 0, 4 + and 5 to see if we found the beginning of the trampoline. This will + tell us how to locate the sigcontext structure. + + Note that with a 2.4 64-bit kernel, the signal context is not properly + passed back to userspace so the unwind will not work correctly. */ + +#define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state + +static _Unwind_Reason_Code +pa32_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned long sp = (unsigned long)context->ra & ~63; + unsigned int *pc = (unsigned int *)sp; + unsigned long off; + _Unwind_Ptr new_cfa; + int i; + struct sigcontext *sc; + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *frame; + + /* rt_sigreturn trampoline: + 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) + 3414015a ldi __NR_rt_sigreturn, %r20 + e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 + 08000240 nop */ + + if (pc[0] == 0x34190000 || pc[0] == 0x34190002) + off = 4*4; + else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) + { + pc += 4; + off = 10 * 4; + } + else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) + { + pc += 5; + off = 10 * 4; + } + else + { + /* We may have to unwind through an alternate signal stack. + We assume that the alignment of the alternate signal stack + is BIGGEST_ALIGNMENT (i.e., that it has been allocated using + malloc). As a result, we can't distinguish trampolines + used prior to 2.6.5-rc2-pa4. However after 2.6.5-rc2-pa4, + the return address of a signal trampoline will be on an odd + word boundary and we can then determine the frame offset. */ + sp = (unsigned long)context->ra; + pc = (unsigned int *)sp; + if ((pc[0] == 0x34190000 || pc[0] == 0x34190002) && (sp & 4)) + off = 5 * 4; + else + return _URC_END_OF_STACK; + } + + if (pc[1] != 0x3414015a + || pc[2] != 0xe4008200 + || pc[3] != 0x08000240) + return _URC_END_OF_STACK; + + frame = (struct rt_sigframe *)(sp + off); + sc = &frame->uc.uc_mcontext; + + new_cfa = sc->sc_gr[30]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 30; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + for (i = 1; i <= 31; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa; + } + for (i = 4; i <= 31; i++) + { + /* FP regs have left and right halves */ + fs->regs.reg[2*i+24].how = REG_SAVED_OFFSET; + fs->regs.reg[2*i+24].loc.offset + = (long)&sc->sc_fr[i] - new_cfa; + fs->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET; + fs->regs.reg[2*i+24+1].loc.offset + = (long)&sc->sc_fr[i] + 4 - new_cfa; + } + fs->regs.reg[88].how = REG_SAVED_OFFSET; + fs->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset + = (long) &sc->sc_iaoq[0] - new_cfa; + fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; + fs->signal_frame = 1; + return _URC_NO_REASON; +} +#endif /* inhibit_libc */ diff --git a/libgcc/config/rs6000/darwin-unwind.h b/libgcc/config/rs6000/darwin-unwind.h new file mode 100644 index 00000000000..8a4fbd55ac1 --- /dev/null +++ b/libgcc/config/rs6000/darwin-unwind.h @@ -0,0 +1,34 @@ +/* DWARF2 EH unwinding support for 32-bit PowerPC Darwin. + Copyright (C) 2004, 2009, 2011 Free Software Foundation, Inc. + + 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 + . */ + +#ifndef __LP64__ + +extern bool _Unwind_fallback_frame_state_for + (struct _Unwind_Context *context, _Unwind_FrameState *fs); + +#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS) \ + (_Unwind_fallback_frame_state_for (CONTEXT, FS) \ + ? _URC_NO_REASON : _URC_END_OF_STACK) + +#endif diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h new file mode 100644 index 00000000000..a16df97e97e --- /dev/null +++ b/libgcc/config/rs6000/linux-unwind.h @@ -0,0 +1,355 @@ +/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + 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 + . */ + +#define R_LR 65 +#define R_CR2 70 +#define R_VR0 77 +#define R_VRSAVE 109 +#define R_VSCR 110 + +struct gcc_vregs +{ + __attribute__ ((vector_size (16))) int vr[32]; +#ifdef __powerpc64__ + unsigned int pad1[3]; + unsigned int vscr; + unsigned int vsave; + unsigned int pad2[3]; +#else + unsigned int vsave; + unsigned int pad[2]; + unsigned int vscr; +#endif +}; + +struct gcc_regs +{ + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; + unsigned long softe; + unsigned long trap; + unsigned long dar; + unsigned long dsisr; + unsigned long result; + unsigned long pad1[4]; + double fpr[32]; + unsigned int pad2; + unsigned int fpscr; +#ifdef __powerpc64__ + struct gcc_vregs *vp; +#else + unsigned int pad3[2]; +#endif + struct gcc_vregs vregs; +}; + +struct gcc_ucontext +{ +#ifdef __powerpc64__ + unsigned long pad[28]; +#else + unsigned long pad[12]; +#endif + struct gcc_regs *regs; + struct gcc_regs rsave; +}; + +#ifdef __powerpc64__ + +enum { SIGNAL_FRAMESIZE = 128 }; + +/* If PC is at a sigreturn trampoline, return a pointer to the + regs. Otherwise return NULL. */ + +static struct gcc_regs * +get_regs (struct _Unwind_Context *context) +{ + const unsigned int *pc = context->ra; + + /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ + /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ + if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002) + return NULL; + if (pc[1] == 0x38000077) + { + struct sigframe { + char gap[SIGNAL_FRAMESIZE]; + unsigned long pad[7]; + struct gcc_regs *regs; + } *frame = (struct sigframe *) context->cfa; + return frame->regs; + } + else if (pc[1] == 0x380000AC) + { + /* This works for 2.4 kernels, but not for 2.6 kernels with vdso + because pc isn't pointing into the stack. Can be removed when + no one is running 2.4.19 or 2.4.20, the first two ppc64 + kernels released. */ + const struct rt_sigframe_24 { + int tramp[6]; + void *pinfo; + struct gcc_ucontext *puc; + } *frame24 = (const struct rt_sigframe_24 *) context->ra; + + /* Test for magic value in *puc of vdso. */ + if ((long) frame24->puc != -21 * 8) + return frame24->puc->regs; + else + { + /* This works for 2.4.21 and later kernels. */ + struct rt_sigframe { + char gap[SIGNAL_FRAMESIZE]; + struct gcc_ucontext uc; + unsigned long pad[2]; + int tramp[6]; + void *pinfo; + struct gcc_ucontext *puc; + } *frame = (struct rt_sigframe *) context->cfa; + return frame->uc.regs; + } + } + return NULL; +} + +#else /* !__powerpc64__ */ + +enum { SIGNAL_FRAMESIZE = 64 }; + +static struct gcc_regs * +get_regs (struct _Unwind_Context *context) +{ + const unsigned int *pc = context->ra; + + /* li r0, 0x7777; sc (sigreturn old) */ + /* li r0, 0x0077; sc (sigreturn new) */ + /* li r0, 0x6666; sc (rt_sigreturn old) */ + /* li r0, 0x00AC; sc (rt_sigreturn new) */ + if (pc[1] != 0x44000002) + return NULL; + if (pc[0] == 0x38007777 || pc[0] == 0x38000077) + { + struct sigframe { + char gap[SIGNAL_FRAMESIZE]; + unsigned long pad[7]; + struct gcc_regs *regs; + } *frame = (struct sigframe *) context->cfa; + return frame->regs; + } + else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC) + { + struct rt_sigframe { + char gap[SIGNAL_FRAMESIZE + 16]; + char siginfo[128]; + struct gcc_ucontext uc; + } *frame = (struct rt_sigframe *) context->cfa; + return frame->uc.regs; + } + return NULL; +} +#endif + +/* Find an entry in the process auxiliary vector. The canonical way to + test for VMX is to look at AT_HWCAP. */ + +static long +ppc_linux_aux_vector (long which) +{ + /* __libc_stack_end holds the original stack passed to a process. */ + extern long *__libc_stack_end; + long argc; + char **argv; + char **envp; + struct auxv + { + long a_type; + long a_val; + } *auxp; + + /* The Linux kernel puts argc first on the stack. */ + argc = __libc_stack_end[0]; + /* Followed by argv, NULL terminated. */ + argv = (char **) __libc_stack_end + 1; + /* Followed by environment string pointers, NULL terminated. */ + envp = argv + argc + 1; + while (*envp++) + continue; + /* Followed by the aux vector, zero terminated. */ + for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp) + if (auxp->a_type == which) + return auxp->a_val; + return 0; +} + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state + +static _Unwind_Reason_Code +ppc_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + static long hwcap = 0; + struct gcc_regs *regs = get_regs (context); + long new_cfa; + int i; + + if (regs == NULL) + return _URC_END_OF_STACK; + + new_cfa = regs->gpr[STACK_POINTER_REGNUM]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 32; i++) + if (i != STACK_POINTER_REGNUM) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; + } + + fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET; + /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit + libgcc loc.offset needs to point to the low 32 bits of regs->ccr. */ + fs->regs.reg[R_CR2].loc.offset = (long) ®s->ccr - new_cfa + + sizeof (long) - 4; + + fs->regs.reg[R_LR].how = REG_SAVED_OFFSET; + fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa; + + fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; + fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; + fs->retaddr_column = ARG_POINTER_REGNUM; + fs->signal_frame = 1; + + if (hwcap == 0) + { + hwcap = ppc_linux_aux_vector (16); + /* These will already be set if we found AT_HWCAP. A nonzero + value stops us looking again if for some reason we couldn't + find AT_HWCAP. */ +#ifdef __powerpc64__ + hwcap |= 0xc0000000; +#else + hwcap |= 0x80000000; +#endif + } + + /* If we have a FPU... */ + if (hwcap & 0x08000000) + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; + } + + /* If we have a VMX unit... */ + if (hwcap & 0x10000000) + { + struct gcc_vregs *vregs; +#ifdef __powerpc64__ + vregs = regs->vp; +#else + vregs = ®s->vregs; +#endif + if (regs->msr & (1 << 25)) + { + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET; + fs->regs.reg[i + R_VR0].loc.offset + = (long) &vregs->vr[i] - new_cfa; + } + + fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET; + fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa; + } + + fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET; + fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa; + } + + /* If we have SPE register high-parts... we check at compile-time to + avoid expanding the code for all other PowerPC. */ +#ifdef __SPE__ + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET; + fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset + = (long) ®s->vregs - new_cfa + 4 * i; + } +#endif + + return _URC_NO_REASON; +} + +#define MD_FROB_UPDATE_CONTEXT frob_update_context + +static void +frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED) +{ + const unsigned int *pc = (const unsigned int *) context->ra; + + /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't + have S flag in it. */ +#ifdef __powerpc64__ + /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ + /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ + if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE + && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) + && pc[2] == 0x44000002) + _Unwind_SetSignalFrame (context, 1); +#else + /* li r0, 0x7777; sc (sigreturn old) */ + /* li r0, 0x0077; sc (sigreturn new) */ + /* li r0, 0x6666; sc (rt_sigreturn old) */ + /* li r0, 0x00AC; sc (rt_sigreturn new) */ + if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 + || pc[0] == 0x38006666 || pc[0] == 0x380000AC) + && pc[1] == 0x44000002) + _Unwind_SetSignalFrame (context, 1); +#endif + +#ifdef __powerpc64__ + if (fs->regs.reg[2].how == REG_UNSAVED) + { + /* If the current unwind info (FS) does not contain explicit info + saving R2, then we have to do a minor amount of code reading to + figure out if it was saved. The big problem here is that the + code that does the save/restore is generated by the linker, so + we have no good way to determine at compile time what to do. */ + unsigned int *insn + = (unsigned int *) _Unwind_GetGR (context, R_LR); + if (insn && *insn == 0xE8410028) + _Unwind_SetGRPtr (context, 2, context->cfa + 40); + } +#endif +} diff --git a/libgcc/config/s390/linux-unwind.h b/libgcc/config/s390/linux-unwind.h new file mode 100644 index 00000000000..558087fad94 --- /dev/null +++ b/libgcc/config/s390/linux-unwind.h @@ -0,0 +1,130 @@ +/* DWARF2 EH unwinding support for S/390 Linux. + Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#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 char *pc = context->ra; + long new_cfa; + int i; + + typedef struct + { + unsigned long psw_mask; + unsigned long psw_addr; + unsigned long gprs[16]; + unsigned int acrs[16]; + unsigned int fpc; + unsigned int __pad; + double fprs[16]; + } __attribute__ ((__aligned__ (8))) sigregs_; + + sigregs_ *regs; + int *signo; + + /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ + if (pc[0] != 0x0a || (pc[1] != 119 && pc[1] != 173)) + return _URC_END_OF_STACK; + + /* Legacy frames: + old signal mask (8 bytes) + pointer to sigregs (8 bytes) - points always to next location + sigregs + retcode + This frame layout was used on kernels < 2.6.9 for non-RT frames, + and on kernels < 2.4.13 for RT frames as well. Note that we need + to look at RA to detect this layout -- this means that if you use + sa_restorer to install a different signal restorer on a legacy + kernel, unwinding from signal frames will not work. */ + if (context->ra == context->cfa + 16 + sizeof (sigregs_)) + { + regs = (sigregs_ *)(context->cfa + 16); + signo = NULL; + } + + /* New-style RT frame: + retcode + alignment (8 bytes) + siginfo (128 bytes) + ucontext (contains sigregs) */ + else if (pc[1] == 173 /* __NR_rt_sigreturn */) + { + struct ucontext_ + { + unsigned long uc_flags; + struct ucontext_ *uc_link; + unsigned long uc_stack[3]; + sigregs_ uc_mcontext; + } *uc = context->cfa + 8 + 128; + + regs = &uc->uc_mcontext; + signo = context->cfa + sizeof(long); + } + + /* New-style non-RT frame: + old signal mask (8 bytes) + pointer to sigregs (followed by signal number) */ + else + { + regs = *(sigregs_ **)(context->cfa + 8); + signo = (int *)(regs + 1); + } + + new_cfa = regs->gprs[15] + 16*sizeof(long) + 32; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = + new_cfa - (long) context->cfa + 16*sizeof(long) + 32; + + for (i = 0; i < 16; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = + (long)®s->gprs[i] - new_cfa; + } + for (i = 0; i < 16; i++) + { + fs->regs.reg[16+i].how = REG_SAVED_OFFSET; + fs->regs.reg[16+i].loc.offset = + (long)®s->fprs[i] - new_cfa; + } + + /* Load return addr from PSW into dummy register 32. */ + + fs->regs.reg[32].how = REG_SAVED_OFFSET; + fs->regs.reg[32].loc.offset = (long)®s->psw_addr - new_cfa; + fs->retaddr_column = 32; + /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr + after the faulting instruction rather than before it. + Don't set FS->signal_frame in that case. */ + if (!signo || (*signo != 4 && *signo != 5 && *signo != 8)) + fs->signal_frame = 1; + + return _URC_NO_REASON; +} diff --git a/libgcc/config/s390/tpf-unwind.h b/libgcc/config/s390/tpf-unwind.h new file mode 100644 index 00000000000..33fd5f5c8c5 --- /dev/null +++ b/libgcc/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 +. */ + +#include + +/* 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; +} + diff --git a/libgcc/config/sh/linux-unwind.h b/libgcc/config/sh/linux-unwind.h new file mode 100644 index 00000000000..94ed95d55e1 --- /dev/null +++ b/libgcc/config/sh/linux-unwind.h @@ -0,0 +1,255 @@ +/* DWARF2 EH unwinding support for SH Linux. + Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. + +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 +. */ + + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + Don't use this at all if inhibit_libc is used. */ + +#ifndef inhibit_libc + +#include +#include +#include "insn-constants.h" + +# if defined (__SH5__) +#define SH_DWARF_FRAME_GP0 0 +#define SH_DWARF_FRAME_FP0 77 +#define SH_DWARF_FRAME_BT0 68 +#define SH_DWARF_FRAME_PR_MEDIA 18 +#define SH_DWARF_FRAME_SR 65 +#define SH_DWARF_FRAME_FPSCR 76 +#else +#define SH_DWARF_FRAME_GP0 0 +#define SH_DWARF_FRAME_FP0 25 +#define SH_DWARF_FRAME_XD0 87 +#define SH_DWARF_FRAME_PR 17 +#define SH_DWARF_FRAME_GBR 18 +#define SH_DWARF_FRAME_MACH 20 +#define SH_DWARF_FRAME_MACL 21 +#define SH_DWARF_FRAME_PC 16 +#define SH_DWARF_FRAME_SR 22 +#define SH_DWARF_FRAME_FPUL 23 +#define SH_DWARF_FRAME_FPSCR 24 +#endif /* defined (__SH5__) */ + +#if defined (__SH5__) + +#define MD_FALLBACK_FRAME_STATE_FOR shmedia_fallback_frame_state + +static _Unwind_Reason_Code +shmedia_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + int i, r; + + /* movi 0x10,r9; shori 0x77,r9; trapa r9; nop (sigreturn) */ + /* movi 0x10,r9; shori 0xad,r9; trapa r9; nop (rt_sigreturn) */ + if ((*(unsigned long *) (pc-1) == 0xcc004090) + && (*(unsigned long *) (pc+3) == 0xc801dc90) + && (*(unsigned long *) (pc+7) == 0x6c91fff0) + && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) + sc = context->cfa; + else if ((*(unsigned long *) (pc-1) == 0xcc004090) + && (*(unsigned long *) (pc+3) == 0xc802b490) + && (*(unsigned long *) (pc+7) == 0x6c91fff0) + && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) + { + struct rt_sigframe { + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + /* The void * cast is necessary to avoid an aliasing warning. + The aliasing warning is correct, but should not be a problem + because it does not alias anything. */ + sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->sc_regs[15]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 63; i++) + { + if (i == 15) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (long)&(sc->sc_regs[i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset + = (long)&(sc->sc_sr) - new_cfa; + + r = SH_DWARF_FRAME_BT0; + for (i = 0; i < 8; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_tregs[i]) - new_cfa; + } + + r = SH_DWARF_FRAME_FP0; + for (i = 0; i < 32; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_fpregs[i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset + = (long)&(sc->sc_fpscr) - new_cfa; + + /* We use the slot for the zero register to save return address. */ + fs->regs.reg[63].how = REG_SAVED_OFFSET; + fs->regs.reg[63].loc.offset + = (long)&(sc->sc_pc) - new_cfa; + fs->retaddr_column = 63; + fs->signal_frame = 1; + return _URC_NO_REASON; +} + +#else /* defined (__SH5__) */ + +#define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state + +static _Unwind_Reason_Code +sh_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + int i; +#if defined (__SH3E__) || defined (__SH4__) + int r; +#endif + + /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77 (sigreturn) */ + /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad (rt_sigreturn) */ + /* Newer kernel uses pad instructions to avoid an SH-4 core bug. */ + /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; + or r0,r0; 1: .short 0x77 (sigreturn) */ + /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; + or r0,r0; 1: .short 0xad (rt_sigreturn) */ + if (((*(unsigned short *) (pc+0) == 0x9300) + && (*(unsigned short *) (pc+2) == 0xc310) + && (*(unsigned short *) (pc+4) == 0x0077)) + || (((*(unsigned short *) (pc+0) == 0x9305) + && (*(unsigned short *) (pc+2) == 0xc310) + && (*(unsigned short *) (pc+14) == 0x0077)))) + sc = context->cfa; + else if (((*(unsigned short *) (pc+0) == 0x9300) + && (*(unsigned short *) (pc+2) == 0xc310) + && (*(unsigned short *) (pc+4) == 0x00ad)) + || (((*(unsigned short *) (pc+0) == 0x9305) + && (*(unsigned short *) (pc+2) == 0xc310) + && (*(unsigned short *) (pc+14) == 0x00ad)))) + { + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + /* The void * cast is necessary to avoid an aliasing warning. + The aliasing warning is correct, but should not be a problem + because it does not alias anything. */ + sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->sc_regs[15]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 15; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 15; i++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (long)&(sc->sc_regs[i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset + = (long)&(sc->sc_pr) - new_cfa; + fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset + = (long)&(sc->sc_sr) - new_cfa; + fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset + = (long)&(sc->sc_gbr) - new_cfa; + fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset + = (long)&(sc->sc_mach) - new_cfa; + fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset + = (long)&(sc->sc_macl) - new_cfa; + +#if defined (__SH3E__) || defined (__SH4__) + r = SH_DWARF_FRAME_FP0; + for (i = 0; i < 16; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_fpregs[i]) - new_cfa; + } + + r = SH_DWARF_FRAME_XD0; + for (i = 0; i < 8; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_xfpregs[2*i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset + = (long)&(sc->sc_fpul) - new_cfa; + fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset + = (long)&(sc->sc_fpscr) - new_cfa; +#endif + + fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset + = (long)&(sc->sc_pc) - new_cfa; + fs->retaddr_column = SH_DWARF_FRAME_PC; + fs->signal_frame = 1; + return _URC_NO_REASON; +} +#endif /* defined (__SH5__) */ + +#endif /* inhibit_libc */ diff --git a/libgcc/config/sparc/linux-unwind.h b/libgcc/config/sparc/linux-unwind.h new file mode 100644 index 00000000000..adfef6ec29d --- /dev/null +++ b/libgcc/config/sparc/linux-unwind.h @@ -0,0 +1,202 @@ +/* DWARF2 EH unwinding support for SPARC Linux. + Copyright 2004, 2005, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#if defined(__arch64__) + +/* 64-bit SPARC version */ +#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state + +static _Unwind_Reason_Code +sparc64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + long this_cfa = (long) context->cfa; + long new_cfa, ra_location, shifted_ra_location; + long regs_off, fpu_save_off; + long fpu_save; + int i; + + if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ + || pc[1] != 0x91d0206d) /* ta 0x6d */ + return _URC_END_OF_STACK; + + regs_off = 192 + 128; + fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4); + + new_cfa = *(long *)(this_cfa + regs_off + (14 * 8)); + new_cfa += 2047; /* Stack bias */ + fpu_save = *(long *)(this_cfa + fpu_save_off); + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - this_cfa; + + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = this_cfa + regs_off + (i * 8) - new_cfa; + } + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset + = this_cfa + (i * 8) - new_cfa; + } + if (fpu_save) + { + for (i = 0; i < 64; i++) + { + if (i > 32 && (i & 0x1)) + continue; + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = fpu_save + (i * 4) - new_cfa; + } + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = this_cfa + regs_off + 17 * 8; + shifted_ra_location = this_cfa + regs_off + 19 * 8; /* Y register */ + *(long *)shifted_ra_location = *(long *)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context + +static void +sparc64_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* The column of %sp contains the old CFA, not the old value of %sp. + The CFA offset already comprises the stack bias so, when %sp is the + CFA register, we must avoid counting the stack bias twice. Do not + do that for signal frames as the offset is artificial for them. */ + if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () + && fs->regs.cfa_how == CFA_REG_OFFSET + && fs->regs.cfa_offset != 0 + && !fs->signal_frame) + context->cfa -= 2047; +} + +#else + +/* 32-bit SPARC version */ +#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state + +static _Unwind_Reason_Code +sparc_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + int this_cfa = (int) context->cfa; + int new_cfa, ra_location, shifted_ra_location; + int regs_off, fpu_save_off; + int fpu_save; + int old_style, i; + + if (pc[1] != 0x91d02010) /* ta 0x10 */ + return _URC_END_OF_STACK; + + if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ + old_style = 1; + else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ + old_style = 0; + else + return _URC_END_OF_STACK; + + if (old_style) + { + regs_off = 96; + fpu_save_off = regs_off + (4 * 4) + (16 * 4); + } + else + { + regs_off = 96 + 128; + fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4); + } + + new_cfa = *(int *)(this_cfa + regs_off + (4 * 4) + (14 * 4)); + fpu_save = *(int *)(this_cfa + fpu_save_off); + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - this_cfa; + + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = this_cfa + regs_off + (4 * 4) + (i * 4) - new_cfa; + } + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset + = this_cfa + (i * 4) - new_cfa; + } + if (fpu_save) + { + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = fpu_save + (i * 4) - new_cfa; + } + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = this_cfa + regs_off + 4; + shifted_ra_location = this_cfa + regs_off + 3 * 4; /* Y register */ + *(int *)shifted_ra_location = *(int *)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#endif diff --git a/libgcc/config/sparc/sol2-unwind.h b/libgcc/config/sparc/sol2-unwind.h new file mode 100644 index 00000000000..f8b99027247 --- /dev/null +++ b/libgcc/config/sparc/sol2-unwind.h @@ -0,0 +1,419 @@ +/* DWARF2 EH unwinding support for SPARC Solaris. + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include +#include +#include + +#if defined(__arch64__) + +#define IS_SIGHANDLER sparc64_is_sighandler + +static int +sparc64_is_sighandler (unsigned int *pc, unsigned int *savpc, int *nframes) +{ + if (/* Solaris 8 - single-threaded + ---------------------------- + : add %g5, %o7, %o2 + : ldx [ %o2 + 0xfa0 ], %g5 + : sra %i0, 0, %o0 + : sllx %o0, 3, %g4 + : ldx [ %g4 + %g5 ], %l0 + : call %l0 + : mov %i2, %o2 + : cmp %i3, 8 <--- PC */ + ( pc[-7] == 0x9401400f + && pc[-6] == 0xca5aafa0 + && pc[-5] == 0x913e2000 + && pc[-4] == 0x892a3003 + && pc[-3] == 0xe0590005 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x80a6e008) + + || /* Solaris 9 - single-threaded + ---------------------------- + The pattern changes slightly in different versions of the + operating system, so we skip the comparison against pc[-6] for + Solaris 9. + + : sra %i0, 0, %l1 + + Solaris 9 5/02: + : ldx [ %o2 + 0xf68 ], %g5 + Solaris 9 9/05: + : ldx [ %o2 + 0xe50 ], %g5 + + : sllx %l1, 3, %g4 + : mov %l1, %o0 + : ldx [ %g4 + %g5 ], %l0 + : call %l0 + : mov %i2, %o2 + : cmp %l1, 8 <--- PC */ + ( pc[-7] == 0xa33e2000 + /* skip pc[-6] */ + && pc[-5] == 0x892c7003 + && pc[-4] == 0x90100011 + && pc[-3] == 0xe0590005 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x80a46008)) + { + /* We need to move up one frame: + + <-- context->cfa + sigacthandler + + */ + *nframes = 1; + return 1; + } + + if (/* Solaris 8+ - multi-threaded + ---------------------------- + <__sighndlr>: save %sp, -176, %sp + <__sighndlr+4>: mov %i0, %o0 + <__sighndlr+8>: mov %i1, %o1 + <__sighndlr+12>: call %i3 + <__sighndlr+16>: mov %i2, %o2 + <__sighndlr+20>: ret <--- PC + <__sighndlr+24>: restore */ + pc[-5] == 0x9de3bf50 + && pc[-4] == 0x90100018 + && pc[-3] == 0x92100019 + && pc[-2] == 0x9fc6c000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x81c7e008 + && pc[ 1] == 0x81e80000) + { + if (/* Solaris 8 /usr/lib/sparcv9/libthread.so.1 + ------------------------------------------ + Before patch 108827-08: + : st %g4, [ %i1 + 0x1c ] + + Since patch 108827-08: + : st %l0, [ %i4 + 0x10 ] */ + savpc[-1] == 0xc826601c + || savpc[-1] == 0xe0272010) + { + /* We need to move up three frames: + + <-- context->cfa + __sighndlr + sigacthandler + + */ + *nframes = 2; + } + else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+ + ---------------------------------------------------------- */ + { + /* We need to move up three frames: + + <-- context->cfa + __sighndlr + call_user_handler + sigacthandler + + */ + *nframes = 3; + } + return 1; + } + + return 0; +} + +#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state + +#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context + +static void +sparc64_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* The column of %sp contains the old CFA, not the old value of %sp. + The CFA offset already comprises the stack bias so, when %sp is the + CFA register, we must avoid counting the stack bias twice. Do not + do that for signal frames as the offset is artificial for them. */ + if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () + && fs->regs.cfa_how == CFA_REG_OFFSET + && fs->regs.cfa_offset != 0 + && !fs->signal_frame) + context->cfa -= STACK_BIAS; +} + +#else + +#define IS_SIGHANDLER sparc_is_sighandler + +static int +sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) +{ + if (/* Solaris 8, 9 - single-threaded + ------------------------------- + The pattern changes slightly in different versions of the operating + system, so we skip the comparison against pc[-6]. + + : add %o1, %o7, %o3 + : mov %i1, %o1 + + : ld [ %o3 + ], %o2 + + : sll %i0, 2, %o0 + : ld [ %o0 + %o2 ], %l0 + : mov %i0, %o0 + : call %l0 + : mov %i2, %o2 + : cmp %i0, 8 <--- PC */ + pc[-8] == 0x9602400f + && pc[-7] == 0x92100019 + /* skip pc[-6] */ + && pc[-5] == 0x912e2002 + && pc[-4] == 0xe002000a + && pc[-3] == 0x90100018 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x80a62008) + { + /* Need to move up one frame: + + <-- context->cfa + sigacthandler + + */ + *nframes = 1; + return 1; + } + + if (/* Solaris 8 - multi-threaded + --------------------------- + <__libthread_segvhdlr+212>: clr %o2 + <__libthread_segvhdlr+216>: ld [ %fp + -28 ], %l0 + <__libthread_segvhdlr+220>: mov %i4, %o0 + <__libthread_segvhdlr+224>: mov %i1, %o1 + <__libthread_segvhdlr+228>: call %l0 + <__libthread_segvhdlr+232>: mov %i2, %o2 + <__libthread_segvhdlr+236>: ret <--- PC + <__libthread_segvhdlr+240>: restore + <__libthread_segvhdlr+244>: cmp %o1, 0 */ + pc[-6] == 0x94102000 + && pc[-5] == 0xe007bfe4 + && pc[-4] == 0x9010001c + && pc[-3] == 0x92100019 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x81c7e008 + && pc[ 1] == 0x81e80000 + && pc[ 2] == 0x80a26000) + { + /* Need to move up one frame: + + <-- context->cfa + __libthread_segvhdlr + + */ + *nframes = 1; + return 1; + } + + if(/* Solaris 8+ - multi-threaded + ---------------------------- + <__sighndlr>: save %sp, -96, %sp + <__sighndlr+4>: mov %i0, %o0 + <__sighndlr+8>: mov %i1, %o1 + <__sighndlr+12>: call %i3 + <__sighndlr+16>: mov %i2, %o2 + <__sighndlr+20>: ret <--- PC + <__sighndlr+24>: restore */ + pc[-5] == 0x9de3bfa0 + && pc[-4] == 0x90100018 + && pc[-3] == 0x92100019 + && pc[-2] == 0x9fc6c000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x81c7e008 + && pc[ 1] == 0x81e80000) + { + if (/* Solaris 8 /usr/lib/libthread.so.1 + ---------------------------------- + : mov %i0, %o0 */ + savpc[-1] == 0x90100018) + { + /* We need to move up two frames: + + <-- context->cfa + __sighndlr + sigacthandler + + */ + *nframes = 2; + } + else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+ + -------------------------------------------------- */ + { + /* We need to move up three frames: + + <-- context->cfa + __sighndlr + call_user_handler + sigacthandler + + */ + *nframes = 3; + } + return 1; + } + + return 0; +} + +#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state + +#endif + +static _Unwind_Reason_Code +MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + void *pc = context->ra; + struct frame *fp = (struct frame *) context->cfa; + int nframes; + void *this_cfa = context->cfa; + long new_cfa; + void *ra_location, *shifted_ra_location; + mcontext_t *mctx; + int i; + + /* Deal with frame-less function from which a signal was raised. */ + if (_Unwind_IsSignalFrame (context)) + { + /* The CFA is by definition unmodified in this case. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = 0; + + /* This is the canonical RA column. */ + fs->retaddr_column = 15; + + return _URC_NO_REASON; + } + + if (IS_SIGHANDLER (pc, (unsigned int *)fp->fr_savpc, &nframes)) + { + struct handler_args { + struct frame frwin; + ucontext_t ucontext; + } *handler_args; + ucontext_t *ucp; + + /* context->cfa points into the frame after the saved frame pointer and + saved pc (struct frame). + + The ucontext_t structure is in the kernel frame after a struct + frame. Since the frame sizes vary even within OS releases, we + need to walk the stack to get there. */ + + for (i = 0; i < nframes; i++) + fp = (struct frame *) ((char *)fp->fr_savfp + STACK_BIAS); + + handler_args = (struct handler_args *) fp; + ucp = &handler_args->ucontext; + mctx = &ucp->uc_mcontext; + } + + /* Exit if the pattern at the return address does not match the + previous three patterns. */ + else + return _URC_END_OF_STACK; + + new_cfa = mctx->gregs[REG_SP]; + /* The frame address is %sp + STACK_BIAS in 64-bit mode. */ + new_cfa += STACK_BIAS; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - (long) this_cfa; + + /* Restore global and out registers (in this order) from the + ucontext_t structure, uc_mcontext.gregs field. */ + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + /* First the global registers and then the out registers. */ + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long)&mctx->gregs[REG_Y + i] - new_cfa; + } + + /* Just above the stack pointer there are 16 extended words in which + the register window (in and local registers) was saved. */ + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset = i*sizeof(long); + } + + /* Check whether we need to restore FPU registers. */ + if (mctx->fpregs.fpu_qcnt) + { + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = (long)&mctx->fpregs.fpu_fr.fpu_regs[i] - new_cfa; + } + +#ifdef __arch64__ + /* For 64-bit, fpu_fr.fpu_dregs contains 32 instead of 16 doubles. */ + for (i = 32; i < 64; i++) + { + if (i > 32 && (i & 1)) + continue; + + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = (long)&mctx->fpregs.fpu_fr.fpu_dregs[i/2] - new_cfa; + } +#endif + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = &mctx->gregs[REG_PC]; + shifted_ra_location = &mctx->gregs[REG_Y]; + *(void **)shifted_ra_location = *(void **)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)shifted_ra_location - new_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} diff --git a/libgcc/config/xtensa/linux-unwind.h b/libgcc/config/xtensa/linux-unwind.h new file mode 100644 index 00000000000..32e93497287 --- /dev/null +++ b/libgcc/config/xtensa/linux-unwind.h @@ -0,0 +1,97 @@ +/* DWARF2 EH unwinding support for Xtensa. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. + +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 +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2-xtensa.c for the structs. + Don't use this at all if inhibit_libc is used. */ + +#ifndef inhibit_libc + +#include +#include + +/* Encoded bytes for Xtensa instructions: + movi a2, __NR_rt_sigreturn + syscall + entry (first byte only) + Some of the bytes are endian-dependent. */ + +#define MOVI_BYTE0 0x22 +#define MOVI_BYTE2 225 /* __NR_rt_sigreturn */ +#define SYSC_BYTE0 0 +#define SYSC_BYTE2 0 + +#ifdef __XTENSA_EB__ +#define MOVI_BYTE1 0x0a +#define SYSC_BYTE1 0x05 +#define ENTRY_BYTE 0x6c +#else +#define MOVI_BYTE1 0xa0 +#define SYSC_BYTE1 0x50 +#define ENTRY_BYTE 0x36 +#endif + +#define MD_FALLBACK_FRAME_STATE_FOR xtensa_fallback_frame_state + +static _Unwind_Reason_Code +xtensa_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *rt_; + + /* movi a2, __NR_rt_sigreturn; syscall */ + if (pc[0] != MOVI_BYTE0 + || pc[1] != MOVI_BYTE1 + || pc[2] != MOVI_BYTE2 + || pc[3] != SYSC_BYTE0 + || pc[4] != SYSC_BYTE1 + || pc[5] != SYSC_BYTE2) + return _URC_END_OF_STACK; + + rt_ = context->sp; + sc = &rt_->uc.uc_mcontext; + fs->signal_regs = (_Unwind_Word *) sc->sc_a; + + /* If the signal arrived just before an ENTRY instruction, find the return + address and pretend the signal arrived before executing the CALL. */ + if (*(unsigned char *) sc->sc_pc == ENTRY_BYTE) + { + unsigned callinc = (sc->sc_ps >> 16) & 3; + fs->signal_ra = ((sc->sc_a[callinc << 2] & XTENSA_RA_FIELD_MASK) + | context->ra_high_bits) - 3; + } + else + fs->signal_ra = sc->sc_pc; + + fs->signal_frame = 1; + return _URC_NO_REASON; +} + +#endif /* ifdef inhibit_libc */ diff --git a/libgcc/configure b/libgcc/configure index 8232725f372..1a3a0bde258 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -3962,6 +3962,8 @@ tmake_file="${tmake_file_}" +ac_config_links="$ac_config_links md-unwind-support.h:config/$md_unwind_header" + # We need multilib support. ac_config_files="$ac_config_files Makefile" @@ -4532,6 +4534,7 @@ esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" +config_links="$ac_config_links" config_commands="$ac_config_commands" _ACEOF @@ -4556,6 +4559,9 @@ Usage: $0 [OPTION]... [TAG]... Configuration files: $config_files +Configuration links: +$config_links + Configuration commands: $config_commands @@ -4683,6 +4689,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in + "md-unwind-support.h") CONFIG_LINKS="$CONFIG_LINKS md-unwind-support.h:config/$md_unwind_header" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; @@ -4697,6 +4704,7 @@ done # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi @@ -4876,7 +4884,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" -eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" +eval set X " :F $CONFIG_FILES :L $CONFIG_LINKS :C $CONFIG_COMMANDS" shift for ac_tag do @@ -5089,7 +5097,38 @@ which seems to be undefined. Please make sure it is defined." >&2;} || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + :L) + # + # CONFIG_LINK + # + + if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then + : + else + # Prefer the file from the source tree if names are identical. + if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then + ac_source=$srcdir/$ac_source + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5 +$as_echo "$as_me: linking $ac_source to $ac_file" >&6;} + + if test ! -r "$ac_source"; then + as_fn_error "$ac_source: file not found" "$LINENO" 5 + fi + rm -f "$ac_file" + + # Try a relative symlink, then a hard link, then a copy. + case $srcdir in + [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;; + *) ac_rel_source=$ac_top_build_prefix$ac_source ;; + esac + ln -s "$ac_rel_source" "$ac_file" 2>/dev/null || + ln "$ac_source" "$ac_file" 2>/dev/null || + cp -p "$ac_source" "$ac_file" || + as_fn_error "cannot link or copy $ac_source to $ac_file" "$LINENO" 5 + fi + ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 75f3967b0c3..f2bcabf4872 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -278,6 +278,7 @@ AC_SUBST(tmake_file) AC_SUBST(cpu_type) AC_SUBST(extra_parts) AC_SUBST(asm_hidden_op) +AC_CONFIG_LINKS([md-unwind-support.h:config/$md_unwind_header]) # We need multilib support. AC_CONFIG_FILES([Makefile])