163d1a8abSmrg /* DWARF2 EH unwinding support for Alpha Linux.
2*ec02198aSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
363d1a8abSmrg
463d1a8abSmrg This file is part of GCC.
563d1a8abSmrg
663d1a8abSmrg GCC is free software; you can redistribute it and/or modify
763d1a8abSmrg it under the terms of the GNU General Public License as published by
863d1a8abSmrg the Free Software Foundation; either version 3, or (at your option)
963d1a8abSmrg any later version.
1063d1a8abSmrg
1163d1a8abSmrg GCC is distributed in the hope that it will be useful,
1263d1a8abSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
1363d1a8abSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1463d1a8abSmrg GNU General Public License for more details.
1563d1a8abSmrg
1663d1a8abSmrg Under Section 7 of GPL version 3, you are granted additional
1763d1a8abSmrg permissions described in the GCC Runtime Library Exception, version
1863d1a8abSmrg 3.1, as published by the Free Software Foundation.
1963d1a8abSmrg
2063d1a8abSmrg You should have received a copy of the GNU General Public License and
2163d1a8abSmrg a copy of the GCC Runtime Library Exception along with this program;
2263d1a8abSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2363d1a8abSmrg <http://www.gnu.org/licenses/>. */
2463d1a8abSmrg
2563d1a8abSmrg #ifndef inhibit_libc
2663d1a8abSmrg /* Do code reading to identify a signal frame, and set the frame
2763d1a8abSmrg state data appropriately. See unwind-dw2.c for the structs. */
2863d1a8abSmrg
2963d1a8abSmrg #include <signal.h>
3063d1a8abSmrg #include <sys/ucontext.h>
3163d1a8abSmrg
3263d1a8abSmrg #define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
3363d1a8abSmrg
3463d1a8abSmrg static _Unwind_Reason_Code
alpha_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)3563d1a8abSmrg alpha_fallback_frame_state (struct _Unwind_Context *context,
3663d1a8abSmrg _Unwind_FrameState *fs)
3763d1a8abSmrg {
3863d1a8abSmrg unsigned int *pc = context->ra;
3963d1a8abSmrg struct sigcontext *sc;
4063d1a8abSmrg long new_cfa;
4163d1a8abSmrg int i;
4263d1a8abSmrg
4363d1a8abSmrg if (pc[0] != 0x47fe0410 /* mov $30,$16 */
4463d1a8abSmrg || pc[2] != 0x00000083) /* callsys */
4563d1a8abSmrg return _URC_END_OF_STACK;
4663d1a8abSmrg if (context->cfa == 0)
4763d1a8abSmrg return _URC_END_OF_STACK;
4863d1a8abSmrg if (pc[1] == 0x201f0067) /* lda $0,NR_sigreturn */
4963d1a8abSmrg sc = context->cfa;
5063d1a8abSmrg else if (pc[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */
5163d1a8abSmrg {
5263d1a8abSmrg struct rt_sigframe {
5363d1a8abSmrg siginfo_t info;
5463d1a8abSmrg ucontext_t uc;
5563d1a8abSmrg } *rt_ = context->cfa;
560fc04c29Smrg /* The void * cast is necessary to avoid an aliasing warning.
570fc04c29Smrg The aliasing warning is correct, but should not be a problem
580fc04c29Smrg because it does not alias anything. */
590fc04c29Smrg sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
6063d1a8abSmrg }
6163d1a8abSmrg else
6263d1a8abSmrg return _URC_END_OF_STACK;
6363d1a8abSmrg
6463d1a8abSmrg new_cfa = sc->sc_regs[30];
6563d1a8abSmrg fs->regs.cfa_how = CFA_REG_OFFSET;
6663d1a8abSmrg fs->regs.cfa_reg = 30;
6763d1a8abSmrg fs->regs.cfa_offset = new_cfa - (long) context->cfa;
6863d1a8abSmrg for (i = 0; i < 30; ++i)
6963d1a8abSmrg {
7063d1a8abSmrg fs->regs.reg[i].how = REG_SAVED_OFFSET;
7163d1a8abSmrg fs->regs.reg[i].loc.offset
7263d1a8abSmrg = (long) &sc->sc_regs[i] - new_cfa;
7363d1a8abSmrg }
7463d1a8abSmrg for (i = 0; i < 31; ++i)
7563d1a8abSmrg {
7663d1a8abSmrg fs->regs.reg[i+32].how = REG_SAVED_OFFSET;
7763d1a8abSmrg fs->regs.reg[i+32].loc.offset
7863d1a8abSmrg = (long) &sc->sc_fpregs[i] - new_cfa;
7963d1a8abSmrg }
8063d1a8abSmrg fs->regs.reg[64].how = REG_SAVED_OFFSET;
8163d1a8abSmrg fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa;
8263d1a8abSmrg fs->retaddr_column = 64;
8363d1a8abSmrg fs->signal_frame = 1;
8463d1a8abSmrg
8563d1a8abSmrg return _URC_NO_REASON;
8663d1a8abSmrg }
8763d1a8abSmrg
8863d1a8abSmrg #define MD_FROB_UPDATE_CONTEXT alpha_frob_update_context
8963d1a8abSmrg
9063d1a8abSmrg /* Fix up for signal handlers that don't have S flag set. */
9163d1a8abSmrg
9263d1a8abSmrg static void
alpha_frob_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs ATTRIBUTE_UNUSED)9363d1a8abSmrg alpha_frob_update_context (struct _Unwind_Context *context,
9463d1a8abSmrg _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
9563d1a8abSmrg {
9663d1a8abSmrg unsigned int *pc = context->ra;
9763d1a8abSmrg
9863d1a8abSmrg if (pc[0] == 0x47fe0410 /* mov $30,$16 */
9963d1a8abSmrg && pc[2] == 0x00000083 /* callsys */
10063d1a8abSmrg && (pc[1] == 0x201f0067 /* lda $0,NR_sigreturn */
10163d1a8abSmrg || pc[1] == 0x201f015f)) /* lda $0,NR_rt_sigreturn */
10263d1a8abSmrg _Unwind_SetSignalFrame (context, 1);
10363d1a8abSmrg }
10463d1a8abSmrg #endif
105