* doc/tm.texi (MD_UNWIND_SUPPORT): Document.
(MD_FALLBACK_FRAME_STATE_FOR): Update.
* unwind-dw2.c (MD_UNWIND_SUPPORT): #include if defined.
(uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
(MD_FROB_UPDATE_CONTEXT): Remove default.
(uw_update_context_1): Instead #ifdef invocation.
* config/ia64/unwind-ia64.c (MD_UNWIND_SUPPORT): #include if defined.
(uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
* config/alpha/gnu.h (MD_FALLBACK_FRAME_STATE_FOR): Don't undef.
(MD_UNWIND_SUPPORT): Undefine this instead.
* config/i386/gnu.h: Likewise.
* config/alpha/linux-unwind.h: New file, macro converted to
function, extracted from..
* config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): ..this.
(MD_UNWIND_SUPPORT): Define.
* config/alpha/vms-unwind.h, config/alpha/vms.h: Likewise.
* config/i386/linux-unwind.h, config/i386/linux.h,
config/i386/linux64.h: Likewise.
* config/ia64/linux-unwind.h, config/ia64/linux.h: Likewise.
MD_HANDLE_UNWABI too.
* config/mips/linux-unwind.h, config/mips/linux.h: Likewise.
* config/pa/linux-unwind.h, config/pa/pa32-linux.h: Likewise.
* config/rs6000/darwin-unwind.h, config/rs6000/darwin.h: Likewise.
* config/s390/linux-unwind.h, config/s390/linux.h: Likewise.
* config/sparc/linux-unwind.h, config/sparc/linux.h,
config/sparc/linux64.h: Likewise.
* config/sh/linux-unwind.h, config/sh/linux.h: Likewise, but merge
SH_FALLBACK_FRAME_FLOAT_STATE into sh_fallback_frame_state.
* config/rs6000/linux-unwind.h, config/rs6000/linux.h,
config/rs6000/linux64.h: Likewise. Split out get_sigcontext
function. Use ARG_POINTER_REGNUM for 32-bit temp reg too.
From-SVN: r87167
+2004-09-08 Alan Modra <amodra@bigpond.net.au>
+
+ * doc/tm.texi (MD_UNWIND_SUPPORT): Document.
+ (MD_FALLBACK_FRAME_STATE_FOR): Update.
+ * unwind-dw2.c (MD_UNWIND_SUPPORT): #include if defined.
+ (uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
+ (MD_FROB_UPDATE_CONTEXT): Remove default.
+ (uw_update_context_1): Instead #ifdef invocation.
+ * config/ia64/unwind-ia64.c (MD_UNWIND_SUPPORT): #include if defined.
+ (uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
+ * config/alpha/gnu.h (MD_FALLBACK_FRAME_STATE_FOR): Don't undef.
+ (MD_UNWIND_SUPPORT): Undefine this instead.
+ * config/i386/gnu.h: Likewise.
+ * config/alpha/linux-unwind.h: New file, macro converted to
+ function, extracted from..
+ * config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): ..this.
+ (MD_UNWIND_SUPPORT): Define.
+ * config/alpha/vms-unwind.h, config/alpha/vms.h: Likewise.
+ * config/i386/linux-unwind.h, config/i386/linux.h,
+ config/i386/linux64.h: Likewise.
+ * config/ia64/linux-unwind.h, config/ia64/linux.h: Likewise.
+ MD_HANDLE_UNWABI too.
+ * config/mips/linux-unwind.h, config/mips/linux.h: Likewise.
+ * config/pa/linux-unwind.h, config/pa/pa32-linux.h: Likewise.
+ * config/rs6000/darwin-unwind.h, config/rs6000/darwin.h: Likewise.
+ * config/s390/linux-unwind.h, config/s390/linux.h: Likewise.
+ * config/sparc/linux-unwind.h, config/sparc/linux.h,
+ config/sparc/linux64.h: Likewise.
+ * config/sh/linux-unwind.h, config/sh/linux.h: Likewise, but merge
+ SH_FALLBACK_FRAME_FLOAT_STATE into sh_fallback_frame_state.
+ * config/rs6000/linux-unwind.h, config/rs6000/linux.h,
+ config/rs6000/linux64.h: Likewise. Split out get_sigcontext
+ function. Use ARG_POINTER_REGNUM for 32-bit temp reg too.
+
2004-09-07 Jan Hubicka <jh@suse.cz>
* cse.c (fold_rtx): Avoid building of
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
-#undef MD_FALLBACK_FRAME_STATE_FOR
+#undef MD_UNWIND_SUPPORT
--- /dev/null
+/* DWARF2 EH unwinding support for Alpha Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* 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->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 30;
+ fs->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;
+}
#define USE_LD_AS_NEEDED 1
#endif
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#ifdef IN_LIBGCC2
-#include <signal.h>
-#include <sys/ucontext.h>
-#endif
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- struct sigcontext *sc_; \
- long new_cfa_, i_; \
- \
- if (pc_[0] != 0x47fe0410 /* mov $30,$16 */ \
- || pc_[2] != 0x00000083 /* callsys */) \
- break; \
- if ((CONTEXT)->cfa == 0) \
- break; \
- 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 \
- break; \
- new_cfa_ = sc_->sc_regs[30]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 30; \
- (FS)->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; \
- goto SUCCESS; \
- } while (0)
+#define MD_UNWIND_SUPPORT "config/alpha/linux-unwind.h"
--- /dev/null
+/* DWARF2 EH unwinding support for Alpha VMS.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <pdscdef.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)
+{
+ PDSCDEF *pv = *((PDSCDEF **) context->reg [29]);
+
+ if (pv && ((long) pv & 0x7) == 0) /* low bits 0 means address */
+ pv = *(PDSCDEF **) pv;
+
+ if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_STACK))
+ {
+ int i, j;
+
+ fs->cfa_offset = pv->pdsc$l_size;
+ fs->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
+ fs->retaddr_column = 26;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->regs.reg[27].loc.offset = -pv->pdsc$l_size;
+ fs->regs.reg[27].how = REG_SAVED_OFFSET;
+ fs->regs.reg[26].loc.offset
+ = -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset);
+ fs->regs.reg[26].how = REG_SAVED_OFFSET;
+
+ for (i = 0, j = 0; i < 32; i++)
+ if (1<<i & pv->pdsc$l_ireg_mask)
+ {
+ fs->regs.reg[i].loc.offset
+ = -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset - 8 * ++j);
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ }
+
+ return _URC_NO_REASON;
+ }
+ else if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_REGISTER))
+ {
+ fs->cfa_offset = pv->pdsc$l_size;
+ fs->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
+ fs->retaddr_column = 26;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->regs.reg[26].loc.reg = pv->pdsc$b_save_ra;
+ fs->regs.reg[26].how = REG_SAVED_REG;
+ fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp;
+ fs->regs.reg[29].how = REG_SAVED_REG;
+
+ return _URC_NO_REASON;
+ }
+ return _URC_END_OF_STACK;
+}
#define LINK_EH_SPEC "vms-dwarf2eh.o%s "
-#ifdef IN_LIBGCC2
-#include <pdscdef.h>
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- PDSCDEF *pv = *((PDSCDEF **) (CONTEXT)->reg [29]); \
- \
- if (pv && ((long) pv & 0x7) == 0) /* low bits 0 means address */ \
- pv = *(PDSCDEF **) pv; \
- \
- if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_STACK)) \
- { \
- int i, j; \
- \
- (FS)->cfa_offset = pv->pdsc$l_size; \
- (FS)->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; \
- (FS)->retaddr_column = 26; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->regs.reg[27].loc.offset = -pv->pdsc$l_size; \
- (FS)->regs.reg[27].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[26].loc.offset \
- = -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset); \
- (FS)->regs.reg[26].how = REG_SAVED_OFFSET; \
- \
- for (i = 0, j = 0; i < 32; i++) \
- if (1<<i & pv->pdsc$l_ireg_mask) \
- { \
- (FS)->regs.reg[i].loc.offset \
- = -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset - 8 * ++j); \
- (FS)->regs.reg[i].how = REG_SAVED_OFFSET; \
- } \
- \
- goto SUCCESS; \
- } \
- else if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_REGISTER)) \
- { \
- (FS)->cfa_offset = pv->pdsc$l_size; \
- (FS)->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; \
- (FS)->retaddr_column = 26; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->regs.reg[26].loc.reg = pv->pdsc$b_save_ra; \
- (FS)->regs.reg[26].how = REG_SAVED_REG; \
- (FS)->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; \
- (FS)->regs.reg[29].how = REG_SAVED_REG; \
- \
- goto SUCCESS; \
- } \
-} while (0)
-#endif
+#define MD_UNWIND_SUPPORT "config/alpha/vms-unwind.h"
/* This is how to output an assembler line
that says to advance the location counter
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
-#undef MD_FALLBACK_FRAME_STATE_FOR
+#undef MD_UNWIND_SUPPORT
--- /dev/null
+/* DWARF2 EH unwinding support for AMD x86-64 and x86.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* 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;
+ sc = (struct sigcontext *) &uc_->uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->rsp;
+ fs->cfa_how = CFA_REG_OFFSET;
+ /* Register 7 is rsp */
+ fs->cfa_reg = 7;
+ fs->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;
+ 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 !(__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;
+ sc = (struct sigcontext *) &rt_->uc.uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->esp;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 4;
+ fs->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;
+ return _URC_NO_REASON;
+}
+#endif /* not glibc 2.0 */
+#endif /* ifdef __x86_64__ */
+#endif /* ifdef inhibit_libc */
#undef NEED_INDICATE_EXEC_STACK
#define NEED_INDICATE_EXEC_STACK 1
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#ifdef IN_LIBGCC2
-/* 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 !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
-#include <signal.h>
-#include <sys/ucontext.h>
-
-#define REG_NAME(reg) reg
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- 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; \
- sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->REG_NAME(esp); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 4; \
- (FS)->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_->REG_NAME(eax) - new_cfa_; \
- (FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[3].loc.offset = (long)&sc_->REG_NAME(ebx) - new_cfa_; \
- (FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[1].loc.offset = (long)&sc_->REG_NAME(ecx) - new_cfa_; \
- (FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[2].loc.offset = (long)&sc_->REG_NAME(edx) - new_cfa_; \
- (FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[6].loc.offset = (long)&sc_->REG_NAME(esi) - new_cfa_; \
- (FS)->regs.reg[7].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[7].loc.offset = (long)&sc_->REG_NAME(edi) - new_cfa_; \
- (FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[5].loc.offset = (long)&sc_->REG_NAME(ebp) - new_cfa_; \
- (FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[8].loc.offset = (long)&sc_->REG_NAME(eip) - new_cfa_; \
- (FS)->retaddr_column = 8; \
- goto SUCCESS; \
- } while (0)
-#endif /* not glibc 2.0 */
-#endif /* IN_LIBGCC2 */
+#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
#undef NEED_INDICATE_EXEC_STACK
#define NEED_INDICATE_EXEC_STACK 1
-/* 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 IN_LIBGCC2
-#include <signal.h>
-#include <sys/ucontext.h>
-#endif
-
-#ifdef __x86_64__
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- 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; \
- sc_ = (struct sigcontext *) &uc_->uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->rsp; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- /* Register 7 is rsp */ \
- (FS)->cfa_reg = 7; \
- (FS)->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; \
- goto SUCCESS; \
- } while (0)
-#else /* ifdef __x86_64__ */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- 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; \
- sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->esp; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 4; \
- (FS)->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; \
- goto SUCCESS; \
- } while (0)
-#endif /* ifdef __x86_64__ */
-#endif /* ifdef inhibit_libc */
+#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
--- /dev/null
+/* DWARF2 EH unwinding support for IA64 Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.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->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);
+ }
+
+ 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;
+
+ return _URC_NO_REASON;
+ }
+ return _URC_END_OF_STACK;
+}
+
+#define MD_HANDLE_UNWABI ia64_handle_unwabi
+
+static void
+ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ if (fs->unwabi == ((3 << 8) | 's')
+ || fs->unwabi == ((0 << 8) | 's'))
+ {
+ 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->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);
+ }
+
+ /* pfs_loc already set above. Without this pfs_loc would point
+ incorrectly to sc_cfm instead of sc_ar_pfs. */
+ fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;
+ }
+}
+#endif /* glibc-2.3 or better */
#undef LINK_EH_SPEC
#define LINK_EH_SPEC ""
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.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)
-
-#ifdef IN_LIBGCC2
-#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(CONTEXT, FS, SUCCESS) \
- 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)->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); \
- } \
- \
- (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; \
- \
- goto SUCCESS; \
- }
-
-#define MD_HANDLE_UNWABI(CONTEXT, FS) \
- if ((FS)->unwabi == ((3 << 8) | 's') \
- || (FS)->unwabi == ((0 << 8) | 's')) \
- { \
- 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)->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); \
- } \
- \
- /* pfs_loc already set above. Without this pfs_loc would point \
- incorrectly to sc_cfm instead of sc_ar_pfs. */ \
- (FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; \
- }
-
-#endif /* IN_LIBGCC2 */
-#endif /* glibc-2.3 or better */
+#define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h"
#undef ENABLE_MALLOC_CHECKING
#ifndef __USING_SJLJ_EXCEPTIONS__
+
#define UNW_VER(x) ((x) >> 48)
#define UNW_FLAG_MASK 0x0000ffff00000000
#define UNW_FLAG_OSMASK 0x0000f00000000000
return (_Unwind_Ptr) context->bsp;
}
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
\f
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
os-specific fallback mechanism. This will necessarily
not provide a personality routine or LSDA. */
#ifdef MD_FALLBACK_FRAME_STATE_FOR
- MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
+ if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
+ return _URC_NO_REASON;
/* [SCRA 11.4.1] A leaf function with no memory stack, no exception
handlers, and which keeps the return value in B0 does not need
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
fs->curr.reg[UNW_REG_RP].when = -1;
fs->curr.reg[UNW_REG_RP].val = 0;
- goto success;
+ return _URC_NO_REASON;
}
-
- return _URC_END_OF_STACK;
- success:
- return _URC_NO_REASON;
-#else
- return _URC_END_OF_STACK;
#endif
+ return _URC_END_OF_STACK;
}
context->region_start = ent->start_offset + segment_base;
--- /dev/null
+/* DWARF2 EH unwinding support for MIPS Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#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>
+
+/* 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;
+ 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 (*(pc + 0) == 0x24021017)
+ {
+ struct sigframe {
+ u_int32_t trampoline[2];
+ struct sigcontext sigctx;
+ } *rt_ = context->ra;
+ sc = &rt_->sigctx;
+ }
+ else if (*(pc + 0) == 0x24021061)
+ {
+ struct rt_sigframe {
+ u_int32_t trampoline[2];
+ struct siginfo info;
+ _sig_ucontext_t uc;
+ } *rt_ = context->ra;
+ sc = &rt_->uc.uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = (_Unwind_Ptr)sc;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = STACK_POINTER_REGNUM;
+ fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+ 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]) - new_cfa;
+ }
+ fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET;
+ fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset
+ = (_Unwind_Ptr)&(sc->sc_pc) - new_cfa;
+ fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
+
+ return _URC_NO_REASON;
+}
+#endif
%{!shared: %{pthread:-lpthread} \
%{profile:-lc_p} %{!profile: -lc}}"
-#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. */
-#ifdef IN_LIBGCC2
-#include <signal.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;
-
-#endif /* IN_LIBGCC2 */
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- u_int32_t *pc_ = (u_int32_t *) (CONTEXT)->ra; \
- struct sigcontext *sc_; \
- _Unwind_Ptr new_cfa_; \
- int i_; \
- \
- /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ \
- /* 0000000c syscall */ \
- /* or */ \
- /* 24021017 li v0, 0x1017 (sigreturn) */ \
- /* 0000000c syscall */ \
- if (*(pc_ + 1) != 0x0000000c) \
- break; \
- if (*(pc_ + 0) == 0x24021017) \
- { \
- struct sigframe { \
- u_int32_t trampoline[2]; \
- struct sigcontext sigctx; \
- } *rt_ = (CONTEXT)->ra; \
- sc_ = &rt_->sigctx; \
- } \
- else if (*(pc_ + 0) == 0x24021061) \
- { \
- struct rt_sigframe { \
- u_int32_t trampoline[2]; \
- struct siginfo info; \
- _sig_ucontext_t uc; \
- } *rt_ = (CONTEXT)->ra; \
- sc_ = &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = (_Unwind_Ptr)sc_; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = STACK_POINTER_REGNUM; \
- (FS)->cfa_offset = new_cfa_ - (_Unwind_Ptr) (CONTEXT)->cfa; \
- \
- 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_]) - new_cfa_; \
- } \
- (FS)->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset \
- = (_Unwind_Ptr)&(sc_->sc_pc) - new_cfa_; \
- (FS)->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN; \
- \
- goto SUCCESS; \
- } while (0)
-#endif
+#define MD_UNWIND_SUPPORT "config/mips/linux-unwind.h"
--- /dev/null
+/* DWARF2 EH unwinding support for PA Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* 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>
+
+/* 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
+ 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->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 30;
+ fs->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[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long) &sc->sc_iaoq[0] - new_cfa;
+ fs->retaddr_column = 2;
+ return _URC_NO_REASON;
+}
aligned(sizeof(func_ptr)))) \
= { (func_ptr) (-1) }
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#ifdef IN_LIBGCC2
-#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(CONTEXT, FS, SUCCESS) \
- do { \
- 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 \
- break; \
- if (pc[1] != 0x3414015a \
- || pc[2] != 0xe4008200 \
- || pc[3] != 0x08000240) \
- break; \
- \
- frame = (struct rt_sigframe *)(sp + off); \
- sc = &frame->uc.uc_mcontext; \
- \
- new_cfa = sc->sc_gr[30]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 30; \
- (FS)->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[2].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[2].loc.offset = (long) &sc->sc_iaoq[0] - new_cfa; \
- (FS)->retaddr_column = 2; \
- goto SUCCESS; \
- } while (0)
-
-#endif /* IN_LIBGCC2 */
+#define MD_UNWIND_SUPPORT "config/pa/linux-unwind.h"
--- /dev/null
+/* DWARF2 EH unwinding support for Darwin.
+ Copyright (C) 2004 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 2, or (at your option)
+ any later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combined
+ executable.)
+
+ 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 COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+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
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- { \
- extern bool _Unwind_fallback_frame_state_for \
- (struct _Unwind_Context *context, _Unwind_FrameState *fs); \
- \
- if (_Unwind_fallback_frame_state_for (CONTEXT, FS)) \
- goto SUCCESS; \
- }
+#define MD_UNWIND_SUPPORT "config/rs6000/darwin-unwind.h"
#define HAS_MD_FALLBACK_FRAME_STATE_FOR 1
--- /dev/null
+/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+/* This file defines our own versions of various kernel and user
+ structs, so that system headers are not needed, which otherwise
+ can make bootstrapping a new toolchain difficult. Do not use
+ these structs elsewhere; Many fields are missing, particularly
+ from the end of the structures. */
+
+struct gcc_pt_regs
+{
+ unsigned long gpr[32];
+ unsigned long nip;
+ unsigned long msr;
+ unsigned long orig_gpr3;
+ unsigned long ctr;
+ unsigned long link;
+};
+
+struct gcc_sigcontext
+{
+ unsigned long pad[7];
+ struct gcc_pt_regs *regs;
+};
+
+struct gcc_ucontext
+{
+#ifdef __powerpc64__
+ unsigned long pad[21];
+#else
+ unsigned long pad[5];
+#endif
+ struct gcc_sigcontext uc_mcontext;
+};
+
+#ifdef __powerpc64__
+
+enum { SIGNAL_FRAMESIZE = 128 };
+
+/* 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. */
+
+#define MD_FROB_UPDATE_CONTEXT frob_update_context
+
+static void
+frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ if (fs->regs.reg[2].how == REG_UNSAVED)
+ {
+ unsigned int *insn
+ = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
+ if (*insn == 0xE8410028)
+ _Unwind_SetGRPtr (context, 2, context->cfa + 40);
+ }
+}
+
+/* If PC is at a sigreturn trampoline, return a pointer to the
+ sigcontext. Otherwise return NULL. */
+
+static struct gcc_sigcontext *
+get_sigcontext (struct _Unwind_Context *context)
+{
+ const unsigned char *pc = context->ra;
+
+ /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
+ /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
+ if (*(unsigned int *) (pc+0) != 0x38210000 + SIGNAL_FRAMESIZE
+ || *(unsigned int *) (pc+8) != 0x44000002)
+ return NULL;
+ if (*(unsigned int *) (pc+4) == 0x38000077)
+ {
+ struct sigframe {
+ char gap[SIGNAL_FRAMESIZE];
+ struct gcc_sigcontext sigctx;
+ } *rt_ = context->cfa;
+ return &rt_->sigctx;
+ }
+ else if (*(unsigned int *) (pc+4) == 0x380000AC)
+ {
+ struct rt_sigframe {
+ int tramp[6];
+ void *pinfo;
+ struct gcc_ucontext *puc;
+ } *rt_ = (struct rt_sigframe *) pc;
+ return &rt_->puc->uc_mcontext;
+ }
+ return NULL;
+}
+
+#else /* !__powerpc64__ */
+
+enum { SIGNAL_FRAMESIZE = 64 };
+
+static struct gcc_sigcontext *
+get_sigcontext (struct _Unwind_Context *context)
+{
+ const unsigned char *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 (*(unsigned int *) (pc+4) != 0x44000002)
+ return NULL;
+ if (*(unsigned int *) (pc+0) == 0x38007777
+ || *(unsigned int *) (pc+0) == 0x38000077)
+ {
+ struct sigframe {
+ char gap[SIGNAL_FRAMESIZE];
+ struct gcc_sigcontext sigctx;
+ } *rt_ = context->cfa;
+ return &rt_->sigctx;
+ }
+ else if (*(unsigned int *) (pc+0) == 0x38006666
+ || *(unsigned int *) (pc+0) == 0x380000AC)
+ {
+ struct rt_sigframe {
+ char gap[SIGNAL_FRAMESIZE + 16];
+ char siginfo[128];
+ struct gcc_ucontext uc;
+ } *rt_ = context->cfa;
+ return &rt_->uc.uc_mcontext;
+ }
+ return NULL;
+}
+#endif
+
+/* 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)
+{
+ struct gcc_sigcontext *sc = get_sigcontext (context);
+ long new_cfa;
+ int i;
+
+ if (sc == NULL)
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->regs->gpr[STACK_POINTER_REGNUM];
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = STACK_POINTER_REGNUM;
+ fs->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)&(sc->regs->gpr[i]) - new_cfa;
+ }
+
+ fs->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET;
+ fs->regs.reg[LINK_REGISTER_REGNUM].loc.offset
+ = (long)&(sc->regs->link) - new_cfa;
+
+ fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
+ fs->regs.reg[ARG_POINTER_REGNUM].loc.offset
+ = (long)&(sc->regs->nip) - new_cfa;
+ fs->retaddr_column = ARG_POINTER_REGNUM;
+ return _URC_NO_REASON;
+}
#define TARGET_HAS_F_SETLKW
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#ifdef IN_LIBGCC2
-#include <signal.h>
-
-/* During the 2.5 kernel series the kernel ucontext was changed, but
- the new layout is compatible with the old one, so we just define
- and use the old one here for simplicity and compatibility. */
-
-struct kernel_old_ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext_struct uc_mcontext;
- sigset_t uc_sigmask;
-};
-
-enum { SIGNAL_FRAMESIZE = 64 };
-#endif
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- struct sigcontext *sc_; \
- long new_cfa_; \
- int i_; \
- \
- /* 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 (*(unsigned int *) (pc_+4) != 0x44000002) \
- break; \
- if (*(unsigned int *) (pc_+0) == 0x38007777 \
- || *(unsigned int *) (pc_+0) == 0x38000077) \
- { \
- struct sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- struct sigcontext sigctx; \
- } *rt_ = (CONTEXT)->cfa; \
- sc_ = &rt_->sigctx; \
- } \
- else if (*(unsigned int *) (pc_+0) == 0x38006666 \
- || *(unsigned int *) (pc_+0) == 0x380000AC) \
- { \
- struct rt_sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- unsigned long _unused[2]; \
- struct siginfo *pinfo; \
- void *puc; \
- struct siginfo info; \
- struct kernel_old_ucontext uc; \
- } *rt_ = (CONTEXT)->cfa; \
- sc_ = &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = STACK_POINTER_REGNUM; \
- (FS)->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)&(sc_->regs->gpr[i_]) - new_cfa_; \
- } \
- \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
- = (long)&(sc_->regs->link) - new_cfa_; \
- \
- (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[CR0_REGNO].loc.offset \
- = (long)&(sc_->regs->nip) - new_cfa_; \
- (FS)->retaddr_column = CR0_REGNO; \
- goto SUCCESS; \
- } while (0)
-
+#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
#define OS_MISSING_POWERPC64 1
#define USE_LD_AS_NEEDED 1
#endif
-#ifdef IN_LIBGCC2
-
-/* This file defines our own versions of various kernel and user
- structs, so that system headers are not needed, which otherwise
- can make bootstrapping a new toolchain difficult. Do not use
- these structs elsewhere; Many fields are missing, particularly
- from the end of the structures. */
-
-struct gcc_pt_regs
-{
- unsigned long gpr[32];
- unsigned long nip;
- unsigned long msr;
- unsigned long orig_gpr3;
- unsigned long ctr;
- unsigned long link;
-};
-
-struct gcc_sigcontext
-{
- unsigned long pad[7];
- struct gcc_pt_regs *regs;
-};
-
-struct gcc_ucontext
-{
-#ifdef __powerpc64__
- unsigned long pad[21];
-#else
- unsigned long pad[5];
-#endif
- struct gcc_sigcontext uc_mcontext;
-};
-
-#ifdef __powerpc64__
-
-enum { SIGNAL_FRAMESIZE = 128 };
-
-/* 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. */
-
-#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \
- do { \
- if ((FS)->regs.reg[2].how == REG_UNSAVED) \
- { \
- unsigned int *insn \
- = (unsigned int *) \
- _Unwind_GetGR ((CTX), LINK_REGISTER_REGNUM); \
- if (*insn == 0xE8410028) \
- _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \
- } \
- } while (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(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- struct gcc_sigcontext *sc_; \
- long new_cfa_; \
- int i_; \
- \
- /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ \
- /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ \
- if (*(unsigned int *) (pc_+0) != 0x38210000 + SIGNAL_FRAMESIZE \
- || *(unsigned int *) (pc_+8) != 0x44000002) \
- break; \
- if (*(unsigned int *) (pc_+4) == 0x38000077) \
- { \
- struct sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- struct gcc_sigcontext sigctx; \
- } *rt_ = (CONTEXT)->cfa; \
- sc_ = &rt_->sigctx; \
- } \
- else if (*(unsigned int *) (pc_+4) == 0x380000AC) \
- { \
- struct rt_sigframe { \
- int tramp[6]; \
- void *pinfo; \
- struct gcc_ucontext *puc; \
- } *rt_ = (struct rt_sigframe *) pc_; \
- sc_ = &rt_->puc->uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = STACK_POINTER_REGNUM; \
- (FS)->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)&(sc_->regs->gpr[i_]) - new_cfa_; \
- } \
- \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
- = (long)&(sc_->regs->link) - new_cfa_; \
- \
- (FS)->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset \
- = (long)&(sc_->regs->nip) - new_cfa_; \
- (FS)->retaddr_column = ARG_POINTER_REGNUM; \
- goto SUCCESS; \
- } while (0)
-
-#else /* !__powerpc64__ */
-
-enum { SIGNAL_FRAMESIZE = 64 };
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- struct gcc_sigcontext *sc_; \
- long new_cfa_; \
- int i_; \
- \
- /* 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 (*(unsigned int *) (pc_+4) != 0x44000002) \
- break; \
- if (*(unsigned int *) (pc_+0) == 0x38007777 \
- || *(unsigned int *) (pc_+0) == 0x38000077) \
- { \
- struct sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- struct gcc_sigcontext sigctx; \
- } *rt_ = (CONTEXT)->cfa; \
- sc_ = &rt_->sigctx; \
- } \
- else if (*(unsigned int *) (pc_+0) == 0x38006666 \
- || *(unsigned int *) (pc_+0) == 0x380000AC) \
- { \
- struct rt_sigframe { \
- char gap[SIGNAL_FRAMESIZE + 16]; \
- char siginfo[128]; \
- struct gcc_ucontext uc; \
- } *rt_ = (CONTEXT)->cfa; \
- sc_ = &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = STACK_POINTER_REGNUM; \
- (FS)->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)&(sc_->regs->gpr[i_]) - new_cfa_; \
- } \
- \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
- = (long)&(sc_->regs->link) - new_cfa_; \
- \
- (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[CR0_REGNO].loc.offset \
- = (long)&(sc_->regs->nip) - new_cfa_; \
- (FS)->retaddr_column = CR0_REGNO; \
- goto SUCCESS; \
- } while (0)
-
-#endif
-#endif /* LIBGCC2 */
+#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
#define OS_MISSING_POWERPC64 !TARGET_64BIT
--- /dev/null
+/* DWARF2 EH unwinding support for S/390 Linux.
+ Copyright (C) 2004 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 2, 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 COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* 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 = NULL;
+
+ /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */
+ if (pc[0] != 0x0a || (pc[1] != 119 && pc[1] != 173))
+ return _URC_END_OF_STACK;
+
+ /* New-style RT frame:
+ retcode + alignment (8 bytes)
+ siginfo (128 bytes)
+ ucontext (contains sigregs) */
+ if (context->ra == context->cfa)
+ {
+ 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);
+ }
+
+ /* Old-style RT frame and all non-RT frames:
+ old signal mask (8 bytes)
+ pointer to sigregs */
+ else
+ {
+ regs = *(sigregs_ **)(context->cfa + 8);
+
+ /* Recent kernels store the signal number immediately after
+ the sigregs; old kernels have the return trampoline at
+ this location. */
+ if ((void *)(regs + 1) != context->ra)
+ signo = (int *)(regs + 1);
+ }
+
+ new_cfa = regs->gprs[15] + 16*sizeof(long) + 32;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 15;
+ fs->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;
+
+ /* If we got a SIGSEGV or a SIGBUS, the PSW address points *to*
+ the faulting instruction, not after it. This causes the logic
+ in unwind-dw2.c that decrements the RA to determine the correct
+ CFI region to get confused. To fix that, we *increment* the RA
+ here in that case. Note that we cannot modify the RA in place,
+ and the frame state wants a *pointer*, not a value; thus we put
+ the modified RA value into the unused register 33 slot of FS and
+ have the register 32 save address point to that slot.
+
+ Unfortunately, for regular signals on old kernels, we don't know
+ the signal number. We default to not fiddling with the RA;
+ that can fail in rare cases. Upgrade your kernel. */
+
+ if (signo && (*signo == 11 || *signo == 7))
+ {
+ fs->regs.reg[33].loc.exp =
+ (unsigned char *)regs->psw_addr + 1;
+ fs->regs.reg[32].loc.offset =
+ (long)&fs->regs.reg[33].loc.exp - new_cfa;
+ }
+
+ return _URC_NO_REASON;
+}
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-/* 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(CONTEXT, FS, SUCCESS) \
- do { \
- 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_ = NULL; \
- \
- /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ \
- if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173)) \
- break; \
- \
- /* New-style RT frame: \
- retcode + alignment (8 bytes) \
- siginfo (128 bytes) \
- ucontext (contains sigregs) */ \
- if ((CONTEXT)->ra == (CONTEXT)->cfa) \
- { \
- 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); \
- } \
- \
- /* Old-style RT frame and all non-RT frames: \
- old signal mask (8 bytes) \
- pointer to sigregs */ \
- else \
- { \
- regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8); \
- \
- /* Recent kernels store the signal number immediately after \
- the sigregs; old kernels have the return trampoline at \
- this location. */ \
- if ((void *)(regs_ + 1) != (CONTEXT)->ra) \
- signo_ = (int *)(regs_ + 1); \
- } \
- \
- new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 15; \
- (FS)->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; \
- \
- /* If we got a SIGSEGV or a SIGBUS, the PSW address points *to* \
- the faulting instruction, not after it. This causes the logic \
- in unwind-dw2.c that decrements the RA to determine the correct \
- CFI region to get confused. To fix that, we *increment* the RA \
- here in that case. Note that we cannot modify the RA in place, \
- and the frame state wants a *pointer*, not a value; thus we put \
- the modified RA value into the unused register 33 slot of FS and \
- have the register 32 save address point to that slot. \
- \
- Unfortunately, for regular signals on old kernels, we don't know \
- the signal number. We default to not fiddling with the RA; \
- that can fail in rare cases. Upgrade your kernel. */ \
- \
- if (signo_ && (*signo_ == 11 || *signo_ == 7)) \
- { \
- (FS)->regs.reg[33].loc.exp = \
- (unsigned char *)regs_->psw_addr + 1; \
- (FS)->regs.reg[32].loc.offset = \
- (long)&(FS)->regs.reg[33].loc.exp - new_cfa_; \
- } \
- \
- goto SUCCESS; \
- } while (0)
+#define MD_UNWIND_SUPPORT "config/s390/linux-unwind.h"
#endif
--- /dev/null
+/* DWARF2 EH unwinding support for SH Linux.
+ Copyright (C) 2004 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 2, 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 this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* 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>
+#include "insn-constants.h"
+
+# if defined (__SH5__)
+#define SH_DWARF_FRAME_GP0 0
+#define SH_DWARF_FRAME_FP0 (__SH5__ == 32 ? 245 : 77)
+#define SH_DWARF_FRAME_XD0 289
+#define SH_DWARF_FRAME_BT0 68
+#define SH_DWARF_FRAME_PR 241
+#define SH_DWARF_FRAME_PR_MEDIA 18
+#define SH_DWARF_FRAME_GBR 238
+#define SH_DWARF_FRAME_MACH 239
+#define SH_DWARF_FRAME_MACL 240
+#define SH_DWARF_FRAME_PC 64
+#define SH_DWARF_FRAME_SR 65
+#define SH_DWARF_FRAME_FPUL 244
+#define SH_DWARF_FRAME_FPSCR 243
+#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 19
+#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__)
+/* MD_FALLBACK_FRAME_STATE_FOR is not yet defined for SHMEDIA. */
+#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;
+ sc = (struct sigcontext *) &rt_->uc.uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->sc_regs[15];
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 15;
+ fs->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[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[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
+
+ /* The unwinder expects the PC to point to the following insn,
+ whereas the kernel returns the address of the actual
+ faulting insn. */
+ sc->sc_pc += 2;
+ 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;
+ return _URC_NO_REASON;
+}
+#endif /* defined (__SH5__) */
fprintf (STREAM, "2:\tlds.l\t@r15+,pr\n"); \
} while (0)
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#ifdef IN_LIBGCC2
-#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 (__SH5__ == 32 ? 245 : 77)
-#define SH_DWARF_FRAME_XD0 289
-#define SH_DWARF_FRAME_BT0 68
-#define SH_DWARF_FRAME_PR 241
-#define SH_DWARF_FRAME_PR_MEDIA 18
-#define SH_DWARF_FRAME_GBR 238
-#define SH_DWARF_FRAME_MACH 239
-#define SH_DWARF_FRAME_MACL 240
-#define SH_DWARF_FRAME_PC 64
-#define SH_DWARF_FRAME_SR 65
-#define SH_DWARF_FRAME_FPUL 244
-#define SH_DWARF_FRAME_FPSCR 243
-#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 19
-#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__)
-/* MD_FALLBACK_FRAME_STATE_FOR is not yet defined for SHMEDIA. */
-#else /* defined (__SH5__) */
-
-#if defined (__SH3E__) || defined (__SH4__)
-#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA) \
- do { \
- int i_, r_; \
- \
- 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_]) - (CFA); \
- } \
- \
- r_ = SH_DWARF_FRAME_XD0 ; \
- for (i_ = 0; i_ < 8; i_++) \
- { \
- (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_].loc.offset \
- = (long)&((SC)->sc_xfpregs[2*i_]) - (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) - (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) - (CFA); \
- } while (0)
-
-#else
-#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA)
-#endif
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- struct sigcontext *sc_; \
- long new_cfa_; \
- int i_; \
- \
- /* 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; \
- sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->sc_regs[15]; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 15; \
- (FS)->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_; \
- \
- SH_FALLBACK_FRAME_FLOAT_STATE(sc_, (FS), new_cfa_); \
- \
- /* The unwinder expects the PC to point to the following insn, \
- whereas the kernel returns the address of the actual \
- faulting insn. */ \
- sc_->sc_pc += 2; \
- (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; \
- goto SUCCESS; \
- } while (0)
-
-#endif /* defined (__SH5__) */
-#endif /* IN_LIBGCC2 */
+#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
--- /dev/null
+/* DWARF2 EH unwinding support for SPARC Linux.
+ Copyright 2004 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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+/* Handle multilib correctly. */
+#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 new_cfa, i;
+ long regs_off, fpu_save_off;
+ long this_cfa, fpu_save;
+
+ 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);
+ this_cfa = (long) context->cfa;
+ new_cfa = *(long *)((context->cfa) + (regs_off + (14 * 8)));
+ new_cfa += 2047; /* Stack bias */
+ fpu_save = *(long *)((this_cfa) + (fpu_save_off));
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 14;
+ fs->cfa_offset = new_cfa - (long) context->cfa;
+ for (i = 1; i < 16; ++i)
+ {
+ 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;
+ }
+ }
+ /* Stick return address into %g0, same trick Alpha uses. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset =
+ this_cfa + (regs_off + (16 * 8) + 8) - new_cfa;
+ fs->retaddr_column = 0;
+ return _URC_NO_REASON;
+}
+
+#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 new_cfa, i, oldstyle;
+ int regs_off, fpu_save_off;
+ int fpu_save, this_cfa;
+
+ if (pc[1] != 0x91d02010) /* ta 0x10 */
+ return _URC_END_OF_STACK;
+ if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */
+ oldstyle = 1;
+ else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */
+ oldstyle = 0;
+ else
+ return _URC_END_OF_STACK;
+ if (oldstyle)
+ {
+ 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);
+ }
+ this_cfa = (int) context->cfa;
+ new_cfa = *(int *)((context->cfa) + (regs_off+(4*4)+(14 * 4)));
+ fpu_save = *(int *)((this_cfa) + (fpu_save_off));
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 14;
+ fs->cfa_offset = new_cfa - (int) context->cfa;
+ for (i = 1; i < 16; ++i)
+ {
+ if (i == 14)
+ 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;
+ }
+ }
+ /* Stick return address into %g0, same trick Alpha uses. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = this_cfa+(regs_off+4)-new_cfa;
+ fs->retaddr_column = 0;
+ return _URC_NO_REASON;
+}
+
+#endif
#define USE_LD_AS_NEEDED 1
#endif
-/* 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(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- int new_cfa_, i_, oldstyle_; \
- int regs_off_, fpu_save_off_; \
- int fpu_save_, this_cfa_; \
- \
- if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
- break; \
- if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
- oldstyle_ = 1; \
- else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
- oldstyle_ = 0; \
- else \
- break; \
- if (oldstyle_) \
- { \
- 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); \
- } \
- this_cfa_ = (int) (CONTEXT)->cfa; \
- new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
- fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- if (i_ == 14) \
- 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_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
+#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h"
#define USE_LD_AS_NEEDED 1
#endif
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-/* Handle multilib correctly. */
-#if defined(__arch64__)
-/* 64-bit SPARC version */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- long new_cfa_, i_; \
- long regs_off_, fpu_save_off_; \
- long this_cfa_, fpu_save_; \
- \
- if (pc_[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ \
- || pc_[1] != 0x91d0206d) /* ta 0x6d */ \
- break; \
- regs_off_ = 192 + 128; \
- fpu_save_off_ = regs_off_ + (16 * 8) + (3 * 8) + (2 * 4); \
- this_cfa_ = (long) (CONTEXT)->cfa; \
- new_cfa_ = *(long *)(((CONTEXT)->cfa) + (regs_off_ + (14 * 8))); \
- new_cfa_ += 2047; /* Stack bias */ \
- fpu_save_ = *(long *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- (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_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = \
- this_cfa_ + (regs_off_ + (16 * 8) + 8) - new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
-#else
-/* 32-bit SPARC version */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- int new_cfa_, i_, oldstyle_; \
- int regs_off_, fpu_save_off_; \
- int fpu_save_, this_cfa_; \
- \
- if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
- break; \
- if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
- oldstyle_ = 1; \
- else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
- oldstyle_ = 0; \
- else \
- break; \
- if (oldstyle_) \
- { \
- 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); \
- } \
- this_cfa_ = (int) (CONTEXT)->cfa; \
- new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
- fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- if (i_ == 14) \
- 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_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
-#endif
+#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h"
to be emitted.
@end defmac
-@defmac MD_FALLBACK_FRAME_STATE_FOR (@var{context}, @var{fs}, @var{success})
+@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
available. The most common reason to implement this macro is to unwind
@var{fs} is an @code{_Unwind_FrameState}. Examine @code{context->ra}
for the address of the code being executed and @code{context->cfa} for
the stack pointer value. If the frame can be decoded, the register save
-addresses should be updated in @var{fs} and the macro should branch to
-@var{success}. If the frame cannot be decoded, the macro should do
-nothing.
+addresses should be updated in @var{fs} and the macro should evaluate to
+@code{_URC_NO_REASON}. If the frame cannot be decoded, the macro should
+evaluate to @code{_URC_END_OF_STACK}.
For proper signal handling in Java this macro is accompanied by
@code{MAKE_THROW_FRAME}, defined in @file{libjava/include/*-signal.h} headers.
#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
#endif
-/* A target can do some update context frobbing. */
-#ifndef MD_FROB_UPDATE_CONTEXT
-#define MD_FROB_UPDATE_CONTEXT(CTX, FS) do { } while (0)
-#endif
-
/* This is the register and unwind state for a particular frame. This
provides the information necessary to unwind up past a frame and return
to its caller. */
return (_Unwind_Ptr) context->bases.tbase;
}
#endif
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
\f
/* Extract any interesting information from the CIE for the translation
unit F belongs to. Return a pointer to the byte after the augmentation,
fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
if (fde == NULL)
{
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
/* Couldn't find frame unwind info for this function. Try a
target-specific fallback mechanism. This will necessarily
not provide a personality routine or LSDA. */
-#ifdef MD_FALLBACK_FRAME_STATE_FOR
- MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
- return _URC_END_OF_STACK;
- success:
- return _URC_NO_REASON;
+ return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
#else
return _URC_END_OF_STACK;
#endif
break;
}
+#ifdef MD_FROB_UPDATE_CONTEXT
MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
}
/* CONTEXT describes the unwind state for a frame, and FS describes the FDE