]>
Commit | Line | Data |
---|---|---|
dd552284 | 1 | /* DWARF2 EH unwinding support for TILEPro. |
ac1dca3c | 2 | Copyright (C) 2011-2014 Free Software Foundation, Inc. |
dd552284 WL |
3 | Contributed by Walter Lee (walt@tilera.com) |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | Under Section 7 of GPL version 3, you are granted additional | |
18 | permissions described in the GCC Runtime Library Exception, version | |
19 | 3.1, as published by the Free Software Foundation. | |
20 | ||
21 | You should have received a copy of the GNU General Public License and | |
22 | a copy of the GCC Runtime Library Exception along with this program; | |
23 | see 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) | |
46 | sigreturn_asm (TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn); | |
47 | #define SIGRETURN_LEN 16 | |
48 | extern char __rt_sigreturn[]; | |
49 | ||
50 | #define MD_FALLBACK_FRAME_STATE_FOR tile_fallback_frame_state | |
51 | ||
52 | static _Unwind_Reason_Code | |
53 | tile_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]; | |
1bde7dab | 63 | siginfo_t info; |
dd552284 WL |
64 | struct ucontext 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; | |
53d68b9f | 81 | fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; |
dd552284 WL |
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 */ |