mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 13:31:04 +08:00
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
This commit is contained in:
parent
a9e10feb68
commit
8662eb14c0
@ -1,3 +1,37 @@
|
||||
2004-09-08 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* doc/tm.texi (MD_UNWIND_SUPPORT): Document.
|
||||
(MD_FALLBACK_FRAME_STATE_FOR): Update.
|
||||
* unwind-dw2.c (MD_UNWIND_SUPPORT): #include if defined.
|
||||
(uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
|
||||
(MD_FROB_UPDATE_CONTEXT): Remove default.
|
||||
(uw_update_context_1): Instead #ifdef invocation.
|
||||
* config/ia64/unwind-ia64.c (MD_UNWIND_SUPPORT): #include if defined.
|
||||
(uw_frame_state_for): Adjust MD_FALLBACK_FRAME_STATE_FOR invocation.
|
||||
* config/alpha/gnu.h (MD_FALLBACK_FRAME_STATE_FOR): Don't undef.
|
||||
(MD_UNWIND_SUPPORT): Undefine this instead.
|
||||
* config/i386/gnu.h: Likewise.
|
||||
* config/alpha/linux-unwind.h: New file, macro converted to
|
||||
function, extracted from..
|
||||
* config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): ..this.
|
||||
(MD_UNWIND_SUPPORT): Define.
|
||||
* config/alpha/vms-unwind.h, config/alpha/vms.h: Likewise.
|
||||
* config/i386/linux-unwind.h, config/i386/linux.h,
|
||||
config/i386/linux64.h: Likewise.
|
||||
* config/ia64/linux-unwind.h, config/ia64/linux.h: Likewise.
|
||||
MD_HANDLE_UNWABI too.
|
||||
* config/mips/linux-unwind.h, config/mips/linux.h: Likewise.
|
||||
* config/pa/linux-unwind.h, config/pa/pa32-linux.h: Likewise.
|
||||
* config/rs6000/darwin-unwind.h, config/rs6000/darwin.h: Likewise.
|
||||
* config/s390/linux-unwind.h, config/s390/linux.h: Likewise.
|
||||
* config/sparc/linux-unwind.h, config/sparc/linux.h,
|
||||
config/sparc/linux64.h: Likewise.
|
||||
* config/sh/linux-unwind.h, config/sh/linux.h: Likewise, but merge
|
||||
SH_FALLBACK_FRAME_FLOAT_STATE into sh_fallback_frame_state.
|
||||
* config/rs6000/linux-unwind.h, config/rs6000/linux.h,
|
||||
config/rs6000/linux64.h: Likewise. Split out get_sigcontext
|
||||
function. Use ARG_POINTER_REGNUM for 32-bit temp reg too.
|
||||
|
||||
2004-09-07 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cse.c (fold_rtx): Avoid building of
|
||||
|
@ -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
|
||||
|
74
gcc/config/alpha/linux-unwind.h
Normal file
74
gcc/config/alpha/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
alpha_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
unsigned int *pc = context->ra;
|
||||
struct sigcontext *sc;
|
||||
long new_cfa, i;
|
||||
|
||||
if (pc[0] != 0x47fe0410 /* mov $30,$16 */
|
||||
|| pc[2] != 0x00000083 /* callsys */)
|
||||
return _URC_END_OF_STACK;
|
||||
if (context->cfa == 0)
|
||||
return _URC_END_OF_STACK;
|
||||
if (pc[1] == 0x201f0067) /* lda $0,NR_sigreturn */
|
||||
sc = context->cfa;
|
||||
else if (pc[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */
|
||||
{
|
||||
struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
} *rt_ = context->cfa;
|
||||
sc = &rt_->uc.uc_mcontext;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
new_cfa = sc->sc_regs[30];
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->cfa_reg = 30;
|
||||
fs->cfa_offset = new_cfa - (long) context->cfa;
|
||||
for (i = 0; i < 30; ++i)
|
||||
{
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i].loc.offset
|
||||
= (long)&sc->sc_regs[i] - new_cfa;
|
||||
}
|
||||
for (i = 0; i < 31; ++i)
|
||||
{
|
||||
fs->regs.reg[i+32].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i+32].loc.offset
|
||||
= (long)&sc->sc_fpregs[i] - new_cfa;
|
||||
}
|
||||
fs->regs.reg[64].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa;
|
||||
fs->retaddr_column = 64;
|
||||
return _URC_NO_REASON;
|
||||
}
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
#endif
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned int *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_, i_; \
|
||||
\
|
||||
if (pc_[0] != 0x47fe0410 /* mov $30,$16 */ \
|
||||
|| pc_[2] != 0x00000083 /* callsys */) \
|
||||
break; \
|
||||
if ((CONTEXT)->cfa == 0) \
|
||||
break; \
|
||||
if (pc_[1] == 0x201f0067) /* lda $0,NR_sigreturn */ \
|
||||
sc_ = (CONTEXT)->cfa; \
|
||||
else if (pc_[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */ \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
struct siginfo info; \
|
||||
struct ucontext uc; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
new_cfa_ = sc_->sc_regs[30]; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 30; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
for (i_ = 0; i_ < 30; ++i_) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset \
|
||||
= (long)&sc_->sc_regs[i_] - new_cfa_; \
|
||||
} \
|
||||
for (i_ = 0; i_ < 31; ++i_) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_+32].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_+32].loc.offset \
|
||||
= (long)&sc_->sc_fpregs[i_] - new_cfa_; \
|
||||
} \
|
||||
(FS)->regs.reg[64].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[64].loc.offset = (long)&sc_->sc_pc - new_cfa_; \
|
||||
(FS)->retaddr_column = 64; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
#define MD_UNWIND_SUPPORT "config/alpha/linux-unwind.h"
|
||||
|
72
gcc/config/alpha/vms-unwind.h
Normal file
72
gcc/config/alpha/vms-unwind.h
Normal file
@ -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 <pdscdef.h>
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
alpha_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
PDSCDEF *pv = *((PDSCDEF **) context->reg [29]);
|
||||
|
||||
if (pv && ((long) pv & 0x7) == 0) /* low bits 0 means address */
|
||||
pv = *(PDSCDEF **) pv;
|
||||
|
||||
if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_STACK))
|
||||
{
|
||||
int i, j;
|
||||
|
||||
fs->cfa_offset = pv->pdsc$l_size;
|
||||
fs->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
|
||||
fs->retaddr_column = 26;
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->regs.reg[27].loc.offset = -pv->pdsc$l_size;
|
||||
fs->regs.reg[27].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[26].loc.offset
|
||||
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset);
|
||||
fs->regs.reg[26].how = REG_SAVED_OFFSET;
|
||||
|
||||
for (i = 0, j = 0; i < 32; i++)
|
||||
if (1<<i & pv->pdsc$l_ireg_mask)
|
||||
{
|
||||
fs->regs.reg[i].loc.offset
|
||||
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset - 8 * ++j);
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
}
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
else if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_REGISTER))
|
||||
{
|
||||
fs->cfa_offset = pv->pdsc$l_size;
|
||||
fs->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
|
||||
fs->retaddr_column = 26;
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->regs.reg[26].loc.reg = pv->pdsc$b_save_ra;
|
||||
fs->regs.reg[26].how = REG_SAVED_REG;
|
||||
fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp;
|
||||
fs->regs.reg[29].how = REG_SAVED_REG;
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
@ -318,55 +318,7 @@ do { \
|
||||
|
||||
#define LINK_EH_SPEC "vms-dwarf2eh.o%s "
|
||||
|
||||
#ifdef IN_LIBGCC2
|
||||
#include <pdscdef.h>
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
PDSCDEF *pv = *((PDSCDEF **) (CONTEXT)->reg [29]); \
|
||||
\
|
||||
if (pv && ((long) pv & 0x7) == 0) /* low bits 0 means address */ \
|
||||
pv = *(PDSCDEF **) pv; \
|
||||
\
|
||||
if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_STACK)) \
|
||||
{ \
|
||||
int i, j; \
|
||||
\
|
||||
(FS)->cfa_offset = pv->pdsc$l_size; \
|
||||
(FS)->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; \
|
||||
(FS)->retaddr_column = 26; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->regs.reg[27].loc.offset = -pv->pdsc$l_size; \
|
||||
(FS)->regs.reg[27].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[26].loc.offset \
|
||||
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset); \
|
||||
(FS)->regs.reg[26].how = REG_SAVED_OFFSET; \
|
||||
\
|
||||
for (i = 0, j = 0; i < 32; i++) \
|
||||
if (1<<i & pv->pdsc$l_ireg_mask) \
|
||||
{ \
|
||||
(FS)->regs.reg[i].loc.offset \
|
||||
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset - 8 * ++j); \
|
||||
(FS)->regs.reg[i].how = REG_SAVED_OFFSET; \
|
||||
} \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
} \
|
||||
else if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_REGISTER)) \
|
||||
{ \
|
||||
(FS)->cfa_offset = pv->pdsc$l_size; \
|
||||
(FS)->cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; \
|
||||
(FS)->retaddr_column = 26; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->regs.reg[26].loc.reg = pv->pdsc$b_save_ra; \
|
||||
(FS)->regs.reg[26].how = REG_SAVED_REG; \
|
||||
(FS)->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; \
|
||||
(FS)->regs.reg[29].how = REG_SAVED_REG; \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define MD_UNWIND_SUPPORT "config/alpha/vms-unwind.h"
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
|
@ -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
|
||||
|
165
gcc/config/i386/linux-unwind.h
Normal file
165
gcc/config/i386/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
x86_64_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
unsigned char *pc = context->ra;
|
||||
struct sigcontext *sc;
|
||||
long new_cfa;
|
||||
|
||||
/* movq __NR_rt_sigreturn, %rax ; syscall */
|
||||
if (*(unsigned char *)(pc+0) == 0x48
|
||||
&& *(unsigned long *)(pc+1) == 0x050f0000000fc0c7)
|
||||
{
|
||||
struct ucontext *uc_ = context->cfa;
|
||||
sc = (struct sigcontext *) &uc_->uc_mcontext;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
new_cfa = sc->rsp;
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
/* Register 7 is rsp */
|
||||
fs->cfa_reg = 7;
|
||||
fs->cfa_offset = new_cfa - (long) context->cfa;
|
||||
|
||||
/* The SVR4 register numbering macros aren't usable in libgcc. */
|
||||
fs->regs.reg[0].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[0].loc.offset = (long)&sc->rax - new_cfa;
|
||||
fs->regs.reg[1].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[1].loc.offset = (long)&sc->rdx - new_cfa;
|
||||
fs->regs.reg[2].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[2].loc.offset = (long)&sc->rcx - new_cfa;
|
||||
fs->regs.reg[3].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[3].loc.offset = (long)&sc->rbx - new_cfa;
|
||||
fs->regs.reg[4].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[4].loc.offset = (long)&sc->rsi - new_cfa;
|
||||
fs->regs.reg[5].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[5].loc.offset = (long)&sc->rdi - new_cfa;
|
||||
fs->regs.reg[6].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[6].loc.offset = (long)&sc->rbp - new_cfa;
|
||||
fs->regs.reg[8].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[8].loc.offset = (long)&sc->r8 - new_cfa;
|
||||
fs->regs.reg[9].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[9].loc.offset = (long)&sc->r9 - new_cfa;
|
||||
fs->regs.reg[10].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[10].loc.offset = (long)&sc->r10 - new_cfa;
|
||||
fs->regs.reg[11].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[11].loc.offset = (long)&sc->r11 - new_cfa;
|
||||
fs->regs.reg[12].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[12].loc.offset = (long)&sc->r12 - new_cfa;
|
||||
fs->regs.reg[13].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[13].loc.offset = (long)&sc->r13 - new_cfa;
|
||||
fs->regs.reg[14].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[14].loc.offset = (long)&sc->r14 - new_cfa;
|
||||
fs->regs.reg[15].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[15].loc.offset = (long)&sc->r15 - new_cfa;
|
||||
fs->regs.reg[16].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa;
|
||||
fs->retaddr_column = 16;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
#else /* ifdef __x86_64__ */
|
||||
|
||||
/* There's no sys/ucontext.h for glibc 2.0, so no
|
||||
signal-turned-exceptions for them. There's also no configure-run for
|
||||
the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the
|
||||
target libc version macro should be enough. */
|
||||
#if !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
x86_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
unsigned char *pc = context->ra;
|
||||
struct sigcontext *sc;
|
||||
long new_cfa;
|
||||
|
||||
/* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */
|
||||
if (*(unsigned short *)(pc+0) == 0xb858
|
||||
&& *(unsigned int *)(pc+2) == 119
|
||||
&& *(unsigned short *)(pc+6) == 0x80cd)
|
||||
sc = context->cfa + 4;
|
||||
/* movl $__NR_rt_sigreturn,%eax ; int $0x80 */
|
||||
else if (*(unsigned char *)(pc+0) == 0xb8
|
||||
&& *(unsigned int *)(pc+1) == 173
|
||||
&& *(unsigned short *)(pc+5) == 0x80cd)
|
||||
{
|
||||
struct rt_sigframe {
|
||||
int sig;
|
||||
struct siginfo *pinfo;
|
||||
void *puc;
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
} *rt_ = context->cfa;
|
||||
sc = (struct sigcontext *) &rt_->uc.uc_mcontext;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
new_cfa = sc->esp;
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->cfa_reg = 4;
|
||||
fs->cfa_offset = new_cfa - (long) context->cfa;
|
||||
|
||||
/* The SVR4 register numbering macros aren't usable in libgcc. */
|
||||
fs->regs.reg[0].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[0].loc.offset = (long)&sc->eax - new_cfa;
|
||||
fs->regs.reg[3].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[3].loc.offset = (long)&sc->ebx - new_cfa;
|
||||
fs->regs.reg[1].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[1].loc.offset = (long)&sc->ecx - new_cfa;
|
||||
fs->regs.reg[2].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[2].loc.offset = (long)&sc->edx - new_cfa;
|
||||
fs->regs.reg[6].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[6].loc.offset = (long)&sc->esi - new_cfa;
|
||||
fs->regs.reg[7].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[7].loc.offset = (long)&sc->edi - new_cfa;
|
||||
fs->regs.reg[5].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[5].loc.offset = (long)&sc->ebp - new_cfa;
|
||||
fs->regs.reg[8].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[8].loc.offset = (long)&sc->eip - new_cfa;
|
||||
fs->retaddr_column = 8;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
#endif /* not glibc 2.0 */
|
||||
#endif /* ifdef __x86_64__ */
|
||||
#endif /* ifdef inhibit_libc */
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define REG_NAME(reg) reg
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned char *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_; \
|
||||
\
|
||||
/* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ \
|
||||
if (*(unsigned short *)(pc_+0) == 0xb858 \
|
||||
&& *(unsigned int *)(pc_+2) == 119 \
|
||||
&& *(unsigned short *)(pc_+6) == 0x80cd) \
|
||||
sc_ = (CONTEXT)->cfa + 4; \
|
||||
/* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ \
|
||||
else if (*(unsigned char *)(pc_+0) == 0xb8 \
|
||||
&& *(unsigned int *)(pc_+1) == 173 \
|
||||
&& *(unsigned short *)(pc_+5) == 0x80cd) \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
int sig; \
|
||||
struct siginfo *pinfo; \
|
||||
void *puc; \
|
||||
struct siginfo info; \
|
||||
struct ucontext uc; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = sc_->REG_NAME(esp); \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 4; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
\
|
||||
/* The SVR4 register numbering macros aren't usable in libgcc. */ \
|
||||
(FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[0].loc.offset = (long)&sc_->REG_NAME(eax) - new_cfa_; \
|
||||
(FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[3].loc.offset = (long)&sc_->REG_NAME(ebx) - new_cfa_; \
|
||||
(FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[1].loc.offset = (long)&sc_->REG_NAME(ecx) - new_cfa_; \
|
||||
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2].loc.offset = (long)&sc_->REG_NAME(edx) - new_cfa_; \
|
||||
(FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[6].loc.offset = (long)&sc_->REG_NAME(esi) - new_cfa_; \
|
||||
(FS)->regs.reg[7].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[7].loc.offset = (long)&sc_->REG_NAME(edi) - new_cfa_; \
|
||||
(FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[5].loc.offset = (long)&sc_->REG_NAME(ebp) - new_cfa_; \
|
||||
(FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[8].loc.offset = (long)&sc_->REG_NAME(eip) - new_cfa_; \
|
||||
(FS)->retaddr_column = 8; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
#endif /* not glibc 2.0 */
|
||||
#endif /* IN_LIBGCC2 */
|
||||
#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
|
||||
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned char *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_; \
|
||||
\
|
||||
/* movq __NR_rt_sigreturn, %rax ; syscall */ \
|
||||
if (*(unsigned char *)(pc_+0) == 0x48 \
|
||||
&& *(unsigned long *)(pc_+1) == 0x050f0000000fc0c7) \
|
||||
{ \
|
||||
struct ucontext *uc_ = (CONTEXT)->cfa; \
|
||||
sc_ = (struct sigcontext *) &uc_->uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = sc_->rsp; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
/* Register 7 is rsp */ \
|
||||
(FS)->cfa_reg = 7; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
\
|
||||
/* The SVR4 register numbering macros aren't usable in libgcc. */ \
|
||||
(FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[0].loc.offset = (long)&sc_->rax - new_cfa_; \
|
||||
(FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[1].loc.offset = (long)&sc_->rdx - new_cfa_; \
|
||||
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2].loc.offset = (long)&sc_->rcx - new_cfa_; \
|
||||
(FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[3].loc.offset = (long)&sc_->rbx - new_cfa_; \
|
||||
(FS)->regs.reg[4].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[4].loc.offset = (long)&sc_->rsi - new_cfa_; \
|
||||
(FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[5].loc.offset = (long)&sc_->rdi - new_cfa_; \
|
||||
(FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[6].loc.offset = (long)&sc_->rbp - new_cfa_; \
|
||||
(FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[8].loc.offset = (long)&sc_->r8 - new_cfa_; \
|
||||
(FS)->regs.reg[9].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[9].loc.offset = (long)&sc_->r9 - new_cfa_; \
|
||||
(FS)->regs.reg[10].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[10].loc.offset = (long)&sc_->r10 - new_cfa_; \
|
||||
(FS)->regs.reg[11].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[11].loc.offset = (long)&sc_->r11 - new_cfa_; \
|
||||
(FS)->regs.reg[12].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[12].loc.offset = (long)&sc_->r12 - new_cfa_; \
|
||||
(FS)->regs.reg[13].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[13].loc.offset = (long)&sc_->r13 - new_cfa_; \
|
||||
(FS)->regs.reg[14].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[14].loc.offset = (long)&sc_->r14 - new_cfa_; \
|
||||
(FS)->regs.reg[15].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[15].loc.offset = (long)&sc_->r15 - new_cfa_; \
|
||||
(FS)->regs.reg[16].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[16].loc.offset = (long)&sc_->rip - new_cfa_; \
|
||||
(FS)->retaddr_column = 16; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
#else /* ifdef __x86_64__ */
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned char *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_; \
|
||||
\
|
||||
/* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ \
|
||||
if (*(unsigned short *)(pc_+0) == 0xb858 \
|
||||
&& *(unsigned int *)(pc_+2) == 119 \
|
||||
&& *(unsigned short *)(pc_+6) == 0x80cd) \
|
||||
sc_ = (CONTEXT)->cfa + 4; \
|
||||
/* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ \
|
||||
else if (*(unsigned char *)(pc_+0) == 0xb8 \
|
||||
&& *(unsigned int *)(pc_+1) == 173 \
|
||||
&& *(unsigned short *)(pc_+5) == 0x80cd) \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
int sig; \
|
||||
struct siginfo *pinfo; \
|
||||
void *puc; \
|
||||
struct siginfo info; \
|
||||
struct ucontext uc; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = sc_->esp; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 4; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
\
|
||||
/* The SVR4 register numbering macros aren't usable in libgcc. */ \
|
||||
(FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_; \
|
||||
(FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_; \
|
||||
(FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_; \
|
||||
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_; \
|
||||
(FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_; \
|
||||
(FS)->regs.reg[7].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_; \
|
||||
(FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_; \
|
||||
(FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_; \
|
||||
(FS)->retaddr_column = 8; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
#endif /* ifdef __x86_64__ */
|
||||
#endif /* ifdef inhibit_libc */
|
||||
#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
|
||||
|
185
gcc/config/ia64/linux-unwind.h
Normal file
185
gcc/config/ia64/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define IA64_GATE_AREA_START 0xa000000000000100LL
|
||||
#define IA64_GATE_AREA_END 0xa000000000030000LL
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
ia64_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
if (context->rp >= IA64_GATE_AREA_START
|
||||
&& context->rp < IA64_GATE_AREA_END)
|
||||
{
|
||||
struct sigframe {
|
||||
char scratch[16];
|
||||
unsigned long sig_number;
|
||||
struct siginfo *info;
|
||||
struct sigcontext *sc;
|
||||
} *frame_ = (struct sigframe *)context->psp;
|
||||
struct sigcontext *sc = frame_->sc;
|
||||
|
||||
/* Restore scratch registers in case the unwinder needs to
|
||||
refer to a value stored in one of them. */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 2; i < 4; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
for (i = 8; i < 12; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
for (i = 14; i < 32; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
}
|
||||
|
||||
context->fpsr_loc = &(sc->sc_ar_fpsr);
|
||||
context->pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->lc_loc = &(sc->sc_ar_lc);
|
||||
context->unat_loc = &(sc->sc_ar_unat);
|
||||
context->br_loc[0] = &(sc->sc_br[0]);
|
||||
context->br_loc[6] = &(sc->sc_br[6]);
|
||||
context->br_loc[7] = &(sc->sc_br[7]);
|
||||
context->pr = sc->sc_pr;
|
||||
context->psp = sc->sc_gr[12];
|
||||
context->gp = sc->sc_gr[1];
|
||||
/* Signal frame doesn't have an associated reg. stack frame
|
||||
other than what we adjust for below. */
|
||||
fs -> no_reg_stack_frame = 1;
|
||||
|
||||
if (sc->sc_rbs_base)
|
||||
{
|
||||
/* Need to switch from alternate register backing store. */
|
||||
long ndirty, loadrs = sc->sc_loadrs >> 16;
|
||||
unsigned long alt_bspstore = context->bsp - loadrs;
|
||||
unsigned long bspstore;
|
||||
unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
|
||||
|
||||
ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
|
||||
(unsigned long *) context->bsp);
|
||||
bspstore = (unsigned long)
|
||||
ia64_rse_skip_regs (ar_bsp, -ndirty);
|
||||
ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
|
||||
sc->sc_ar_rnat);
|
||||
}
|
||||
|
||||
/* Don't touch the branch registers o.t. b0, b6 and b7.
|
||||
The kernel doesn't pass the preserved branch registers
|
||||
in the sigcontext but leaves them intact, so there's no
|
||||
need to do anything with them here. */
|
||||
{
|
||||
unsigned long sof = sc->sc_cfm & 0x7f;
|
||||
context->bsp = (unsigned long)
|
||||
ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
|
||||
}
|
||||
|
||||
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;
|
||||
fs->curr.reg[UNW_REG_RP].val
|
||||
= (unsigned long)&(sc->sc_ip) - context->psp;
|
||||
fs->curr.reg[UNW_REG_RP].when = -1;
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
#define MD_HANDLE_UNWABI ia64_handle_unwabi
|
||||
|
||||
static void
|
||||
ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
{
|
||||
if (fs->unwabi == ((3 << 8) | 's')
|
||||
|| fs->unwabi == ((0 << 8) | 's'))
|
||||
{
|
||||
struct sigframe {
|
||||
char scratch[16];
|
||||
unsigned long sig_number;
|
||||
struct siginfo *info;
|
||||
struct sigcontext *sc;
|
||||
} *frame = (struct sigframe *)context->psp;
|
||||
struct sigcontext *sc = frame->sc;
|
||||
|
||||
/* Restore scratch registers in case the unwinder needs to
|
||||
refer to a value stored in one of them. */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 2; i < 4; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
for (i = 8; i < 12; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
for (i = 14; i < 32; i++)
|
||||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
}
|
||||
|
||||
context->pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->lc_loc = &(sc->sc_ar_lc);
|
||||
context->unat_loc = &(sc->sc_ar_unat);
|
||||
context->br_loc[0] = &(sc->sc_br[0]);
|
||||
context->br_loc[6] = &(sc->sc_br[6]);
|
||||
context->br_loc[7] = &(sc->sc_br[7]);
|
||||
context->pr = sc->sc_pr;
|
||||
context->gp = sc->sc_gr[1];
|
||||
/* Signal frame doesn't have an associated reg. stack frame
|
||||
other than what we adjust for below. */
|
||||
fs -> no_reg_stack_frame = 1;
|
||||
|
||||
if (sc->sc_rbs_base)
|
||||
{
|
||||
/* Need to switch from alternate register backing store. */
|
||||
long ndirty, loadrs = sc->sc_loadrs >> 16;
|
||||
unsigned long alt_bspstore = context->bsp - loadrs;
|
||||
unsigned long bspstore;
|
||||
unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
|
||||
|
||||
ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
|
||||
(unsigned long *) context->bsp);
|
||||
bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty);
|
||||
ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
|
||||
sc->sc_ar_rnat);
|
||||
}
|
||||
|
||||
/* Don't touch the branch registers o.t. b0, b6 and b7.
|
||||
The kernel doesn't pass the preserved branch registers
|
||||
in the sigcontext but leaves them intact, so there's no
|
||||
need to do anything with them here. */
|
||||
{
|
||||
unsigned long sof = sc->sc_cfm & 0x7f;
|
||||
context->bsp = (unsigned long)
|
||||
ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
|
||||
}
|
||||
|
||||
/* pfs_loc already set above. Without this pfs_loc would point
|
||||
incorrectly to sc_cfm instead of sc_ar_pfs. */
|
||||
fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;
|
||||
}
|
||||
}
|
||||
#endif /* glibc-2.3 or better */
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#define IA64_GATE_AREA_START 0xa000000000000100LL
|
||||
#define IA64_GATE_AREA_END 0xa000000000030000LL
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
if ((CONTEXT)->rp >= IA64_GATE_AREA_START \
|
||||
&& (CONTEXT)->rp < IA64_GATE_AREA_END) \
|
||||
{ \
|
||||
struct sigframe { \
|
||||
char scratch[16]; \
|
||||
unsigned long sig_number; \
|
||||
struct siginfo *info; \
|
||||
struct sigcontext *sc; \
|
||||
} *frame_ = (struct sigframe *)(CONTEXT)->psp; \
|
||||
struct sigcontext *sc_ = frame_->sc; \
|
||||
\
|
||||
/* Restore scratch registers in case the unwinder needs to \
|
||||
refer to a value stored in one of them. */ \
|
||||
{ \
|
||||
int i_; \
|
||||
\
|
||||
for (i_ = 2; i_ < 4; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
for (i_ = 8; i_ < 12; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
for (i_ = 14; i_ < 32; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
} \
|
||||
\
|
||||
(CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr); \
|
||||
(CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
|
||||
(CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
|
||||
(CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
|
||||
(CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
|
||||
(CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
|
||||
(CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
|
||||
(CONTEXT)->pr = sc_->sc_pr; \
|
||||
(CONTEXT)->psp = sc_->sc_gr[12]; \
|
||||
(CONTEXT)->gp = sc_->sc_gr[1]; \
|
||||
/* Signal frame doesn't have an associated reg. stack frame \
|
||||
other than what we adjust for below. */ \
|
||||
(FS) -> no_reg_stack_frame = 1; \
|
||||
\
|
||||
if (sc_->sc_rbs_base) \
|
||||
{ \
|
||||
/* Need to switch from alternate register backing store. */ \
|
||||
long ndirty, loadrs = sc_->sc_loadrs >> 16; \
|
||||
unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
|
||||
unsigned long bspstore; \
|
||||
unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
|
||||
\
|
||||
ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
|
||||
(unsigned long *) (CONTEXT)->bsp);\
|
||||
bspstore = (unsigned long) \
|
||||
ia64_rse_skip_regs (ar_bsp, -ndirty); \
|
||||
ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
|
||||
sc_->sc_ar_rnat); \
|
||||
} \
|
||||
\
|
||||
/* Don't touch the branch registers o.t. b0, b6 and b7. \
|
||||
The kernel doesn't pass the preserved branch registers \
|
||||
in the sigcontext but leaves them intact, so there's no \
|
||||
need to do anything with them here. */ \
|
||||
{ \
|
||||
unsigned long sof = sc_->sc_cfm & 0x7f; \
|
||||
(CONTEXT)->bsp = (unsigned long) \
|
||||
ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
|
||||
} \
|
||||
\
|
||||
(FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; \
|
||||
(FS)->curr.reg[UNW_REG_RP].val \
|
||||
= (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp; \
|
||||
(FS)->curr.reg[UNW_REG_RP].when = -1; \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
}
|
||||
|
||||
#define MD_HANDLE_UNWABI(CONTEXT, FS) \
|
||||
if ((FS)->unwabi == ((3 << 8) | 's') \
|
||||
|| (FS)->unwabi == ((0 << 8) | 's')) \
|
||||
{ \
|
||||
struct sigframe { \
|
||||
char scratch[16]; \
|
||||
unsigned long sig_number; \
|
||||
struct siginfo *info; \
|
||||
struct sigcontext *sc; \
|
||||
} *frame_ = (struct sigframe *)(CONTEXT)->psp; \
|
||||
struct sigcontext *sc_ = frame_->sc; \
|
||||
\
|
||||
/* Restore scratch registers in case the unwinder needs to \
|
||||
refer to a value stored in one of them. */ \
|
||||
{ \
|
||||
int i_; \
|
||||
\
|
||||
for (i_ = 2; i_ < 4; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
for (i_ = 8; i_ < 12; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
for (i_ = 14; i_ < 32; i_++) \
|
||||
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
|
||||
} \
|
||||
\
|
||||
(CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
|
||||
(CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
|
||||
(CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
|
||||
(CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
|
||||
(CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
|
||||
(CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
|
||||
(CONTEXT)->pr = sc_->sc_pr; \
|
||||
(CONTEXT)->gp = sc_->sc_gr[1]; \
|
||||
/* Signal frame doesn't have an associated reg. stack frame \
|
||||
other than what we adjust for below. */ \
|
||||
(FS) -> no_reg_stack_frame = 1; \
|
||||
\
|
||||
if (sc_->sc_rbs_base) \
|
||||
{ \
|
||||
/* Need to switch from alternate register backing store. */ \
|
||||
long ndirty, loadrs = sc_->sc_loadrs >> 16; \
|
||||
unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
|
||||
unsigned long bspstore; \
|
||||
unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
|
||||
\
|
||||
ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
|
||||
(unsigned long *) (CONTEXT)->bsp);\
|
||||
bspstore = (unsigned long) \
|
||||
ia64_rse_skip_regs (ar_bsp, -ndirty); \
|
||||
ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
|
||||
sc_->sc_ar_rnat); \
|
||||
} \
|
||||
\
|
||||
/* Don't touch the branch registers o.t. b0, b6 and b7. \
|
||||
The kernel doesn't pass the preserved branch registers \
|
||||
in the sigcontext but leaves them intact, so there's no \
|
||||
need to do anything with them here. */ \
|
||||
{ \
|
||||
unsigned long sof = sc_->sc_cfm & 0x7f; \
|
||||
(CONTEXT)->bsp = (unsigned long) \
|
||||
ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
|
||||
} \
|
||||
\
|
||||
/* pfs_loc already set above. Without this pfs_loc would point \
|
||||
incorrectly to sc_cfm instead of sc_ar_pfs. */ \
|
||||
(FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; \
|
||||
}
|
||||
|
||||
#endif /* IN_LIBGCC2 */
|
||||
#endif /* glibc-2.3 or better */
|
||||
#define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h"
|
||||
|
@ -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;
|
||||
|
93
gcc/config/mips/linux-unwind.h
Normal file
93
gcc/config/mips/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
|
||||
/* The third parameter to the signal handler points to something with
|
||||
* this structure defined in asm/ucontext.h, but the name clashes with
|
||||
* struct ucontext from sys/ucontext.h so this private copy is used. */
|
||||
typedef struct _sig_ucontext {
|
||||
unsigned long uc_flags;
|
||||
struct _sig_ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
struct sigcontext uc_mcontext;
|
||||
sigset_t uc_sigmask;
|
||||
} _sig_ucontext_t;
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
mips_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
u_int32_t *pc = (u_int32_t *) context->ra;
|
||||
struct sigcontext *sc;
|
||||
_Unwind_Ptr new_cfa;
|
||||
int i;
|
||||
|
||||
/* 24021061 li v0, 0x1061 (rt_sigreturn)*/
|
||||
/* 0000000c syscall */
|
||||
/* or */
|
||||
/* 24021017 li v0, 0x1017 (sigreturn) */
|
||||
/* 0000000c syscall */
|
||||
if (*(pc + 1) != 0x0000000c)
|
||||
return _URC_END_OF_STACK;
|
||||
if (*(pc + 0) == 0x24021017)
|
||||
{
|
||||
struct sigframe {
|
||||
u_int32_t trampoline[2];
|
||||
struct sigcontext sigctx;
|
||||
} *rt_ = context->ra;
|
||||
sc = &rt_->sigctx;
|
||||
}
|
||||
else if (*(pc + 0) == 0x24021061)
|
||||
{
|
||||
struct rt_sigframe {
|
||||
u_int32_t trampoline[2];
|
||||
struct siginfo info;
|
||||
_sig_ucontext_t uc;
|
||||
} *rt_ = context->ra;
|
||||
sc = &rt_->uc.uc_mcontext;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
new_cfa = (_Unwind_Ptr)sc;
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->cfa_reg = STACK_POINTER_REGNUM;
|
||||
fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i].loc.offset
|
||||
= (_Unwind_Ptr)&(sc->sc_regs[i]) - new_cfa;
|
||||
}
|
||||
fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset
|
||||
= (_Unwind_Ptr)&(sc->sc_pc) - new_cfa;
|
||||
fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
#endif
|
@ -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 <signal.h>
|
||||
|
||||
/* The third parameter to the signal handler points to something with
|
||||
* this structure defined in asm/ucontext.h, but the name clashes with
|
||||
* struct ucontext from sys/ucontext.h so this private copy is used. */
|
||||
typedef struct _sig_ucontext {
|
||||
unsigned long uc_flags;
|
||||
struct _sig_ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
struct sigcontext uc_mcontext;
|
||||
sigset_t uc_sigmask;
|
||||
} _sig_ucontext_t;
|
||||
|
||||
#endif /* IN_LIBGCC2 */
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
u_int32_t *pc_ = (u_int32_t *) (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
_Unwind_Ptr new_cfa_; \
|
||||
int i_; \
|
||||
\
|
||||
/* 24021061 li v0, 0x1061 (rt_sigreturn)*/ \
|
||||
/* 0000000c syscall */ \
|
||||
/* or */ \
|
||||
/* 24021017 li v0, 0x1017 (sigreturn) */ \
|
||||
/* 0000000c syscall */ \
|
||||
if (*(pc_ + 1) != 0x0000000c) \
|
||||
break; \
|
||||
if (*(pc_ + 0) == 0x24021017) \
|
||||
{ \
|
||||
struct sigframe { \
|
||||
u_int32_t trampoline[2]; \
|
||||
struct sigcontext sigctx; \
|
||||
} *rt_ = (CONTEXT)->ra; \
|
||||
sc_ = &rt_->sigctx; \
|
||||
} \
|
||||
else if (*(pc_ + 0) == 0x24021061) \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
u_int32_t trampoline[2]; \
|
||||
struct siginfo info; \
|
||||
_sig_ucontext_t uc; \
|
||||
} *rt_ = (CONTEXT)->ra; \
|
||||
sc_ = &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = (_Unwind_Ptr)sc_; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = STACK_POINTER_REGNUM; \
|
||||
(FS)->cfa_offset = new_cfa_ - (_Unwind_Ptr) (CONTEXT)->cfa; \
|
||||
\
|
||||
for (i_ = 0; i_ < 32; i_++) { \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset \
|
||||
= (_Unwind_Ptr)&(sc_->sc_regs[i_]) - new_cfa_; \
|
||||
} \
|
||||
(FS)->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset \
|
||||
= (_Unwind_Ptr)&(sc_->sc_pc) - new_cfa_; \
|
||||
(FS)->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN; \
|
||||
\
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
#endif
|
||||
#define MD_UNWIND_SUPPORT "config/mips/linux-unwind.h"
|
||||
|
115
gcc/config/pa/linux-unwind.h
Normal file
115
gcc/config/pa/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
/* Unfortunately, because of various bugs and changes to the kernel,
|
||||
we have several cases to deal with.
|
||||
|
||||
In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should
|
||||
point directly at the beginning of the trampoline and struct rt_sigframe.
|
||||
|
||||
In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and
|
||||
(CONTEXT)->ra points at the 4th word in the trampoline structure. This
|
||||
is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4.
|
||||
|
||||
To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes
|
||||
to get the beginning of the signal frame, and then check offsets 0, 4
|
||||
and 5 to see if we found the beginning of the trampoline. This will
|
||||
tell us how to locate the sigcontext structure.
|
||||
|
||||
Note that with a 2.4 64-bit kernel, the signal context is not properly
|
||||
passed back to userspace so the unwind will not work correctly. */
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
pa32_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
unsigned long sp = (unsigned long)context->ra & ~63;
|
||||
unsigned int *pc = (unsigned int *)sp;
|
||||
unsigned long off;
|
||||
_Unwind_Ptr new_cfa;
|
||||
int i;
|
||||
struct sigcontext *sc;
|
||||
struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
} *frame;
|
||||
|
||||
/* rt_sigreturn trampoline:
|
||||
3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2)
|
||||
3414015a ldi __NR_rt_sigreturn, %r20
|
||||
e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31
|
||||
08000240 nop */
|
||||
|
||||
if (pc[0] == 0x34190000 || pc[0] == 0x34190002)
|
||||
off = 4*4;
|
||||
else if (pc[4] == 0x34190000 || pc[4] == 0x34190002)
|
||||
{
|
||||
pc += 4;
|
||||
off = 10 * 4;
|
||||
}
|
||||
else if (pc[5] == 0x34190000 || pc[5] == 0x34190002)
|
||||
{
|
||||
pc += 5;
|
||||
off = 10 * 4;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
if (pc[1] != 0x3414015a
|
||||
|| pc[2] != 0xe4008200
|
||||
|| pc[3] != 0x08000240)
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
frame = (struct rt_sigframe *)(sp + off);
|
||||
sc = &frame->uc.uc_mcontext;
|
||||
|
||||
new_cfa = sc->sc_gr[30];
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->cfa_reg = 30;
|
||||
fs->cfa_offset = new_cfa - (long) context->cfa;
|
||||
for (i = 1; i <= 31; i++)
|
||||
{
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa;
|
||||
}
|
||||
for (i = 4; i <= 31; i++)
|
||||
{
|
||||
/* FP regs have left and right halves */
|
||||
fs->regs.reg[2*i+24].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[2*i+24].loc.offset
|
||||
= (long)&sc->sc_fr[i] - new_cfa;
|
||||
fs->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[2*i+24+1].loc.offset
|
||||
= (long)&sc->sc_fr[i] + 4 - new_cfa;
|
||||
}
|
||||
fs->regs.reg[88].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa;
|
||||
fs->regs.reg[2].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[2].loc.offset = (long) &sc->sc_iaoq[0] - new_cfa;
|
||||
fs->retaddr_column = 2;
|
||||
return _URC_NO_REASON;
|
||||
}
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
/* Unfortunately, because of various bugs and changes to the kernel,
|
||||
we have several cases to deal with.
|
||||
|
||||
In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should
|
||||
point directly at the beginning of the trampoline and struct rt_sigframe.
|
||||
|
||||
In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and
|
||||
(CONTEXT)->ra points at the 4th word in the trampoline structure. This
|
||||
is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4.
|
||||
|
||||
To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes
|
||||
to get the beginning of the signal frame, and then check offsets 0, 4
|
||||
and 5 to see if we found the beginning of the trampoline. This will
|
||||
tell us how to locate the sigcontext structure.
|
||||
|
||||
Note that with a 2.4 64-bit kernel, the signal context is not properly
|
||||
passed back to userspace so the unwind will not work correctly. */
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned long sp = (unsigned long)(CONTEXT)->ra & ~63; \
|
||||
unsigned int *pc = (unsigned int *)sp; \
|
||||
unsigned long off; \
|
||||
_Unwind_Ptr new_cfa; \
|
||||
int i; \
|
||||
struct sigcontext *sc; \
|
||||
struct rt_sigframe { \
|
||||
struct siginfo info; \
|
||||
struct ucontext uc; \
|
||||
} *frame; \
|
||||
\
|
||||
/* rt_sigreturn trampoline: \
|
||||
3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) \
|
||||
3414015a ldi __NR_rt_sigreturn, %r20 \
|
||||
e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 \
|
||||
08000240 nop */ \
|
||||
\
|
||||
if (pc[0] == 0x34190000 || pc[0] == 0x34190002) \
|
||||
off = 4*4; \
|
||||
else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) \
|
||||
{ \
|
||||
pc += 4; \
|
||||
off = 10 * 4; \
|
||||
} \
|
||||
else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) \
|
||||
{ \
|
||||
pc += 5; \
|
||||
off = 10 * 4; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
if (pc[1] != 0x3414015a \
|
||||
|| pc[2] != 0xe4008200 \
|
||||
|| pc[3] != 0x08000240) \
|
||||
break; \
|
||||
\
|
||||
frame = (struct rt_sigframe *)(sp + off); \
|
||||
sc = &frame->uc.uc_mcontext; \
|
||||
\
|
||||
new_cfa = sc->sc_gr[30]; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 30; \
|
||||
(FS)->cfa_offset = new_cfa - (long) (CONTEXT)->cfa; \
|
||||
for (i = 1; i <= 31; i++) \
|
||||
{ \
|
||||
(FS)->regs.reg[i].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa; \
|
||||
} \
|
||||
for (i = 4; i <= 31; i++) \
|
||||
{ \
|
||||
/* FP regs have left and right halves */ \
|
||||
(FS)->regs.reg[2*i+24].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2*i+24].loc.offset \
|
||||
= (long)&sc->sc_fr[i] - new_cfa; \
|
||||
(FS)->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2*i+24+1].loc.offset \
|
||||
= (long)&sc->sc_fr[i] + 4 - new_cfa; \
|
||||
} \
|
||||
(FS)->regs.reg[88].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa; \
|
||||
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[2].loc.offset = (long) &sc->sc_iaoq[0] - new_cfa; \
|
||||
(FS)->retaddr_column = 2; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
|
||||
#endif /* IN_LIBGCC2 */
|
||||
#define MD_UNWIND_SUPPORT "config/pa/linux-unwind.h"
|
||||
|
35
gcc/config/rs6000/darwin-unwind.h
Normal file
35
gcc/config/rs6000/darwin-unwind.h
Normal file
@ -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)
|
@ -371,14 +371,7 @@ extern const char *darwin_one_byte_bool;
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
{ \
|
||||
extern bool _Unwind_fallback_frame_state_for \
|
||||
(struct _Unwind_Context *context, _Unwind_FrameState *fs); \
|
||||
\
|
||||
if (_Unwind_fallback_frame_state_for (CONTEXT, FS)) \
|
||||
goto SUCCESS; \
|
||||
}
|
||||
#define MD_UNWIND_SUPPORT "config/rs6000/darwin-unwind.h"
|
||||
|
||||
#define HAS_MD_FALLBACK_FRAME_STATE_FOR 1
|
||||
|
||||
|
186
gcc/config/rs6000/linux-unwind.h
Normal file
186
gcc/config/rs6000/linux-unwind.h
Normal file
@ -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;
|
||||
}
|
@ -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 <signal.h>
|
||||
|
||||
/* During the 2.5 kernel series the kernel ucontext was changed, but
|
||||
the new layout is compatible with the old one, so we just define
|
||||
and use the old one here for simplicity and compatibility. */
|
||||
|
||||
struct kernel_old_ucontext {
|
||||
unsigned long uc_flags;
|
||||
struct ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
struct sigcontext_struct uc_mcontext;
|
||||
sigset_t uc_sigmask;
|
||||
};
|
||||
|
||||
enum { SIGNAL_FRAMESIZE = 64 };
|
||||
#endif
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned char *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_; \
|
||||
int i_; \
|
||||
\
|
||||
/* li r0, 0x7777; sc (sigreturn old) */ \
|
||||
/* li r0, 0x0077; sc (sigreturn new) */ \
|
||||
/* li r0, 0x6666; sc (rt_sigreturn old) */ \
|
||||
/* li r0, 0x00AC; sc (rt_sigreturn new) */ \
|
||||
if (*(unsigned int *) (pc_+4) != 0x44000002) \
|
||||
break; \
|
||||
if (*(unsigned int *) (pc_+0) == 0x38007777 \
|
||||
|| *(unsigned int *) (pc_+0) == 0x38000077) \
|
||||
{ \
|
||||
struct sigframe { \
|
||||
char gap[SIGNAL_FRAMESIZE]; \
|
||||
struct sigcontext sigctx; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = &rt_->sigctx; \
|
||||
} \
|
||||
else if (*(unsigned int *) (pc_+0) == 0x38006666 \
|
||||
|| *(unsigned int *) (pc_+0) == 0x380000AC) \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
char gap[SIGNAL_FRAMESIZE]; \
|
||||
unsigned long _unused[2]; \
|
||||
struct siginfo *pinfo; \
|
||||
void *puc; \
|
||||
struct siginfo info; \
|
||||
struct kernel_old_ucontext uc; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = STACK_POINTER_REGNUM; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
\
|
||||
for (i_ = 0; i_ < 32; i_++) \
|
||||
if (i_ != STACK_POINTER_REGNUM) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset \
|
||||
= (long)&(sc_->regs->gpr[i_]) - new_cfa_; \
|
||||
} \
|
||||
\
|
||||
(FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
|
||||
= (long)&(sc_->regs->link) - new_cfa_; \
|
||||
\
|
||||
(FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[CR0_REGNO].loc.offset \
|
||||
= (long)&(sc_->regs->nip) - new_cfa_; \
|
||||
(FS)->retaddr_column = CR0_REGNO; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
|
||||
#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
|
||||
|
||||
#define OS_MISSING_POWERPC64 1
|
||||
|
@ -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
|
||||
|
131
gcc/config/s390/linux-unwind.h
Normal file
131
gcc/config/s390/linux-unwind.h
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
167
gcc/config/sh/linux-unwind.h
Normal file
167
gcc/config/sh/linux-unwind.h
Normal file
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include "insn-constants.h"
|
||||
|
||||
# if defined (__SH5__)
|
||||
#define SH_DWARF_FRAME_GP0 0
|
||||
#define SH_DWARF_FRAME_FP0 (__SH5__ == 32 ? 245 : 77)
|
||||
#define SH_DWARF_FRAME_XD0 289
|
||||
#define SH_DWARF_FRAME_BT0 68
|
||||
#define SH_DWARF_FRAME_PR 241
|
||||
#define SH_DWARF_FRAME_PR_MEDIA 18
|
||||
#define SH_DWARF_FRAME_GBR 238
|
||||
#define SH_DWARF_FRAME_MACH 239
|
||||
#define SH_DWARF_FRAME_MACL 240
|
||||
#define SH_DWARF_FRAME_PC 64
|
||||
#define SH_DWARF_FRAME_SR 65
|
||||
#define SH_DWARF_FRAME_FPUL 244
|
||||
#define SH_DWARF_FRAME_FPSCR 243
|
||||
#else
|
||||
#define SH_DWARF_FRAME_GP0 0
|
||||
#define SH_DWARF_FRAME_FP0 25
|
||||
#define SH_DWARF_FRAME_XD0 87
|
||||
#define SH_DWARF_FRAME_PR 17
|
||||
#define SH_DWARF_FRAME_GBR 19
|
||||
#define SH_DWARF_FRAME_MACH 20
|
||||
#define SH_DWARF_FRAME_MACL 21
|
||||
#define SH_DWARF_FRAME_PC 16
|
||||
#define SH_DWARF_FRAME_SR 22
|
||||
#define SH_DWARF_FRAME_FPUL 23
|
||||
#define SH_DWARF_FRAME_FPSCR 24
|
||||
#endif /* defined (__SH5__) */
|
||||
|
||||
#if defined (__SH5__)
|
||||
/* MD_FALLBACK_FRAME_STATE_FOR is not yet defined for SHMEDIA. */
|
||||
#else /* defined (__SH5__) */
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
sh_fallback_frame_state (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
unsigned char *pc = context->ra;
|
||||
struct sigcontext *sc;
|
||||
long new_cfa;
|
||||
int i;
|
||||
#if defined (__SH3E__) || defined (__SH4__)
|
||||
int r;
|
||||
#endif
|
||||
|
||||
/* mov.w 1f,r3; trapa #0x10; 1: .short 0x77 (sigreturn) */
|
||||
/* mov.w 1f,r3; trapa #0x10; 1: .short 0xad (rt_sigreturn) */
|
||||
/* Newer kernel uses pad instructions to avoid an SH-4 core bug. */
|
||||
/* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
|
||||
or r0,r0; 1: .short 0x77 (sigreturn) */
|
||||
/* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
|
||||
or r0,r0; 1: .short 0xad (rt_sigreturn) */
|
||||
if (((*(unsigned short *) (pc+0) == 0x9300)
|
||||
&& (*(unsigned short *) (pc+2) == 0xc310)
|
||||
&& (*(unsigned short *) (pc+4) == 0x0077))
|
||||
|| (((*(unsigned short *) (pc+0) == 0x9305)
|
||||
&& (*(unsigned short *) (pc+2) == 0xc310)
|
||||
&& (*(unsigned short *) (pc+14) == 0x0077))))
|
||||
sc = context->cfa;
|
||||
else if (((*(unsigned short *) (pc+0) == 0x9300)
|
||||
&& (*(unsigned short *) (pc+2) == 0xc310)
|
||||
&& (*(unsigned short *) (pc+4) == 0x00ad))
|
||||
|| (((*(unsigned short *) (pc+0) == 0x9305)
|
||||
&& (*(unsigned short *) (pc+2) == 0xc310)
|
||||
&& (*(unsigned short *) (pc+14) == 0x00ad))))
|
||||
{
|
||||
struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
} *rt_ = context->cfa;
|
||||
sc = (struct sigcontext *) &rt_->uc.uc_mcontext;
|
||||
}
|
||||
else
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
new_cfa = sc->sc_regs[15];
|
||||
fs->cfa_how = CFA_REG_OFFSET;
|
||||
fs->cfa_reg = 15;
|
||||
fs->cfa_offset = new_cfa - (long) context->cfa;
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i].loc.offset
|
||||
= (long)&(sc->sc_regs[i]) - new_cfa;
|
||||
}
|
||||
|
||||
fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset
|
||||
= (long)&(sc->sc_pr) - new_cfa;
|
||||
fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset
|
||||
= (long)&(sc->sc_sr) - new_cfa;
|
||||
fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset
|
||||
= (long)&(sc->sc_gbr) - new_cfa;
|
||||
fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset
|
||||
= (long)&(sc->sc_mach) - new_cfa;
|
||||
fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset
|
||||
= (long)&(sc->sc_macl) - new_cfa;
|
||||
|
||||
#if defined (__SH3E__) || defined (__SH4__)
|
||||
r = SH_DWARF_FRAME_FP0;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
fs->regs.reg[r+i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[r+i].loc.offset
|
||||
= (long)&(sc->sc_fpregs[i]) - new_cfa;
|
||||
}
|
||||
|
||||
r = SH_DWARF_FRAME_XD0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i].loc.offset
|
||||
= (long)&(sc->sc_xfpregs[2*i]) - new_cfa;
|
||||
}
|
||||
|
||||
fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset
|
||||
= (long)&(sc->sc_fpul) - new_cfa;
|
||||
fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset
|
||||
= (long)&(sc->sc_fpscr) - new_cfa;
|
||||
#endif
|
||||
|
||||
/* The unwinder expects the PC to point to the following insn,
|
||||
whereas the kernel returns the address of the actual
|
||||
faulting insn. */
|
||||
sc->sc_pc += 2;
|
||||
fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset
|
||||
= (long)&(sc->sc_pc) - new_cfa;
|
||||
fs->retaddr_column = SH_DWARF_FRAME_PC;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
#endif /* defined (__SH5__) */
|
@ -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 <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include "insn-constants.h"
|
||||
|
||||
# if defined (__SH5__)
|
||||
#define SH_DWARF_FRAME_GP0 0
|
||||
#define SH_DWARF_FRAME_FP0 (__SH5__ == 32 ? 245 : 77)
|
||||
#define SH_DWARF_FRAME_XD0 289
|
||||
#define SH_DWARF_FRAME_BT0 68
|
||||
#define SH_DWARF_FRAME_PR 241
|
||||
#define SH_DWARF_FRAME_PR_MEDIA 18
|
||||
#define SH_DWARF_FRAME_GBR 238
|
||||
#define SH_DWARF_FRAME_MACH 239
|
||||
#define SH_DWARF_FRAME_MACL 240
|
||||
#define SH_DWARF_FRAME_PC 64
|
||||
#define SH_DWARF_FRAME_SR 65
|
||||
#define SH_DWARF_FRAME_FPUL 244
|
||||
#define SH_DWARF_FRAME_FPSCR 243
|
||||
#else
|
||||
#define SH_DWARF_FRAME_GP0 0
|
||||
#define SH_DWARF_FRAME_FP0 25
|
||||
#define SH_DWARF_FRAME_XD0 87
|
||||
#define SH_DWARF_FRAME_PR 17
|
||||
#define SH_DWARF_FRAME_GBR 19
|
||||
#define SH_DWARF_FRAME_MACH 20
|
||||
#define SH_DWARF_FRAME_MACL 21
|
||||
#define SH_DWARF_FRAME_PC 16
|
||||
#define SH_DWARF_FRAME_SR 22
|
||||
#define SH_DWARF_FRAME_FPUL 23
|
||||
#define SH_DWARF_FRAME_FPSCR 24
|
||||
#endif /* defined (__SH5__) */
|
||||
|
||||
#if defined (__SH5__)
|
||||
/* MD_FALLBACK_FRAME_STATE_FOR is not yet defined for SHMEDIA. */
|
||||
#else /* defined (__SH5__) */
|
||||
|
||||
#if defined (__SH3E__) || defined (__SH4__)
|
||||
#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA) \
|
||||
do { \
|
||||
int i_, r_; \
|
||||
\
|
||||
r_ = SH_DWARF_FRAME_FP0; \
|
||||
for (i_ = 0; i_ < 16; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[r_+i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[r_+i_].loc.offset \
|
||||
= (long)&((SC)->sc_fpregs[i_]) - (CFA); \
|
||||
} \
|
||||
\
|
||||
r_ = SH_DWARF_FRAME_XD0 ; \
|
||||
for (i_ = 0; i_ < 8; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset \
|
||||
= (long)&((SC)->sc_xfpregs[2*i_]) - (CFA); \
|
||||
} \
|
||||
\
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset \
|
||||
= (long)&((SC)->sc_fpul) - (CFA); \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset \
|
||||
= (long)&((SC)->sc_fpscr) - (CFA); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define SH_FALLBACK_FRAME_FLOAT_STATE(SC, FS, CFA)
|
||||
#endif
|
||||
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
|
||||
do { \
|
||||
unsigned char *pc_ = (CONTEXT)->ra; \
|
||||
struct sigcontext *sc_; \
|
||||
long new_cfa_; \
|
||||
int i_; \
|
||||
\
|
||||
/* mov.w 1f,r3; trapa #0x10; 1: .short 0x77 (sigreturn) */ \
|
||||
/* mov.w 1f,r3; trapa #0x10; 1: .short 0xad (rt_sigreturn) */ \
|
||||
/* Newer kernel uses pad instructions to avoid an SH-4 core bug. */\
|
||||
/* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;\
|
||||
or r0,r0; 1: .short 0x77 (sigreturn) */ \
|
||||
/* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;\
|
||||
or r0,r0; 1: .short 0xad (rt_sigreturn) */ \
|
||||
if (((*(unsigned short *) (pc_+0) == 0x9300) \
|
||||
&& (*(unsigned short *) (pc_+2) == 0xc310) \
|
||||
&& (*(unsigned short *) (pc_+4) == 0x0077)) \
|
||||
|| (((*(unsigned short *) (pc_+0) == 0x9305) \
|
||||
&& (*(unsigned short *) (pc_+2) == 0xc310) \
|
||||
&& (*(unsigned short *) (pc_+14) == 0x0077)))) \
|
||||
sc_ = (CONTEXT)->cfa; \
|
||||
else if (((*(unsigned short *) (pc_+0) == 0x9300) \
|
||||
&& (*(unsigned short *) (pc_+2) == 0xc310) \
|
||||
&& (*(unsigned short *) (pc_+4) == 0x00ad)) \
|
||||
|| (((*(unsigned short *) (pc_+0) == 0x9305) \
|
||||
&& (*(unsigned short *) (pc_+2) == 0xc310) \
|
||||
&& (*(unsigned short *) (pc_+14) == 0x00ad)))) \
|
||||
{ \
|
||||
struct rt_sigframe { \
|
||||
struct siginfo info; \
|
||||
struct ucontext uc; \
|
||||
} *rt_ = (CONTEXT)->cfa; \
|
||||
sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
\
|
||||
new_cfa_ = sc_->sc_regs[15]; \
|
||||
(FS)->cfa_how = CFA_REG_OFFSET; \
|
||||
(FS)->cfa_reg = 15; \
|
||||
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
|
||||
\
|
||||
for (i_ = 0; i_ < 15; i_++) \
|
||||
{ \
|
||||
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[i_].loc.offset \
|
||||
= (long)&(sc_->sc_regs[i_]) - new_cfa_; \
|
||||
} \
|
||||
\
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_PR].loc.offset \
|
||||
= (long)&(sc_->sc_pr) - new_cfa_; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_SR].loc.offset \
|
||||
= (long)&(sc_->sc_sr) - new_cfa_; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_GBR].loc.offset \
|
||||
= (long)&(sc_->sc_gbr) - new_cfa_; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_MACH].loc.offset \
|
||||
= (long)&(sc_->sc_mach) - new_cfa_; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_MACL].loc.offset \
|
||||
= (long)&(sc_->sc_macl) - new_cfa_; \
|
||||
\
|
||||
SH_FALLBACK_FRAME_FLOAT_STATE(sc_, (FS), new_cfa_); \
|
||||
\
|
||||
/* The unwinder expects the PC to point to the following insn, \
|
||||
whereas the kernel returns the address of the actual \
|
||||
faulting insn. */ \
|
||||
sc_->sc_pc += 2; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET; \
|
||||
(FS)->regs.reg[SH_DWARF_FRAME_PC].loc.offset \
|
||||
= (long)&(sc_->sc_pc) - new_cfa_; \
|
||||
(FS)->retaddr_column = SH_DWARF_FRAME_PC; \
|
||||
goto SUCCESS; \
|
||||
} while (0)
|
||||
|
||||
#endif /* defined (__SH5__) */
|
||||
#endif /* IN_LIBGCC2 */
|
||||
#define MD_UNWIND_SUPPORT "config/sh/linux-unwind.h"
|
||||
|
||||
/* For SH3 and SH4, we use a slot of the unwind frame which correspond
|
||||
to a fake register number 16 as a placeholder for the return address
|
||||
|
150
gcc/config/sparc/linux-unwind.h
Normal file
150
gcc/config/sparc/linux-unwind.h
Normal file
@ -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
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user