+2011-06-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * 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 <howarth@bromo.med.uc.edu>
* varpool.c (varpool_extra_name_alias): Return NULL, not false.
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#include <signal.h>
-#include <sys/ucontext.h>
-
-#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;
-}
/* 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.
#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
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <sys/context_t.h>
-
-#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;
-}
/* Handle #pragma extern_prefix. */
#define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 1
-
-#define MD_UNWIND_SUPPORT "config/alpha/osf5-unwind.h"
+++ /dev/null
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <vms/pdscdef.h>
-#include <vms/libicb.h>
-#include <vms/chfctxdef.h>
-#include <vms/chfdef.h>
-
-#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;
-}
-
-
-
#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)
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-
-#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 */
-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
%{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: \
/* 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.
/* 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 { \
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-
-#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 <signal.h>
-#include <sys/ucontext.h>
-
-#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 */
#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"
#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"
#include <windows.h>
#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
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#include <ucontext.h>
-#include <sys/frame.h>
-
-#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:
-
- <signal handler> <-- context->cfa
- __sighndlr
- call_user_handler
- sigacthandler
- <kernel>
-
- 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
- ----------------------------
- <sigacthandler+17>: mov 0x10(%ebp),%esi
- <sigacthandler+20>: push %esi
- <sigacthandler+21>: pushl 0xc(%ebp)
- <sigacthandler+24>: mov 0x8(%ebp),%ecx
- <sigacthandler+27>: push %ecx
- <sigacthandler+28>: mov offset(%ebx),%eax
- <sigacthandler+34>: call *(%eax,%ecx,4)
- <sigacthandler+37>: add $0xc,%esp <--- PC
- <sigacthandler+40>: 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
- ----------------------------
- <sigacthandler+16>: mov 0x244(%ebx),%ecx
- <sigacthandler+22>: mov 0x8(%ebp),%eax
- <sigacthandler+25>: mov (%ecx,%eax,4),%ecx
- <sigacthandler+28>: pushl 0x10(%ebp)
- <sigacthandler+31>: pushl 0xc(%ebp)
- <sigacthandler+34>: push %eax
- <sigacthandler+35>: call *%ecx
- <sigacthandler+37>: add $0xc,%esp <--- PC
- <sigacthandler+40>: 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
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-
-#define MD_UNWIND_SUPPORT "config/i386/sol2-unwind.h"
+++ /dev/null
-/* Definitions for Dwarf2 EH unwind support for Windows32 targets
- Copyright (C) 2007, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Pascal Obry <obry@adacore.com>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* 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 <windows.h>
-/* 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),<reg> */ \
-
-/* 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;
-}
+++ /dev/null
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-
-#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 */
#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
/* 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 <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
David Mosberger-Tang <davidm@hpl.hp.com>
return (_Unwind_Ptr) context->bsp;
}
-#ifdef MD_UNWIND_SUPPORT
-#include MD_UNWIND_SUPPORT
-#endif
+#include "md-unwind-support.h"
\f
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+++ /dev/null
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-#include <vms/libicb.h>
-#include <vms/chfdef.h>
-#include <vms/chfctxdef.h>
-
-#define __int64 long long
-#include <vms/intstkdef.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#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;
-}
-
/* 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))
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-
-/* <sys/ucontext.h> 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 */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-
-#define MD_UNWIND_SUPPORT "config/m68k/linux-unwind.h"
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-#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 <signal.h>
-#include <asm/unistd.h>
-
-/* 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
%{!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 \
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-#include <unistd.h>
-
-/* 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 */
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-
-/* 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 */
/* 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.
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"
/* 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.
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-
-#define MD_UNWIND_SUPPORT "config/pa/linux-unwind.h"
+++ /dev/null
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-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)
#include <stdbool.h>
#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
+++ /dev/null
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-#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
-}
#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
#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). */
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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;
-}
#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). */
+++ /dev/null
-/* DWARF2 EH unwinding support for TPF OS.
- Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
- Contributed by P.J. Darcy (darcypj@us.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include <dlfcn.h>
-
-/* Function Name: __isPATrange
- Parameters passed into it: address to check
- Return Value: A 1 if address is in pat code "range", 0 if not
- Description: This function simply checks to see if the address
- passed to it is in the CP pat code range. */
-
-#define MIN_PATRANGE 0x10000
-#define MAX_PATRANGE 0x800000
-
-static inline unsigned int
-__isPATrange (void *addr)
-{
- if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
- return 1;
- else
- return 0;
-}
-
-/* TPF return address offset from start of stack frame. */
-#define TPFRA_OFFSET 168
-
-/* Exceptions macro defined for TPF so that functions without
- dwarf frame information can be used with exceptions. */
-#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
-
-static _Unwind_Reason_Code
-s390_fallback_frame_state (struct _Unwind_Context *context,
- _Unwind_FrameState *fs)
-{
- unsigned long int regs;
- unsigned long int new_cfa;
- int i;
-
- regs = *((unsigned long int *)
- (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
-
- /* Are we going through special linkage code? */
- if (__isPATrange (context->ra))
- {
-
- /* Our return register isn't zero for end of stack, so
- check backward stackpointer to see if it is zero. */
- if (regs == NULL)
- return _URC_END_OF_STACK;
-
- /* No stack frame. */
- fs->regs.cfa_how = CFA_REG_OFFSET;
- fs->regs.cfa_reg = 15;
- fs->regs.cfa_offset = STACK_POINTER_OFFSET;
-
- /* All registers remain unchanged ... */
- for (i = 0; i < 32; i++)
- {
- fs->regs.reg[i].how = REG_SAVED_REG;
- fs->regs.reg[i].loc.reg = i;
- }
-
- /* ... except for %r14, which is stored at CFA-112
- and used as return address. */
- fs->regs.reg[14].how = REG_SAVED_OFFSET;
- fs->regs.reg[14].loc.offset = TPFRA_OFFSET - STACK_POINTER_OFFSET;
- fs->retaddr_column = 14;
-
- return _URC_NO_REASON;
- }
-
- regs = *((unsigned long int *)
- (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
- new_cfa = regs + STACK_POINTER_OFFSET;
-
- fs->regs.cfa_how = CFA_REG_OFFSET;
- fs->regs.cfa_reg = 15;
- fs->regs.cfa_offset = new_cfa -
- (unsigned long int) context->cfa + STACK_POINTER_OFFSET;
-
- for (i = 0; i < 16; i++)
- {
- fs->regs.reg[i].how = REG_SAVED_OFFSET;
- fs->regs.reg[i].loc.offset = regs + i*8 - new_cfa;
- }
-
- for (i = 0; i < 4; i++)
- {
- fs->regs.reg[16 + i].how = REG_SAVED_OFFSET;
- fs->regs.reg[16 + i].loc.offset = regs + 16*8 + i*8 - new_cfa;
- }
-
- fs->retaddr_column = 14;
-
- return _URC_NO_REASON;
-}
-
-/* Function Name: __tpf_eh_return
- Parameters passed into it: Destination address to jump to.
- Return Value: Converted Destination address if a Pat Stub exists.
- Description: This function swaps the unwinding return address
- with the cp stub code. The original target return address is
- then stored into the tpf return address field. The cp stub
- code is searched for by climbing back up the stack and
- comparing the tpf stored return address object address to
- that of the targets object address. */
-
-#define CURRENT_STACK_PTR() \
- ({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; })
-
-#define PREVIOUS_STACK_PTR() \
- ((unsigned long int *)(*(CURRENT_STACK_PTR())))
-
-#define RA_OFFSET 112
-#define R15_OFFSET 120
-#define TPFAREA_OFFSET 160
-#define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET
-#define INVALID_RETURN 0
-
-void * __tpf_eh_return (void *target);
-
-void *
-__tpf_eh_return (void *target)
-{
- Dl_info targetcodeInfo, currentcodeInfo;
- int retval;
- void *current, *stackptr, *destination_frame;
- unsigned long int shifter, is_a_stub;
-
- is_a_stub = 0;
-
- /* Get code info for target return's address. */
- retval = dladdr (target, &targetcodeInfo);
-
- /* Ensure the code info is valid (for target). */
- if (retval != INVALID_RETURN)
- {
-
- /* Get the stack pointer of the stack frame to be modified by
- the exception unwinder. So that we can begin our climb
- there. */
- stackptr = (void *) *((unsigned long int *) (*(PREVIOUS_STACK_PTR())));
-
- /* Begin looping through stack frames. Stop if invalid
- code information is retrieved or if a match between the
- current stack frame iteration shared object's address
- matches that of the target, calculated above. */
- do
- {
- /* Get return address based on our stackptr iterator. */
- current = (void *) *((unsigned long int *)
- (stackptr+RA_OFFSET));
-
- /* Is it a Pat Stub? */
- if (__isPATrange (current))
- {
- /* Yes it was, get real return address
- in TPF stack area. */
- current = (void *) *((unsigned long int *)
- (stackptr+TPFRA_OFFSET));
- is_a_stub = 1;
- }
-
- /* Get codeinfo on RA so that we can figure out
- the module address. */
- retval = dladdr (current, ¤tcodeInfo);
-
- /* Check that codeinfo for current stack frame is valid.
- Then compare the module address of current stack frame
- to target stack frame to determine if we have the pat
- stub address we want. Also ensure we are dealing
- with a module crossing, stub return address. */
- if (is_a_stub && retval != INVALID_RETURN
- && targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase)
- {
- /* Yes! They are in the same module.
- Force copy of TPF private stack area to
- destination stack frame TPF private area. */
- destination_frame = (void *) *((unsigned long int *)
- (*PREVIOUS_STACK_PTR() + R15_OFFSET));
-
- /* Copy TPF linkage area from current frame to
- destination frame. */
- memcpy((void *) (destination_frame + TPFAREA_OFFSET),
- (void *) (stackptr + TPFAREA_OFFSET), TPFAREA_SIZE);
-
- /* Now overlay the
- real target address into the TPF stack area of
- the target frame we are jumping to. */
- *((unsigned long int *) (destination_frame +
- TPFRA_OFFSET)) = (unsigned long int) target;
-
- /* Before returning the desired pat stub address to
- the exception handling unwinder so that it can
- actually do the "leap" shift out the low order
- bit designated to determine if we are in 64BIT mode.
- This is necessary for CTOA stubs.
- Otherwise we leap one byte past where we want to
- go to in the TPF pat stub linkage code. */
- shifter = *((unsigned long int *)
- (stackptr + RA_OFFSET));
-
- shifter &= ~1ul;
-
- /* Store Pat Stub Address in destination Stack Frame. */
- *((unsigned long int *) (destination_frame +
- RA_OFFSET)) = shifter;
-
- /* Re-adjust pat stub address to go to correct place
- in linkage. */
- shifter = shifter - 4;
-
- return (void *) shifter;
- }
-
- /* Desired module pat stub not found ...
- Bump stack frame iterator. */
- stackptr = (void *) *(unsigned long int *) stackptr;
-
- is_a_stub = 0;
-
- } while (stackptr && retval != INVALID_RETURN
- && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase);
- }
-
- /* No pat stub found, could be a problem? Simply return unmodified
- target address. */
- return target;
-}
-
%{!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"
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-#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 */
} \
} 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
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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
/* 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. */
/* 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. */
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#include <ucontext.h>
-#include <sys/frame.h>
-#include <sys/stack.h>
-
-#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
- ----------------------------
- <sigacthandler+24>: add %g5, %o7, %o2
- <sigacthandler+28>: ldx [ %o2 + 0xfa0 ], %g5
- <sigacthandler+32>: sra %i0, 0, %o0
- <sigacthandler+36>: sllx %o0, 3, %g4
- <sigacthandler+40>: ldx [ %g4 + %g5 ], %l0
- <sigacthandler+44>: call %l0
- <sigacthandler+48>: mov %i2, %o2
- <sigacthandler+52>: 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.
-
- <sigacthandler+24>: sra %i0, 0, %l1
-
- Solaris 9 5/02:
- <sigacthandler+28>: ldx [ %o2 + 0xf68 ], %g5
- Solaris 9 9/05:
- <sigacthandler+28>: ldx [ %o2 + 0xe50 ], %g5
-
- <sigacthandler+32>: sllx %l1, 3, %g4
- <sigacthandler+36>: mov %l1, %o0
- <sigacthandler+40>: ldx [ %g4 + %g5 ], %l0
- <sigacthandler+44>: call %l0
- <sigacthandler+48>: mov %i2, %o2
- <sigacthandler+52>: 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:
-
- <signal handler> <-- context->cfa
- sigacthandler
- <kernel>
- */
- *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:
- <sigacthandler+1760>: st %g4, [ %i1 + 0x1c ]
-
- Since patch 108827-08:
- <sigacthandler+1816>: st %l0, [ %i4 + 0x10 ] */
- savpc[-1] == 0xc826601c
- || savpc[-1] == 0xe0272010)
- {
- /* We need to move up three frames:
-
- <signal handler> <-- context->cfa
- __sighndlr
- sigacthandler
- <kernel>
- */
- *nframes = 2;
- }
- else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+
- ---------------------------------------------------------- */
- {
- /* We need to move up three frames:
-
- <signal handler> <-- context->cfa
- __sighndlr
- call_user_handler
- sigacthandler
- <kernel>
- */
- *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].
-
- <sigacthandler+16>: add %o1, %o7, %o3
- <sigacthandler+20>: mov %i1, %o1
-
- <sigacthandler+24>: ld [ %o3 + <offset> ], %o2
-
- <sigacthandler+28>: sll %i0, 2, %o0
- <sigacthandler+32>: ld [ %o0 + %o2 ], %l0
- <sigacthandler+36>: mov %i0, %o0
- <sigacthandler+40>: call %l0
- <sigacthandler+44>: mov %i2, %o2
- <sigacthandler+48>: 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:
-
- <signal handler> <-- context->cfa
- sigacthandler
- <kernel>
- */
- *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:
-
- <signal handler> <-- context->cfa
- __libthread_segvhdlr
- <kernel>
- */
- *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
- ----------------------------------
- <sigacthandler+1796>: mov %i0, %o0 */
- savpc[-1] == 0x90100018)
- {
- /* We need to move up two frames:
-
- <signal handler> <-- context->cfa
- __sighndlr
- sigacthandler
- <kernel>
- */
- *nframes = 2;
- }
- else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+
- -------------------------------------------------- */
- {
- /* We need to move up three frames:
-
- <signal handler> <-- context->cfa
- __sighndlr
- call_user_handler
- sigacthandler
- <kernel>
- */
- *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;
-}
/* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1
-
-#define MD_UNWIND_SUPPORT "config/sparc/sol2-unwind.h"
+++ /dev/null
-/* 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
-<http://www.gnu.org/licenses/>. */
-
-/* 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 <signal.h>
-#include <sys/ucontext.h>
-
-/* 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 */
#undef DBX_REGISTER_NUMBER
-#define MD_UNWIND_SUPPORT "config/xtensa/linux-unwind.h"
-
/* 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.
return (_Unwind_Ptr) context->bases.tbase;
}
-#ifdef MD_UNWIND_SUPPORT
-#include MD_UNWIND_SUPPORT
-#endif
+#include "md-unwind-support.h"
\f
/* Extract any interesting information from the CIE for the translation
unit F belongs to. Return a pointer to the byte after the augmentation,
@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.
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
@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.
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
/* 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
}
#endif
-#ifdef MD_UNWIND_SUPPORT
-#include MD_UNWIND_SUPPORT
-#endif
+#include "md-unwind-support.h"
\f
/* Extract any interesting information from the CIE for the translation
unit F belongs to. Return a pointer to the byte after the augmentation,
+2011-06-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * 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 <ro@CeBiTec.Uni-Bielefeld.DE>
* config.host (mips-sgi-irix[56]*): Restrict to mips-sgi-irix6.5*.
# 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".
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/-.*$//'`
alpha*-*-linux*)
tmake_file="${tmake_file} alpha/t-crtfm"
extra_parts="$extra_parts crtfastmath.o"
+ md_unwind_header=alpha/linux-unwind.h
;;
alpha*-*-freebsd*)
;;
;;
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)
;;
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*-*)
;;
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*)
;;
;;
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*)
;;
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*)
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*)
;;
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*)
;;
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*)
;;
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*)
;;
;;
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)
;;
;;
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)
;;
case ${host} in
sh*-*-linux*)
tmake_file="${tmake_file} sh/t-linux"
+ md_unwind_header=sh/unwind-linux.h
;;
esac
;;
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"
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"
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*)
;;
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"
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#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;
+}
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <sys/context_t.h>
+
+#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;
+}
--- /dev/null
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <vms/pdscdef.h>
+#include <vms/libicb.h>
+#include <vms/chfctxdef.h>
+#include <vms/chfdef.h>
+
+#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;
+}
+
+
+
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+
+#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 */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+
+#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 <signal.h>
+#include <sys/ucontext.h>
+
+#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 */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <ucontext.h>
+#include <sys/frame.h>
+
+#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:
+
+ <signal handler> <-- context->cfa
+ __sighndlr
+ call_user_handler
+ sigacthandler
+ <kernel>
+
+ 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
+ ----------------------------
+ <sigacthandler+17>: mov 0x10(%ebp),%esi
+ <sigacthandler+20>: push %esi
+ <sigacthandler+21>: pushl 0xc(%ebp)
+ <sigacthandler+24>: mov 0x8(%ebp),%ecx
+ <sigacthandler+27>: push %ecx
+ <sigacthandler+28>: mov offset(%ebx),%eax
+ <sigacthandler+34>: call *(%eax,%ecx,4)
+ <sigacthandler+37>: add $0xc,%esp <--- PC
+ <sigacthandler+40>: 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
+ ----------------------------
+ <sigacthandler+16>: mov 0x244(%ebx),%ecx
+ <sigacthandler+22>: mov 0x8(%ebp),%eax
+ <sigacthandler+25>: mov (%ecx,%eax,4),%ecx
+ <sigacthandler+28>: pushl 0x10(%ebp)
+ <sigacthandler+31>: pushl 0xc(%ebp)
+ <sigacthandler+34>: push %eax
+ <sigacthandler+35>: call *%ecx
+ <sigacthandler+37>: add $0xc,%esp <--- PC
+ <sigacthandler+40>: 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
--- /dev/null
+/* Definitions for Dwarf2 EH unwind support for Windows32 targets
+ Copyright (C) 2007, 2009, 2010, 2011
+ Free Software Foundation, Inc.
+ Contributed by Pascal Obry <obry@adacore.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+
+/* 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 <windows.h>
+/* 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),<reg> */ \
+
+/* 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__ */
--- /dev/null
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+
+#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 */
--- /dev/null
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <vms/libicb.h>
+#include <vms/chfdef.h>
+#include <vms/chfctxdef.h>
+
+#define __int64 long long
+#include <vms/intstkdef.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}
+
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+
+/* <sys/ucontext.h> 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 */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+#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 <signal.h>
+#include <asm/unistd.h>
+
+/* 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
--- /dev/null
+/* Dummy header for targets without a definition of
+ MD_FALLBACK_FRAME_STATE_FOR. */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+
+/* 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 */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+
+/* 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 */
--- /dev/null
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#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
--- /dev/null
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#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
+}
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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;
+}
--- /dev/null
+/* DWARF2 EH unwinding support for TPF OS.
+ Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
+ Contributed by P.J. Darcy (darcypj@us.ibm.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+
+/* Function Name: __isPATrange
+ Parameters passed into it: address to check
+ Return Value: A 1 if address is in pat code "range", 0 if not
+ Description: This function simply checks to see if the address
+ passed to it is in the CP pat code range. */
+
+#define MIN_PATRANGE 0x10000
+#define MAX_PATRANGE 0x800000
+
+static inline unsigned int
+__isPATrange (void *addr)
+{
+ if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
+ return 1;
+ else
+ return 0;
+}
+
+/* TPF return address offset from start of stack frame. */
+#define TPFRA_OFFSET 168
+
+/* Exceptions macro defined for TPF so that functions without
+ dwarf frame information can be used with exceptions. */
+#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
+
+static _Unwind_Reason_Code
+s390_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned long int regs;
+ unsigned long int new_cfa;
+ int i;
+
+ regs = *((unsigned long int *)
+ (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
+
+ /* Are we going through special linkage code? */
+ if (__isPATrange (context->ra))
+ {
+
+ /* Our return register isn't zero for end of stack, so
+ check backward stackpointer to see if it is zero. */
+ if (regs == NULL)
+ return _URC_END_OF_STACK;
+
+ /* No stack frame. */
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = 15;
+ fs->regs.cfa_offset = STACK_POINTER_OFFSET;
+
+ /* All registers remain unchanged ... */
+ for (i = 0; i < 32; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_REG;
+ fs->regs.reg[i].loc.reg = i;
+ }
+
+ /* ... except for %r14, which is stored at CFA-112
+ and used as return address. */
+ fs->regs.reg[14].how = REG_SAVED_OFFSET;
+ fs->regs.reg[14].loc.offset = TPFRA_OFFSET - STACK_POINTER_OFFSET;
+ fs->retaddr_column = 14;
+
+ return _URC_NO_REASON;
+ }
+
+ regs = *((unsigned long int *)
+ (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
+ new_cfa = regs + STACK_POINTER_OFFSET;
+
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = 15;
+ fs->regs.cfa_offset = new_cfa -
+ (unsigned long int) context->cfa + STACK_POINTER_OFFSET;
+
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset = regs + i*8 - new_cfa;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ fs->regs.reg[16 + i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[16 + i].loc.offset = regs + 16*8 + i*8 - new_cfa;
+ }
+
+ fs->retaddr_column = 14;
+
+ return _URC_NO_REASON;
+}
+
+/* Function Name: __tpf_eh_return
+ Parameters passed into it: Destination address to jump to.
+ Return Value: Converted Destination address if a Pat Stub exists.
+ Description: This function swaps the unwinding return address
+ with the cp stub code. The original target return address is
+ then stored into the tpf return address field. The cp stub
+ code is searched for by climbing back up the stack and
+ comparing the tpf stored return address object address to
+ that of the targets object address. */
+
+#define CURRENT_STACK_PTR() \
+ ({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; })
+
+#define PREVIOUS_STACK_PTR() \
+ ((unsigned long int *)(*(CURRENT_STACK_PTR())))
+
+#define RA_OFFSET 112
+#define R15_OFFSET 120
+#define TPFAREA_OFFSET 160
+#define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET
+#define INVALID_RETURN 0
+
+void * __tpf_eh_return (void *target);
+
+void *
+__tpf_eh_return (void *target)
+{
+ Dl_info targetcodeInfo, currentcodeInfo;
+ int retval;
+ void *current, *stackptr, *destination_frame;
+ unsigned long int shifter, is_a_stub;
+
+ is_a_stub = 0;
+
+ /* Get code info for target return's address. */
+ retval = dladdr (target, &targetcodeInfo);
+
+ /* Ensure the code info is valid (for target). */
+ if (retval != INVALID_RETURN)
+ {
+
+ /* Get the stack pointer of the stack frame to be modified by
+ the exception unwinder. So that we can begin our climb
+ there. */
+ stackptr = (void *) *((unsigned long int *) (*(PREVIOUS_STACK_PTR())));
+
+ /* Begin looping through stack frames. Stop if invalid
+ code information is retrieved or if a match between the
+ current stack frame iteration shared object's address
+ matches that of the target, calculated above. */
+ do
+ {
+ /* Get return address based on our stackptr iterator. */
+ current = (void *) *((unsigned long int *)
+ (stackptr+RA_OFFSET));
+
+ /* Is it a Pat Stub? */
+ if (__isPATrange (current))
+ {
+ /* Yes it was, get real return address
+ in TPF stack area. */
+ current = (void *) *((unsigned long int *)
+ (stackptr+TPFRA_OFFSET));
+ is_a_stub = 1;
+ }
+
+ /* Get codeinfo on RA so that we can figure out
+ the module address. */
+ retval = dladdr (current, ¤tcodeInfo);
+
+ /* Check that codeinfo for current stack frame is valid.
+ Then compare the module address of current stack frame
+ to target stack frame to determine if we have the pat
+ stub address we want. Also ensure we are dealing
+ with a module crossing, stub return address. */
+ if (is_a_stub && retval != INVALID_RETURN
+ && targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase)
+ {
+ /* Yes! They are in the same module.
+ Force copy of TPF private stack area to
+ destination stack frame TPF private area. */
+ destination_frame = (void *) *((unsigned long int *)
+ (*PREVIOUS_STACK_PTR() + R15_OFFSET));
+
+ /* Copy TPF linkage area from current frame to
+ destination frame. */
+ memcpy((void *) (destination_frame + TPFAREA_OFFSET),
+ (void *) (stackptr + TPFAREA_OFFSET), TPFAREA_SIZE);
+
+ /* Now overlay the
+ real target address into the TPF stack area of
+ the target frame we are jumping to. */
+ *((unsigned long int *) (destination_frame +
+ TPFRA_OFFSET)) = (unsigned long int) target;
+
+ /* Before returning the desired pat stub address to
+ the exception handling unwinder so that it can
+ actually do the "leap" shift out the low order
+ bit designated to determine if we are in 64BIT mode.
+ This is necessary for CTOA stubs.
+ Otherwise we leap one byte past where we want to
+ go to in the TPF pat stub linkage code. */
+ shifter = *((unsigned long int *)
+ (stackptr + RA_OFFSET));
+
+ shifter &= ~1ul;
+
+ /* Store Pat Stub Address in destination Stack Frame. */
+ *((unsigned long int *) (destination_frame +
+ RA_OFFSET)) = shifter;
+
+ /* Re-adjust pat stub address to go to correct place
+ in linkage. */
+ shifter = shifter - 4;
+
+ return (void *) shifter;
+ }
+
+ /* Desired module pat stub not found ...
+ Bump stack frame iterator. */
+ stackptr = (void *) *(unsigned long int *) stackptr;
+
+ is_a_stub = 0;
+
+ } while (stackptr && retval != INVALID_RETURN
+ && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase);
+ }
+
+ /* No pat stub found, could be a problem? Simply return unmodified
+ target address. */
+ return target;
+}
+
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+#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 */
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <ucontext.h>
+#include <sys/frame.h>
+#include <sys/stack.h>
+
+#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
+ ----------------------------
+ <sigacthandler+24>: add %g5, %o7, %o2
+ <sigacthandler+28>: ldx [ %o2 + 0xfa0 ], %g5
+ <sigacthandler+32>: sra %i0, 0, %o0
+ <sigacthandler+36>: sllx %o0, 3, %g4
+ <sigacthandler+40>: ldx [ %g4 + %g5 ], %l0
+ <sigacthandler+44>: call %l0
+ <sigacthandler+48>: mov %i2, %o2
+ <sigacthandler+52>: 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.
+
+ <sigacthandler+24>: sra %i0, 0, %l1
+
+ Solaris 9 5/02:
+ <sigacthandler+28>: ldx [ %o2 + 0xf68 ], %g5
+ Solaris 9 9/05:
+ <sigacthandler+28>: ldx [ %o2 + 0xe50 ], %g5
+
+ <sigacthandler+32>: sllx %l1, 3, %g4
+ <sigacthandler+36>: mov %l1, %o0
+ <sigacthandler+40>: ldx [ %g4 + %g5 ], %l0
+ <sigacthandler+44>: call %l0
+ <sigacthandler+48>: mov %i2, %o2
+ <sigacthandler+52>: 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:
+
+ <signal handler> <-- context->cfa
+ sigacthandler
+ <kernel>
+ */
+ *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:
+ <sigacthandler+1760>: st %g4, [ %i1 + 0x1c ]
+
+ Since patch 108827-08:
+ <sigacthandler+1816>: st %l0, [ %i4 + 0x10 ] */
+ savpc[-1] == 0xc826601c
+ || savpc[-1] == 0xe0272010)
+ {
+ /* We need to move up three frames:
+
+ <signal handler> <-- context->cfa
+ __sighndlr
+ sigacthandler
+ <kernel>
+ */
+ *nframes = 2;
+ }
+ else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+
+ ---------------------------------------------------------- */
+ {
+ /* We need to move up three frames:
+
+ <signal handler> <-- context->cfa
+ __sighndlr
+ call_user_handler
+ sigacthandler
+ <kernel>
+ */
+ *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].
+
+ <sigacthandler+16>: add %o1, %o7, %o3
+ <sigacthandler+20>: mov %i1, %o1
+
+ <sigacthandler+24>: ld [ %o3 + <offset> ], %o2
+
+ <sigacthandler+28>: sll %i0, 2, %o0
+ <sigacthandler+32>: ld [ %o0 + %o2 ], %l0
+ <sigacthandler+36>: mov %i0, %o0
+ <sigacthandler+40>: call %l0
+ <sigacthandler+44>: mov %i2, %o2
+ <sigacthandler+48>: 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:
+
+ <signal handler> <-- context->cfa
+ sigacthandler
+ <kernel>
+ */
+ *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:
+
+ <signal handler> <-- context->cfa
+ __libthread_segvhdlr
+ <kernel>
+ */
+ *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
+ ----------------------------------
+ <sigacthandler+1796>: mov %i0, %o0 */
+ savpc[-1] == 0x90100018)
+ {
+ /* We need to move up two frames:
+
+ <signal handler> <-- context->cfa
+ __sighndlr
+ sigacthandler
+ <kernel>
+ */
+ *nframes = 2;
+ }
+ else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+
+ -------------------------------------------------- */
+ {
+ /* We need to move up three frames:
+
+ <signal handler> <-- context->cfa
+ __sighndlr
+ call_user_handler
+ sigacthandler
+ <kernel>
+ */
+ *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;
+}
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+/* 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 <signal.h>
+#include <sys/ucontext.h>
+
+/* 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 */
+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"
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
Configuration files:
$config_files
+Configuration links:
+$config_links
+
Configuration commands:
$config_commands
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" ;;
# 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
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
|| 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;}
;;
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])