1 /* DWARF2 EH unwinding support for Blackfin.
2    Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10 
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19 
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 <http://www.gnu.org/licenses/>.  */
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    Don't use this at all if inhibit_libc is used.  */
28 
29 #ifndef inhibit_libc
30 
31 #include <signal.h>
32 #include <sys/ucontext.h>
33 
34 #define MD_FALLBACK_FRAME_STATE_FOR bfin_fallback_frame_state
35 
36 static _Unwind_Reason_Code
bfin_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)37 bfin_fallback_frame_state (struct _Unwind_Context *context,
38 			   _Unwind_FrameState *fs)
39 {
40   unsigned char *pc = context->ra;
41   struct sigcontext *sc;
42   long new_cfa;
43 
44   /* P0=__NR_rt_sigreturn (X); EXCPT  0x0; */
45   if (*(unsigned short *)pc == 0xe128
46       && *(unsigned short *)(pc + 2) == 0x00ad
47       && *(unsigned short *)(pc + 4) == 0x00a0)
48     {
49       struct rt_sigframe {
50 	int sig;
51 	siginfo_t *pinfo;
52 	void *puc;
53 	char retcode[8];
54 	siginfo_t info;
55 	ucontext_t uc;
56       } *rt_ = context->cfa;
57 
58       /* The void * cast is necessary to avoid an aliasing warning.
59          The aliasing warning is correct, but should not be a problem
60          because it does not alias anything.  */
61       sc = (struct sigcontext *)(void *)&rt_->uc.uc_mcontext.gregs;
62     }
63   else
64     return _URC_END_OF_STACK;
65 
66   new_cfa = sc->sc_usp;
67   fs->regs.cfa_how = CFA_REG_OFFSET;
68   fs->regs.cfa_reg = 14;
69   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
70 
71   fs->regs.reg[0].how = REG_SAVED_OFFSET;
72   fs->regs.reg[0].loc.offset = (long)&sc->sc_r0 - new_cfa;
73   fs->regs.reg[1].how = REG_SAVED_OFFSET;
74   fs->regs.reg[1].loc.offset = (long)&sc->sc_r1 - new_cfa;
75   fs->regs.reg[2].how = REG_SAVED_OFFSET;
76   fs->regs.reg[2].loc.offset = (long)&sc->sc_r2 - new_cfa;
77   fs->regs.reg[3].how = REG_SAVED_OFFSET;
78   fs->regs.reg[3].loc.offset = (long)&sc->sc_r3 - new_cfa;
79   fs->regs.reg[4].how = REG_SAVED_OFFSET;
80   fs->regs.reg[4].loc.offset = (long)&sc->sc_r4 - new_cfa;
81   fs->regs.reg[5].how = REG_SAVED_OFFSET;
82   fs->regs.reg[5].loc.offset = (long)&sc->sc_r5 - new_cfa;
83   fs->regs.reg[6].how = REG_SAVED_OFFSET;
84   fs->regs.reg[6].loc.offset = (long)&sc->sc_r6 - new_cfa;
85   fs->regs.reg[7].how = REG_SAVED_OFFSET;
86   fs->regs.reg[7].loc.offset = (long)&sc->sc_r7 - new_cfa;
87   fs->regs.reg[8].how = REG_SAVED_OFFSET;
88   fs->regs.reg[8].loc.offset = (long)&sc->sc_p0 - new_cfa;
89   fs->regs.reg[9].how = REG_SAVED_OFFSET;
90   fs->regs.reg[9].loc.offset = (long)&sc->sc_p1 - new_cfa;
91   fs->regs.reg[10].how = REG_SAVED_OFFSET;
92   fs->regs.reg[10].loc.offset = (long)&sc->sc_p2 - new_cfa;
93   fs->regs.reg[11].how = REG_SAVED_OFFSET;
94   fs->regs.reg[11].loc.offset = (long)&sc->sc_p3 - new_cfa;
95   fs->regs.reg[12].how = REG_SAVED_OFFSET;
96   fs->regs.reg[12].loc.offset = (long)&sc->sc_p4 - new_cfa;
97   fs->regs.reg[13].how = REG_SAVED_OFFSET;
98   fs->regs.reg[13].loc.offset = (long)&sc->sc_p5 - new_cfa;
99 
100   fs->regs.reg[15].how = REG_SAVED_OFFSET;
101   fs->regs.reg[15].loc.offset = (long)&sc->sc_fp - new_cfa;
102   fs->regs.reg[16].how = REG_SAVED_OFFSET;
103   fs->regs.reg[16].loc.offset = (long)&sc->sc_i0 - new_cfa;
104   fs->regs.reg[17].how = REG_SAVED_OFFSET;
105   fs->regs.reg[17].loc.offset = (long)&sc->sc_i1 - new_cfa;
106   fs->regs.reg[18].how = REG_SAVED_OFFSET;
107   fs->regs.reg[18].loc.offset = (long)&sc->sc_i2 - new_cfa;
108   fs->regs.reg[19].how = REG_SAVED_OFFSET;
109   fs->regs.reg[19].loc.offset = (long)&sc->sc_i3 - new_cfa;
110   fs->regs.reg[20].how = REG_SAVED_OFFSET;
111   fs->regs.reg[20].loc.offset = (long)&sc->sc_b0 - new_cfa;
112   fs->regs.reg[21].how = REG_SAVED_OFFSET;
113   fs->regs.reg[21].loc.offset = (long)&sc->sc_b1 - new_cfa;
114   fs->regs.reg[22].how = REG_SAVED_OFFSET;
115   fs->regs.reg[22].loc.offset = (long)&sc->sc_b2 - new_cfa;
116   fs->regs.reg[23].how = REG_SAVED_OFFSET;
117   fs->regs.reg[23].loc.offset = (long)&sc->sc_b3 - new_cfa;
118   fs->regs.reg[24].how = REG_SAVED_OFFSET;
119   fs->regs.reg[24].loc.offset = (long)&sc->sc_l0 - new_cfa;
120   fs->regs.reg[25].how = REG_SAVED_OFFSET;
121   fs->regs.reg[25].loc.offset = (long)&sc->sc_l1 - new_cfa;
122   fs->regs.reg[26].how = REG_SAVED_OFFSET;
123   fs->regs.reg[26].loc.offset = (long)&sc->sc_l2 - new_cfa;
124   fs->regs.reg[27].how = REG_SAVED_OFFSET;
125   fs->regs.reg[27].loc.offset = (long)&sc->sc_l3 - new_cfa;
126   fs->regs.reg[28].how = REG_SAVED_OFFSET;
127   fs->regs.reg[28].loc.offset = (long)&sc->sc_m0 - new_cfa;
128   fs->regs.reg[29].how = REG_SAVED_OFFSET;
129   fs->regs.reg[29].loc.offset = (long)&sc->sc_m1 - new_cfa;
130   fs->regs.reg[30].how = REG_SAVED_OFFSET;
131   fs->regs.reg[30].loc.offset = (long)&sc->sc_m2 - new_cfa;
132   fs->regs.reg[31].how = REG_SAVED_OFFSET;
133   fs->regs.reg[31].loc.offset = (long)&sc->sc_m3 - new_cfa;
134   /* FIXME: Handle A0, A1, CC.  */
135   fs->regs.reg[35].how = REG_SAVED_OFFSET;
136   fs->regs.reg[35].loc.offset = (long)&sc->sc_rets - new_cfa;
137   fs->regs.reg[36].how = REG_SAVED_OFFSET;
138   fs->regs.reg[36].loc.offset = (long)&sc->sc_pc - new_cfa;
139   fs->regs.reg[37].how = REG_SAVED_OFFSET;
140   fs->regs.reg[37].loc.offset = (long)&sc->sc_retx - new_cfa;
141 
142   fs->regs.reg[40].how = REG_SAVED_OFFSET;
143   fs->regs.reg[40].loc.offset = (long)&sc->sc_astat - new_cfa;
144   fs->regs.reg[41].how = REG_SAVED_OFFSET;
145   fs->regs.reg[41].loc.offset = (long)&sc->sc_seqstat - new_cfa;
146 
147   fs->regs.reg[44].how = REG_SAVED_OFFSET;
148   fs->regs.reg[44].loc.offset = (long)&sc->sc_lt0 - new_cfa;
149   fs->regs.reg[45].how = REG_SAVED_OFFSET;
150   fs->regs.reg[45].loc.offset = (long)&sc->sc_lt1 - new_cfa;
151   fs->regs.reg[46].how = REG_SAVED_OFFSET;
152   fs->regs.reg[46].loc.offset = (long)&sc->sc_lc0 - new_cfa;
153   fs->regs.reg[47].how = REG_SAVED_OFFSET;
154   fs->regs.reg[47].loc.offset = (long)&sc->sc_lc1 - new_cfa;
155   fs->regs.reg[48].how = REG_SAVED_OFFSET;
156   fs->regs.reg[48].loc.offset = (long)&sc->sc_lb0 - new_cfa;
157   fs->regs.reg[49].how = REG_SAVED_OFFSET;
158   fs->regs.reg[49].loc.offset = (long)&sc->sc_lb1 - new_cfa;
159   fs->retaddr_column = 35;
160 
161   return _URC_NO_REASON;
162 }
163 
164 #endif /* ifdef inhibit_libc */
165