1/* DWARF2 EH unwinding support for TILEPro. 2 Copyright (C) 2011-2020 Free Software Foundation, Inc. 3 Contributed by Walter Lee (walt@tilera.com) 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17Under Section 7 of GPL version 3, you are granted additional 18permissions described in the GCC Runtime Library Exception, version 193.1, as published by the Free Software Foundation. 20 21You should have received a copy of the GNU General Public License and 22a copy of the GCC Runtime Library Exception along with this program; 23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24<http://www.gnu.org/licenses/>. */ 25 26#ifndef inhibit_libc 27 28#include <arch/abi.h> 29#include <signal.h> 30#include <sys/ucontext.h> 31#include <linux/unistd.h> 32 33/* Macro to define a copy of the kernel's __rt_sigreturn function 34 (in arch/tile/kernel/entry.S). If that function is changed, 35 this one needs to be changed to match it. */ 36#define _sigreturn_asm(REG, NR) asm( \ 37 ".pushsection .text.__rt_sigreturn,\"a\"\n" \ 38 ".global __rt_sigreturn\n" \ 39 ".type __rt_sigreturn,@function\n" \ 40 "__rt_sigreturn:\n" \ 41 "moveli " #REG ", " #NR "\n" \ 42 "swint1\n" \ 43 ".size __rt_sigreturn, . - __rt_sigreturn\n" \ 44 ".popsection") 45#define sigreturn_asm(REG, NR) _sigreturn_asm(REG, NR) 46sigreturn_asm (TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn); 47#define SIGRETURN_LEN 16 48extern char __rt_sigreturn[]; 49 50#define MD_FALLBACK_FRAME_STATE_FOR tile_fallback_frame_state 51 52static _Unwind_Reason_Code 53tile_fallback_frame_state (struct _Unwind_Context *context, 54 _Unwind_FrameState *fs) 55{ 56 unsigned char *pc = context->ra; 57 struct sigcontext *sc; 58 long new_cfa; 59 int i; 60 61 struct rt_sigframe { 62 unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; 63 siginfo_t info; 64 ucontext_t uc; 65 } *rt_; 66 67 /* Return if this is not a signal handler. */ 68 if (memcmp (pc, __rt_sigreturn, SIGRETURN_LEN) != 0) 69 return _URC_END_OF_STACK; 70 71 /* It was a signal handler; update the reported PC to point to our 72 copy, since that will be findable with dladdr() and therefore 73 somewhat easier to help understand what actually happened. */ 74 context->ra = __rt_sigreturn; 75 76 rt_ = context->cfa; 77 sc = &rt_->uc.uc_mcontext; 78 79 new_cfa = sc->sp; 80 fs->regs.cfa_how = CFA_REG_OFFSET; 81 fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; 82 fs->regs.cfa_offset = new_cfa - (long) context->cfa; 83 84 for (i = 0; i < 56; ++i) 85 { 86 fs->regs.reg[i].how = REG_SAVED_OFFSET; 87 fs->regs.reg[i].loc.offset 88 = (long)&sc->gregs[i] - new_cfa; 89 } 90 91 fs->regs.reg[56].how = REG_SAVED_OFFSET; 92 fs->regs.reg[56].loc.offset = (long)&sc->pc - new_cfa; 93 fs->retaddr_column = 56; 94 fs->signal_frame = 1; 95 96 return _URC_NO_REASON; 97} 98 99#endif /* ifdef inhibit_libc */ 100