diff options
author | Alan Modra <amodra@bigpond.net.au> | 2004-09-08 00:17:19 +0000 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2004-09-08 09:47:19 +0930 |
commit | 8662eb14c0ef6531d7086ec08f5e52b87c472ede (patch) | |
tree | f6927bd90fe84c682dd04619d255d6355aac36d5 /gcc/config/rs6000 | |
parent | a9e10feb68d5cbc371f581ebca229043b7854fe5 (diff) | |
download | gcc-8662eb14c0ef6531d7086ec08f5e52b87c472ede.zip gcc-8662eb14c0ef6531d7086ec08f5e52b87c472ede.tar.gz gcc-8662eb14c0ef6531d7086ec08f5e52b87c472ede.tar.bz2 |
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
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r-- | gcc/config/rs6000/darwin-unwind.h | 35 | ||||
-rw-r--r-- | gcc/config/rs6000/darwin.h | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/linux-unwind.h | 186 | ||||
-rw-r--r-- | gcc/config/rs6000/linux.h | 84 | ||||
-rw-r--r-- | gcc/config/rs6000/linux64.h | 181 |
5 files changed, 224 insertions, 271 deletions
diff --git a/gcc/config/rs6000/darwin-unwind.h b/gcc/config/rs6000/darwin-unwind.h new file mode 100644 index 0000000..e3d0326 --- /dev/null +++ b/gcc/config/rs6000/darwin-unwind.h @@ -0,0 +1,35 @@ +/* DWARF2 EH unwinding support for Darwin. + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file into combinations with other programs, + and to distribute those combinations without any restriction coming + from the use of this file. (The General Public License restrictions + do apply in other respects; for example, they cover modification of + the file, and distribution when not linked into a combined + executable.) + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +extern bool _Unwind_fallback_frame_state_for + (struct _Unwind_Context *context, _Unwind_FrameState *fs); + +#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS) \ + (_Unwind_fallback_frame_state_for (CONTEXT, FS) \ + ? _URC_NO_REASON : _URC_END_OF_STACK) diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 1e92d5f..44ae79a 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -371,14 +371,7 @@ extern const char *darwin_one_byte_bool; #include <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 diff --git a/gcc/config/rs6000/linux-unwind.h b/gcc/config/rs6000/linux-unwind.h new file mode 100644 index 0000000..bb4f0cf9 --- /dev/null +++ b/gcc/config/rs6000/linux-unwind.h @@ -0,0 +1,186 @@ +/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +/* This file defines our own versions of various kernel and user + structs, so that system headers are not needed, which otherwise + can make bootstrapping a new toolchain difficult. Do not use + these structs elsewhere; Many fields are missing, particularly + from the end of the structures. */ + +struct gcc_pt_regs +{ + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; + unsigned long ctr; + unsigned long link; +}; + +struct gcc_sigcontext +{ + unsigned long pad[7]; + struct gcc_pt_regs *regs; +}; + +struct gcc_ucontext +{ +#ifdef __powerpc64__ + unsigned long pad[21]; +#else + unsigned long pad[5]; +#endif + struct gcc_sigcontext uc_mcontext; +}; + +#ifdef __powerpc64__ + +enum { SIGNAL_FRAMESIZE = 128 }; + +/* If the current unwind info (FS) does not contain explicit info + saving R2, then we have to do a minor amount of code reading to + figure out if it was saved. The big problem here is that the + code that does the save/restore is generated by the linker, so + we have no good way to determine at compile time what to do. */ + +#define MD_FROB_UPDATE_CONTEXT frob_update_context + +static void +frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + if (fs->regs.reg[2].how == REG_UNSAVED) + { + unsigned int *insn + = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM); + if (*insn == 0xE8410028) + _Unwind_SetGRPtr (context, 2, context->cfa + 40); + } +} + +/* If PC is at a sigreturn trampoline, return a pointer to the + sigcontext. Otherwise return NULL. */ + +static struct gcc_sigcontext * +get_sigcontext (struct _Unwind_Context *context) +{ + const unsigned char *pc = context->ra; + + /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ + /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ + if (*(unsigned int *) (pc+0) != 0x38210000 + SIGNAL_FRAMESIZE + || *(unsigned int *) (pc+8) != 0x44000002) + return NULL; + if (*(unsigned int *) (pc+4) == 0x38000077) + { + struct sigframe { + char gap[SIGNAL_FRAMESIZE]; + struct gcc_sigcontext sigctx; + } *rt_ = context->cfa; + return &rt_->sigctx; + } + else if (*(unsigned int *) (pc+4) == 0x380000AC) + { + struct rt_sigframe { + int tramp[6]; + void *pinfo; + struct gcc_ucontext *puc; + } *rt_ = (struct rt_sigframe *) pc; + return &rt_->puc->uc_mcontext; + } + return NULL; +} + +#else /* !__powerpc64__ */ + +enum { SIGNAL_FRAMESIZE = 64 }; + +static struct gcc_sigcontext * +get_sigcontext (struct _Unwind_Context *context) +{ + const unsigned char *pc = context->ra; + + /* li r0, 0x7777; sc (sigreturn old) */ + /* li r0, 0x0077; sc (sigreturn new) */ + /* li r0, 0x6666; sc (rt_sigreturn old) */ + /* li r0, 0x00AC; sc (rt_sigreturn new) */ + if (*(unsigned int *) (pc+4) != 0x44000002) + return NULL; + if (*(unsigned int *) (pc+0) == 0x38007777 + || *(unsigned int *) (pc+0) == 0x38000077) + { + struct sigframe { + char gap[SIGNAL_FRAMESIZE]; + struct gcc_sigcontext sigctx; + } *rt_ = context->cfa; + return &rt_->sigctx; + } + else if (*(unsigned int *) (pc+0) == 0x38006666 + || *(unsigned int *) (pc+0) == 0x380000AC) + { + struct rt_sigframe { + char gap[SIGNAL_FRAMESIZE + 16]; + char siginfo[128]; + struct gcc_ucontext uc; + } *rt_ = context->cfa; + return &rt_->uc.uc_mcontext; + } + return NULL; +} +#endif + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state + +static _Unwind_Reason_Code +ppc_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + struct gcc_sigcontext *sc = get_sigcontext (context); + long new_cfa; + int i; + + if (sc == NULL) + return _URC_END_OF_STACK; + + new_cfa = sc->regs->gpr[STACK_POINTER_REGNUM]; + fs->cfa_how = CFA_REG_OFFSET; + fs->cfa_reg = STACK_POINTER_REGNUM; + fs->cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 32; i++) + if (i != STACK_POINTER_REGNUM) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (long)&(sc->regs->gpr[i]) - new_cfa; + } + + fs->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; + fs->regs.reg[LINK_REGISTER_REGNUM].loc.offset + = (long)&(sc->regs->link) - new_cfa; + + fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; + fs->regs.reg[ARG_POINTER_REGNUM].loc.offset + = (long)&(sc->regs->nip) - new_cfa; + fs->retaddr_column = ARG_POINTER_REGNUM; + return _URC_NO_REASON; +} diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index 83aef83..0f4d046 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -98,88 +98,6 @@ #define TARGET_HAS_F_SETLKW -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#ifdef IN_LIBGCC2 -#include <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 diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index e7b57d4..410f31e 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -557,185 +557,6 @@ while (0) #define USE_LD_AS_NEEDED 1 #endif -#ifdef IN_LIBGCC2 - -/* This file defines our own versions of various kernel and user - structs, so that system headers are not needed, which otherwise - can make bootstrapping a new toolchain difficult. Do not use - these structs elsewhere; Many fields are missing, particularly - from the end of the structures. */ - -struct gcc_pt_regs -{ - unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long orig_gpr3; - unsigned long ctr; - unsigned long link; -}; - -struct gcc_sigcontext -{ - unsigned long pad[7]; - struct gcc_pt_regs *regs; -}; - -struct gcc_ucontext -{ -#ifdef __powerpc64__ - unsigned long pad[21]; -#else - unsigned long pad[5]; -#endif - struct gcc_sigcontext uc_mcontext; -}; - -#ifdef __powerpc64__ - -enum { SIGNAL_FRAMESIZE = 128 }; - -/* If the current unwind info (FS) does not contain explicit info - saving R2, then we have to do a minor amount of code reading to - figure out if it was saved. The big problem here is that the - code that does the save/restore is generated by the linker, so - we have no good way to determine at compile time what to do. */ - -#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ - do { \ - if ((FS)->regs.reg[2].how == REG_UNSAVED) \ - { \ - unsigned int *insn \ - = (unsigned int *) \ - _Unwind_GetGR ((CTX), LINK_REGISTER_REGNUM); \ - if (*insn == 0xE8410028) \ - _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \ - } \ - } while (0) - -/* Do code reading to identify a signal frame, and set the frame - state data appropriately. See unwind-dw2.c for the structs. */ - -#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ - do { \ - unsigned char *pc_ = (CONTEXT)->ra; \ - struct gcc_sigcontext *sc_; \ - long new_cfa_; \ - int i_; \ - \ - /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ \ - /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ \ - if (*(unsigned int *) (pc_+0) != 0x38210000 + SIGNAL_FRAMESIZE \ - || *(unsigned int *) (pc_+8) != 0x44000002) \ - break; \ - if (*(unsigned int *) (pc_+4) == 0x38000077) \ - { \ - struct sigframe { \ - char gap[SIGNAL_FRAMESIZE]; \ - struct gcc_sigcontext sigctx; \ - } *rt_ = (CONTEXT)->cfa; \ - sc_ = &rt_->sigctx; \ - } \ - else if (*(unsigned int *) (pc_+4) == 0x380000AC) \ - { \ - struct rt_sigframe { \ - int tramp[6]; \ - void *pinfo; \ - struct gcc_ucontext *puc; \ - } *rt_ = (struct rt_sigframe *) pc_; \ - sc_ = &rt_->puc->uc_mcontext; \ - } \ - else \ - break; \ - \ - new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \ - (FS)->cfa_how = CFA_REG_OFFSET; \ - (FS)->cfa_reg = STACK_POINTER_REGNUM; \ - (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \ - \ - for (i_ = 0; i_ < 32; i_++) \ - if (i_ != STACK_POINTER_REGNUM) \ - { \ - (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[i_].loc.offset \ - = (long)&(sc_->regs->gpr[i_]) - new_cfa_; \ - } \ - \ - (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \ - = (long)&(sc_->regs->link) - new_cfa_; \ - \ - (FS)->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset \ - = (long)&(sc_->regs->nip) - new_cfa_; \ - (FS)->retaddr_column = ARG_POINTER_REGNUM; \ - goto SUCCESS; \ - } while (0) - -#else /* !__powerpc64__ */ - -enum { SIGNAL_FRAMESIZE = 64 }; - -#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ - do { \ - unsigned char *pc_ = (CONTEXT)->ra; \ - struct gcc_sigcontext *sc_; \ - long new_cfa_; \ - int i_; \ - \ - /* li r0, 0x7777; sc (sigreturn old) */ \ - /* li r0, 0x0077; sc (sigreturn new) */ \ - /* li r0, 0x6666; sc (rt_sigreturn old) */ \ - /* li r0, 0x00AC; sc (rt_sigreturn new) */ \ - if (*(unsigned int *) (pc_+4) != 0x44000002) \ - break; \ - if (*(unsigned int *) (pc_+0) == 0x38007777 \ - || *(unsigned int *) (pc_+0) == 0x38000077) \ - { \ - struct sigframe { \ - char gap[SIGNAL_FRAMESIZE]; \ - struct gcc_sigcontext sigctx; \ - } *rt_ = (CONTEXT)->cfa; \ - sc_ = &rt_->sigctx; \ - } \ - else if (*(unsigned int *) (pc_+0) == 0x38006666 \ - || *(unsigned int *) (pc_+0) == 0x380000AC) \ - { \ - struct rt_sigframe { \ - char gap[SIGNAL_FRAMESIZE + 16]; \ - char siginfo[128]; \ - struct gcc_ucontext uc; \ - } *rt_ = (CONTEXT)->cfa; \ - sc_ = &rt_->uc.uc_mcontext; \ - } \ - else \ - break; \ - \ - new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \ - (FS)->cfa_how = CFA_REG_OFFSET; \ - (FS)->cfa_reg = STACK_POINTER_REGNUM; \ - (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \ - \ - for (i_ = 0; i_ < 32; i_++) \ - if (i_ != STACK_POINTER_REGNUM) \ - { \ - (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[i_].loc.offset \ - = (long)&(sc_->regs->gpr[i_]) - new_cfa_; \ - } \ - \ - (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \ - = (long)&(sc_->regs->link) - new_cfa_; \ - \ - (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \ - (FS)->regs.reg[CR0_REGNO].loc.offset \ - = (long)&(sc_->regs->nip) - new_cfa_; \ - (FS)->retaddr_column = CR0_REGNO; \ - goto SUCCESS; \ - } while (0) - -#endif -#endif /* LIBGCC2 */ +#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h" #define OS_MISSING_POWERPC64 !TARGET_64BIT |