OSDN Git Service

struct siginfo vs. siginfo_t
[pf3gnuchains/gcc-fork.git] / libgcc / config / sh / linux-unwind.h
1 /* DWARF2 EH unwinding support for SH Linux.
2    Copyright (C) 2004, 2005, 2006, 2007, 2009, 2012 Free Software Foundation,
3    Inc.
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
27 /* Do code reading to identify a signal frame, and set the frame
28    state data appropriately.  See unwind-dw2.c for the structs.
29    Don't use this at all if inhibit_libc is used.  */
30
31 #ifndef inhibit_libc
32
33 #include <signal.h>
34 #include <sys/ucontext.h>
35 #include "insn-constants.h"
36
37 # if defined (__SH5__)
38 #define SH_DWARF_FRAME_GP0      0
39 #define SH_DWARF_FRAME_FP0      77
40 #define SH_DWARF_FRAME_BT0      68
41 #define SH_DWARF_FRAME_PR_MEDIA 18
42 #define SH_DWARF_FRAME_SR       65
43 #define SH_DWARF_FRAME_FPSCR    76
44 #else
45 #define SH_DWARF_FRAME_GP0      0
46 #define SH_DWARF_FRAME_FP0      25
47 #define SH_DWARF_FRAME_XD0      87
48 #define SH_DWARF_FRAME_PR       17
49 #define SH_DWARF_FRAME_GBR      18
50 #define SH_DWARF_FRAME_MACH     20
51 #define SH_DWARF_FRAME_MACL     21
52 #define SH_DWARF_FRAME_PC       16
53 #define SH_DWARF_FRAME_SR       22
54 #define SH_DWARF_FRAME_FPUL     23
55 #define SH_DWARF_FRAME_FPSCR    24
56 #endif /* defined (__SH5__) */
57
58 #if defined (__SH5__)
59
60 #define MD_FALLBACK_FRAME_STATE_FOR shmedia_fallback_frame_state
61
62 static _Unwind_Reason_Code
63 shmedia_fallback_frame_state (struct _Unwind_Context *context,
64                               _Unwind_FrameState *fs)
65 {
66   unsigned char *pc = context->ra;
67   struct sigcontext *sc;
68   long new_cfa;
69   int i, r;
70
71   /* movi 0x10,r9; shori 0x77,r9; trapa r9; nop (sigreturn)  */
72   /* movi 0x10,r9; shori 0xad,r9; trapa r9; nop (rt_sigreturn)  */
73   if ((*(unsigned long *) (pc-1)  == 0xcc004090)
74       && (*(unsigned long *) (pc+3)  == 0xc801dc90)
75       && (*(unsigned long *) (pc+7)  == 0x6c91fff0)
76       && (*(unsigned long *) (pc+11)  == 0x6ff0fff0))
77     sc = context->cfa;
78   else if ((*(unsigned long *) (pc-1)  == 0xcc004090)
79            && (*(unsigned long *) (pc+3)  == 0xc802b490)
80            && (*(unsigned long *) (pc+7)  == 0x6c91fff0)
81            && (*(unsigned long *) (pc+11)  == 0x6ff0fff0))
82     {
83       struct rt_sigframe {
84         siginfo_t *pinfo;
85         void *puc;
86         siginfo_t info;
87         struct ucontext uc;
88       } *rt_ = context->cfa;
89       /* The void * cast is necessary to avoid an aliasing warning.
90          The aliasing warning is correct, but should not be a problem
91          because it does not alias anything.  */
92       sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
93     }
94   else
95     return _URC_END_OF_STACK;
96
97   new_cfa = sc->sc_regs[15];
98   fs->regs.cfa_how = CFA_REG_OFFSET;
99   fs->regs.cfa_reg = 15;
100   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
101
102   for (i = 0; i < 63; i++)
103     {
104       if (i == 15)
105         continue;
106
107       fs->regs.reg[i].how = REG_SAVED_OFFSET;
108       fs->regs.reg[i].loc.offset
109         = (long)&(sc->sc_regs[i]) - new_cfa;
110     }
111
112   fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET;
113   fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset
114     = (long)&(sc->sc_sr) - new_cfa;
115
116   r = SH_DWARF_FRAME_BT0;
117   for (i = 0; i < 8; i++)
118     {
119       fs->regs.reg[r+i].how = REG_SAVED_OFFSET;
120       fs->regs.reg[r+i].loc.offset
121         = (long)&(sc->sc_tregs[i]) - new_cfa;
122     }
123
124   r = SH_DWARF_FRAME_FP0;
125   for (i = 0; i < 32; i++)
126     {
127       fs->regs.reg[r+i].how = REG_SAVED_OFFSET;
128       fs->regs.reg[r+i].loc.offset
129         = (long)&(sc->sc_fpregs[i]) - new_cfa;
130     }
131
132   fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET;
133   fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset
134     = (long)&(sc->sc_fpscr) - new_cfa;
135
136   /* We use the slot for the zero register to save return address.  */
137   fs->regs.reg[63].how = REG_SAVED_OFFSET;
138   fs->regs.reg[63].loc.offset
139     = (long)&(sc->sc_pc) - new_cfa;
140   fs->retaddr_column = 63;
141   fs->signal_frame = 1;
142   return _URC_NO_REASON;
143 }
144
145 #else /* defined (__SH5__) */
146
147 #define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state
148
149 static _Unwind_Reason_Code
150 sh_fallback_frame_state (struct _Unwind_Context *context,
151                          _Unwind_FrameState *fs)
152 {
153   unsigned char *pc = context->ra;
154   struct sigcontext *sc;
155   long new_cfa;
156   int i;
157 #if defined (__SH3E__) || defined (__SH4__)
158   int r;
159 #endif
160
161   /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77  (sigreturn)  */
162   /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad  (rt_sigreturn)  */
163   /* Newer kernel uses pad instructions to avoid an SH-4 core bug.  */
164   /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
165      or r0,r0; 1: .short 0x77  (sigreturn)  */
166   /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
167      or r0,r0; 1: .short 0xad  (rt_sigreturn)  */
168   if (((*(unsigned short *) (pc+0)  == 0x9300)
169        && (*(unsigned short *) (pc+2)  == 0xc310)
170        && (*(unsigned short *) (pc+4)  == 0x0077))
171       || (((*(unsigned short *) (pc+0)  == 0x9305)
172            && (*(unsigned short *) (pc+2)  == 0xc310)
173            && (*(unsigned short *) (pc+14)  == 0x0077))))
174     sc = context->cfa;
175   else if (((*(unsigned short *) (pc+0) == 0x9300)
176             && (*(unsigned short *) (pc+2)  == 0xc310)
177             && (*(unsigned short *) (pc+4)  == 0x00ad))
178            || (((*(unsigned short *) (pc+0) == 0x9305)
179                 && (*(unsigned short *) (pc+2)  == 0xc310)
180                 && (*(unsigned short *) (pc+14)  == 0x00ad))))
181     {
182       struct rt_sigframe {
183         siginfo_t info;
184         struct ucontext uc;
185       } *rt_ = context->cfa;
186       /* The void * cast is necessary to avoid an aliasing warning.
187          The aliasing warning is correct, but should not be a problem
188          because it does not alias anything.  */
189       sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
190     }
191   else
192     return _URC_END_OF_STACK;
193
194   new_cfa = sc->sc_regs[15];
195   fs->regs.cfa_how = CFA_REG_OFFSET;
196   fs->regs.cfa_reg = 15;
197   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
198
199   for (i = 0; i < 15; i++)
200     {
201       fs->regs.reg[i].how = REG_SAVED_OFFSET;
202       fs->regs.reg[i].loc.offset
203         = (long)&(sc->sc_regs[i]) - new_cfa;
204     }
205
206   fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET;
207   fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset
208     = (long)&(sc->sc_pr) - new_cfa;
209   fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET;
210   fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset
211     = (long)&(sc->sc_sr) - new_cfa;
212   fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET;
213   fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset
214     = (long)&(sc->sc_gbr) - new_cfa;
215   fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET;
216   fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset
217     = (long)&(sc->sc_mach) - new_cfa;
218   fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET;
219   fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset
220     = (long)&(sc->sc_macl) - new_cfa;
221
222 #if defined (__SH3E__) || defined (__SH4__)
223   r = SH_DWARF_FRAME_FP0;
224   for (i = 0; i < 16; i++)
225     {
226       fs->regs.reg[r+i].how = REG_SAVED_OFFSET;
227       fs->regs.reg[r+i].loc.offset
228         = (long)&(sc->sc_fpregs[i]) - new_cfa;
229     }
230
231   r = SH_DWARF_FRAME_XD0;
232   for (i = 0; i < 8; i++)
233     {
234       fs->regs.reg[r+i].how = REG_SAVED_OFFSET;
235       fs->regs.reg[r+i].loc.offset
236         = (long)&(sc->sc_xfpregs[2*i]) - new_cfa;
237     }
238
239   fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET;
240   fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset
241     = (long)&(sc->sc_fpul) - new_cfa;
242   fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET;
243   fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset
244     = (long)&(sc->sc_fpscr) - new_cfa;
245 #endif
246
247   fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET;
248   fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset
249     = (long)&(sc->sc_pc) - new_cfa;
250   fs->retaddr_column = SH_DWARF_FRAME_PC;
251   fs->signal_frame = 1;
252   return _URC_NO_REASON;
253 }
254 #endif /* defined (__SH5__) */
255
256 #endif /* inhibit_libc */