1/* DWARF2 EH unwinding support for Nios II Linux. 2 Copyright (C) 2008-2020 Free Software Foundation, Inc. 3 4This file is free software; you can redistribute it and/or modify it 5under the terms of the GNU General Public License as published by the 6Free Software Foundation; either version 3, or (at your option) any 7later version. 8 9This file is distributed in the hope that it will be useful, but 10WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12General Public License for more details. 13 14Under Section 7 of GPL version 3, you are granted additional 15permissions described in the GCC Runtime Library Exception, version 163.1, as published by the Free Software Foundation. 17 18You should have received a copy of the GNU General Public License and 19a copy of the GCC Runtime Library Exception along with this program; 20see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 21<http://www.gnu.org/licenses/>. */ 22 23#ifndef inhibit_libc 24 25/* Do code reading to identify a signal frame, and set the frame 26 state data appropriately. See unwind-dw2.c for the structs. 27 The corresponding bits in the Linux kernel are in 28 arch/nios2/kernel/signal.c. */ 29 30#include <signal.h> 31#include <asm/unistd.h> 32 33/* Exactly the same layout as the kernel structures, unique names. */ 34struct nios2_mcontext { 35 int version; 36 int gregs[32]; 37}; 38 39struct nios2_ucontext { 40 unsigned long uc_flags; 41 ucontext_t *uc_link; 42 stack_t uc_stack; 43 struct nios2_mcontext uc_mcontext; 44 sigset_t uc_sigmask; /* mask last for extensibility */ 45}; 46 47#define MD_FALLBACK_FRAME_STATE_FOR nios2_fallback_frame_state 48 49static _Unwind_Reason_Code 50nios2_fallback_frame_state (struct _Unwind_Context *context, 51 _Unwind_FrameState *fs) 52{ 53 u_int32_t *pc = (u_int32_t *) context->ra; 54 _Unwind_Ptr new_cfa; 55 56 /* The expected sequence of instructions is: 57 movi r2,(rt_sigreturn) 58 trap 59 Check for the trap first. */ 60 if (pc[1] != 0x003b683a) 61 return _URC_END_OF_STACK; 62 63#define NIOS2_REG(NUM,NAME) \ 64 (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \ 65 fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr)&(regs->NAME) - new_cfa) 66 67 if (pc[0] == (0x00800004 | (__NR_rt_sigreturn << 6))) 68 { 69 struct rt_sigframe { 70 siginfo_t info; 71 struct nios2_ucontext uc; 72 } *rt_ = context->cfa; 73 struct nios2_mcontext *regs = &rt_->uc.uc_mcontext; 74 int i; 75 76 /* MCONTEXT_VERSION is defined to 2 in the kernel. */ 77 if (regs->version != 2) 78 return _URC_END_OF_STACK; 79 80 /* The CFA is the user's incoming stack pointer value. */ 81 new_cfa = (_Unwind_Ptr)regs->gregs[28]; 82 fs->regs.cfa_how = CFA_REG_OFFSET; 83 fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; 84 fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; 85 86 /* The sequential registers. */ 87 for (i = 1; i < 24; i++) 88 NIOS2_REG (i, gregs[i-1]); 89 90 /* The random registers. The kernel stores these in a funny order 91 in the gregs array. */ 92 NIOS2_REG (RA_REGNO, gregs[23]); 93 NIOS2_REG (FP_REGNO, gregs[24]); 94 NIOS2_REG (GP_REGNO, gregs[25]); 95 NIOS2_REG (EA_REGNO, gregs[27]); 96 97 fs->retaddr_column = EA_REGNO; 98 fs->signal_frame = 1; 99 100 return _URC_NO_REASON; 101 } 102#undef NIOS2_REG 103 return _URC_END_OF_STACK; 104} 105#endif 106