From: Alan Modra Date: Wed, 8 Sep 2004 00:17:19 +0000 (+0000) Subject: tm.texi (MD_UNWIND_SUPPORT): Document. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8662eb14c0ef6531d7086ec08f5e52b87c472ede;p=gcc.git tm.texi (MD_UNWIND_SUPPORT): Document. * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3938e7a5695..3177547be52 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2004-09-08 Alan Modra + + * 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 * cse.c (fold_rtx): Avoid building of diff --git a/gcc/config/alpha/gnu.h b/gcc/config/alpha/gnu.h index 40348c60abb..b9bfceafd0a 100644 --- a/gcc/config/alpha/gnu.h +++ b/gcc/config/alpha/gnu.h @@ -23,4 +23,4 @@ %{!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 diff --git a/gcc/config/alpha/linux-unwind.h b/gcc/config/alpha/linux-unwind.h new file mode 100644 index 00000000000..ec0af1a6bee --- /dev/null +++ b/gcc/config/alpha/linux-unwind.h @@ -0,0 +1,74 @@ +/* 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 +#include + +#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state + +static _Unwind_Reason_Code +alpha_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + struct sigcontext *sc; + long new_cfa, i; + + if (pc[0] != 0x47fe0410 /* mov $30,$16 */ + || pc[2] != 0x00000083 /* callsys */) + return _URC_END_OF_STACK; + if (context->cfa == 0) + return _URC_END_OF_STACK; + if (pc[1] == 0x201f0067) /* lda $0,NR_sigreturn */ + sc = context->cfa; + else if (pc[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */ + { + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + sc = &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + new_cfa = sc->sc_regs[30]; + fs->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; +} diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h index e2a16dff3db..e9a0e900580 100644 --- a/gcc/config/alpha/linux.h +++ b/gcc/config/alpha/linux.h @@ -76,55 +76,4 @@ Boston, MA 02111-1307, USA. */ #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 -#include -#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" diff --git a/gcc/config/alpha/vms-unwind.h b/gcc/config/alpha/vms-unwind.h new file mode 100644 index 00000000000..cafe72a6ae1 --- /dev/null +++ b/gcc/config/alpha/vms-unwind.h @@ -0,0 +1,72 @@ +/* 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 + +#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<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; +} diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h index b062d616c00..39fce013c87 100644 --- a/gcc/config/alpha/vms.h +++ b/gcc/config/alpha/vms.h @@ -318,55 +318,7 @@ do { \ #define LINK_EH_SPEC "vms-dwarf2eh.o%s " -#ifdef IN_LIBGCC2 -#include - -#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<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 diff --git a/gcc/config/i386/gnu.h b/gcc/config/i386/gnu.h index cc9994bcaed..ce80c9821fd 100644 --- a/gcc/config/i386/gnu.h +++ b/gcc/config/i386/gnu.h @@ -40,4 +40,4 @@ %{!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 diff --git a/gcc/config/i386/linux-unwind.h b/gcc/config/i386/linux-unwind.h new file mode 100644 index 00000000000..ecbce1d337c --- /dev/null +++ b/gcc/config/i386/linux-unwind.h @@ -0,0 +1,165 @@ +/* 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 +#include + +#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state + +static _Unwind_Reason_Code +x86_64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + + /* movq __NR_rt_sigreturn, %rax ; syscall */ + if (*(unsigned char *)(pc+0) == 0x48 + && *(unsigned long *)(pc+1) == 0x050f0000000fc0c7) + { + struct ucontext *uc_ = context->cfa; + 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 +#include + +#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state + +static _Unwind_Reason_Code +x86_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + + /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ + if (*(unsigned short *)(pc+0) == 0xb858 + && *(unsigned int *)(pc+2) == 119 + && *(unsigned short *)(pc+6) == 0x80cd) + sc = context->cfa + 4; + /* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ + else if (*(unsigned char *)(pc+0) == 0xb8 + && *(unsigned int *)(pc+1) == 173 + && *(unsigned short *)(pc+5) == 0x80cd) + { + struct rt_sigframe { + int sig; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + 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 */ diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h index 08b859ac310..e31c5114e93 100644 --- a/gcc/config/i386/linux.h +++ b/gcc/config/i386/linux.h @@ -181,72 +181,4 @@ Boston, MA 02111-1307, USA. */ #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 -#include - -#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" diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h index 98536c19bd3..4838cf8fa8e 100644 --- a/gcc/config/i386/linux64.h +++ b/gcc/config/i386/linux64.h @@ -69,128 +69,4 @@ Boston, MA 02111-1307, USA. */ #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 -#include -#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" diff --git a/gcc/config/ia64/linux-unwind.h b/gcc/config/ia64/linux-unwind.h new file mode 100644 index 00000000000..801597ce311 --- /dev/null +++ b/gcc/config/ia64/linux-unwind.h @@ -0,0 +1,185 @@ +/* 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 +#include + +#define IA64_GATE_AREA_START 0xa000000000000100LL +#define IA64_GATE_AREA_END 0xa000000000030000LL + +#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state + +static _Unwind_Reason_Code +ia64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + if (context->rp >= IA64_GATE_AREA_START + && context->rp < IA64_GATE_AREA_END) + { + struct sigframe { + char scratch[16]; + unsigned long sig_number; + struct siginfo *info; + struct sigcontext *sc; + } *frame_ = (struct sigframe *)context->psp; + struct sigcontext *sc = frame_->sc; + + /* Restore scratch registers in case the unwinder needs to + refer to a value stored in one of them. */ + { + int i; + + for (i = 2; i < 4; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 8; i < 12; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + for (i = 14; i < 32; i++) + context->ireg[i - 2].loc = &sc->sc_gr[i]; + } + + context->fpsr_loc = &(sc->sc_ar_fpsr); + context->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 */ diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h index 5c73b0c25ef..3d585609f61 100644 --- a/gcc/config/ia64/linux.h +++ b/gcc/config/ia64/linux.h @@ -55,161 +55,4 @@ do { \ #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 -#include - -#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" diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c index 692f07b1adf..4a4d65aaa20 100644 --- a/gcc/config/ia64/unwind-ia64.c +++ b/gcc/config/ia64/unwind-ia64.c @@ -44,6 +44,7 @@ #undef ENABLE_MALLOC_CHECKING #ifndef __USING_SJLJ_EXCEPTIONS__ + #define UNW_VER(x) ((x) >> 48) #define UNW_FLAG_MASK 0x0000ffff00000000 #define UNW_FLAG_OSMASK 0x0000f00000000000 @@ -1754,6 +1755,9 @@ _Unwind_GetBSP (struct _Unwind_Context *context) return (_Unwind_Ptr) context->bsp; } +#ifdef MD_UNWIND_SUPPORT +#include MD_UNWIND_SUPPORT +#endif static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) @@ -1777,7 +1781,8 @@ 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 @@ -1792,15 +1797,10 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) 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; diff --git a/gcc/config/mips/linux-unwind.h b/gcc/config/mips/linux-unwind.h new file mode 100644 index 00000000000..5c136c14109 --- /dev/null +++ b/gcc/config/mips/linux-unwind.h @@ -0,0 +1,93 @@ +/* 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 + +/* 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 diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h index a4765d494ee..be5c8d4d219 100644 --- a/gcc/config/mips/linux.h +++ b/gcc/config/mips/linux.h @@ -183,74 +183,4 @@ Boston, MA 02111-1307, USA. */ %{!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 - -/* 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" diff --git a/gcc/config/pa/linux-unwind.h b/gcc/config/pa/linux-unwind.h new file mode 100644 index 00000000000..41ec61caa9e --- /dev/null +++ b/gcc/config/pa/linux-unwind.h @@ -0,0 +1,115 @@ +/* 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 +#include + +/* Unfortunately, because of various bugs and changes to the kernel, + we have several cases to deal with. + + In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should + point directly at the beginning of the trampoline and struct rt_sigframe. + + In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and + (CONTEXT)->ra points at the 4th word in the trampoline structure. This + is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4. + + To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes + to get the beginning of the signal frame, and then check offsets 0, 4 + and 5 to see if we found the beginning of the trampoline. This will + tell us how to locate the sigcontext structure. + + Note that with a 2.4 64-bit kernel, the signal context is not properly + passed back to userspace so the unwind will not work correctly. */ + +#define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state + +static _Unwind_Reason_Code +pa32_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned long sp = (unsigned long)context->ra & ~63; + unsigned int *pc = (unsigned int *)sp; + unsigned long off; + _Unwind_Ptr new_cfa; + int i; + struct sigcontext *sc; + struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + } *frame; + + /* rt_sigreturn trampoline: + 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) + 3414015a ldi __NR_rt_sigreturn, %r20 + e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 + 08000240 nop */ + + if (pc[0] == 0x34190000 || pc[0] == 0x34190002) + off = 4*4; + else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) + { + pc += 4; + off = 10 * 4; + } + else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) + { + pc += 5; + off = 10 * 4; + } + else + 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; +} diff --git a/gcc/config/pa/pa32-linux.h b/gcc/config/pa/pa32-linux.h index 14cc2cf9159..07b680de88a 100644 --- a/gcc/config/pa/pa32-linux.h +++ b/gcc/config/pa/pa32-linux.h @@ -36,96 +36,4 @@ Boston, MA 02111-1307, USA. */ 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 -#include - -/* Unfortunately, because of various bugs and changes to the kernel, - we have several cases to deal with. - - In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should - point directly at the beginning of the trampoline and struct rt_sigframe. - - In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and - (CONTEXT)->ra points at the 4th word in the trampoline structure. This - is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4. - - To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes - to get the beginning of the signal frame, and then check offsets 0, 4 - and 5 to see if we found the beginning of the trampoline. This will - tell us how to locate the sigcontext structure. - - Note that with a 2.4 64-bit kernel, the signal context is not properly - passed back to userspace so the unwind will not work correctly. */ -#define MD_FALLBACK_FRAME_STATE_FOR(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" diff --git a/gcc/config/rs6000/darwin-unwind.h b/gcc/config/rs6000/darwin-unwind.h new file mode 100644 index 00000000000..e3d03262d5a --- /dev/null +++ b/gcc/config/rs6000/darwin-unwind.h @@ -0,0 +1,35 @@ +/* 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) diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 1e92d5fe2bf..44ae79ac38c 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -371,14 +371,7 @@ extern const char *darwin_one_byte_bool; #include #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 diff --git a/gcc/config/rs6000/linux-unwind.h b/gcc/config/rs6000/linux-unwind.h new file mode 100644 index 00000000000..bb4f0cf90db --- /dev/null +++ b/gcc/config/rs6000/linux-unwind.h @@ -0,0 +1,186 @@ +/* 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; +} diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index 83aef83a387..0f4d046e049 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -98,88 +98,6 @@ #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 - -/* 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 diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index e7b57d4f570..410f31ee49b 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -557,185 +557,6 @@ while (0) #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 diff --git a/gcc/config/s390/linux-unwind.h b/gcc/config/s390/linux-unwind.h new file mode 100644 index 00000000000..3713f1821a9 --- /dev/null +++ b/gcc/config/s390/linux-unwind.h @@ -0,0 +1,131 @@ +/* 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; +} diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h index 9dd07c71ef3..fc26f7a91a6 100644 --- a/gcc/config/s390/linux.h +++ b/gcc/config/s390/linux.h @@ -92,112 +92,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #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 diff --git a/gcc/config/sh/linux-unwind.h b/gcc/config/sh/linux-unwind.h new file mode 100644 index 00000000000..ed32e245cfa --- /dev/null +++ b/gcc/config/sh/linux-unwind.h @@ -0,0 +1,167 @@ +/* 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 +#include +#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__) */ diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h index b01b52d28db..1142b126946 100644 --- a/gcc/config/sh/linux.h +++ b/gcc/config/sh/linux.h @@ -147,159 +147,7 @@ do { \ 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 -#include -#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 diff --git a/gcc/config/sparc/linux-unwind.h b/gcc/config/sparc/linux-unwind.h new file mode 100644 index 00000000000..3ce967d9171 --- /dev/null +++ b/gcc/config/sparc/linux-unwind.h @@ -0,0 +1,150 @@ +/* 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 diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index 2ee6ad90513..788b1433dc3 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -228,66 +228,4 @@ do { \ #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" diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index 78d657c27ec..daf1653bfc7 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -366,121 +366,4 @@ do { \ #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" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index e21f72747ed..74d3b4df407 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3094,7 +3094,12 @@ of bytes that the format occupies, @var{addr} is the @code{SYMBOL_REF} 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 @@ -3105,9 +3110,9 @@ and @file{unwind-ia64.c}. @var{context} is an @code{_Unwind_Context}; @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. diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index db8f3f5e20a..eb36e207e2f 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -60,11 +60,6 @@ #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. */ @@ -252,6 +247,10 @@ _Unwind_GetTextRelBase (struct _Unwind_Context *context) return (_Unwind_Ptr) context->bases.tbase; } #endif + +#ifdef MD_UNWIND_SUPPORT +#include MD_UNWIND_SUPPORT +#endif /* Extract any interesting information from the CIE for the translation unit F belongs to. Return a pointer to the byte after the augmentation, @@ -963,14 +962,11 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) 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 @@ -1176,7 +1172,9 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) 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