1/* ARM EABI compliant unwinding routines
2   Copyright (C) 2004-2015 Free Software Foundation, Inc.
3   Contributed by Paul Brook
4
5   This file is free software; you can redistribute it and/or modify it
6   under the terms of the GNU General Public License as published by the
7   Free Software Foundation; either version 3, or (at your option) any
8   later version.
9
10   This file is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   Under Section 7 of GPL version 3, you are granted additional
16   permissions described in the GCC Runtime Library Exception, version
17   3.1, as published by the Free Software Foundation.
18
19   You should have received a copy of the GNU General Public License and
20   a copy of the GCC Runtime Library Exception along with this program;
21   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22   <http://www.gnu.org/licenses/>.  */
23
24#include "unwind.h"
25
26/* We add a prototype for abort here to avoid creating a dependency on
27   target headers.  */
28extern void abort (void);
29
30typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
31
32/* Misc constants.  */
33#define R_IP    12
34#define R_SP    13
35#define R_LR    14
36#define R_PC    15
37
38#define uint32_highbit (((_uw) 1) << 31)
39
40void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
41
42/* Unwind descriptors.  */
43
44typedef struct
45{
46  _uw16 length;
47  _uw16 offset;
48} EHT16;
49
50typedef struct
51{
52  _uw length;
53  _uw offset;
54} EHT32;
55
56/* Calculate the address encoded by a 31-bit self-relative offset at address
57   P.  Copy of routine in unwind-arm.c.  */
58
59static inline _uw
60selfrel_offset31 (const _uw *p)
61{
62  _uw offset;
63
64  offset = *p;
65  /* Sign extend to 32 bits.  */
66  if (offset & (1 << 30))
67    offset |= 1u << 31;
68
69  return offset + (_uw) p;
70}
71
72
73/* Personality routine helper functions.  */
74
75#define CODE_FINISH (0xb0)
76
77/* Return the next byte of unwinding information, or CODE_FINISH if there is
78   no data remaining.  */
79static inline _uw8
80next_unwind_byte (__gnu_unwind_state * uws)
81{
82  _uw8 b;
83
84  if (uws->bytes_left == 0)
85    {
86      /* Load another word */
87      if (uws->words_left == 0)
88	return CODE_FINISH; /* Nothing left.  */
89      uws->words_left--;
90      uws->data = *(uws->next++);
91      uws->bytes_left = 3;
92    }
93  else
94    uws->bytes_left--;
95
96  /* Extract the most significant byte.  */
97  b = (uws->data >> 24) & 0xff;
98  uws->data <<= 8;
99  return b;
100}
101
102/* Execute the unwinding instructions described by UWS.  */
103_Unwind_Reason_Code
104__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
105{
106  _uw op;
107  int set_pc;
108  _uw reg;
109
110  set_pc = 0;
111  for (;;)
112    {
113      op = next_unwind_byte (uws);
114      if (op == CODE_FINISH)
115	{
116	  /* If we haven't already set pc then copy it from lr.  */
117	  if (!set_pc)
118	    {
119	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
120			       &reg);
121	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
122			       &reg);
123	      set_pc = 1;
124	    }
125	  /* Drop out of the loop.  */
126	  break;
127	}
128      if ((op & 0x80) == 0)
129	{
130	  /* vsp = vsp +- (imm6 << 2 + 4).  */
131	  _uw offset;
132
133	  offset = ((op & 0x3f) << 2) + 4;
134	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
135	  if (op & 0x40)
136	    reg -= offset;
137	  else
138	    reg += offset;
139	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
140	  continue;
141	}
142
143      if ((op & 0xf0) == 0x80)
144	{
145	  op = (op << 8) | next_unwind_byte (uws);
146	  if (op == 0x8000)
147	    {
148	      /* Refuse to unwind.  */
149	      return _URC_FAILURE;
150	    }
151	  /* Pop r4-r15 under mask.  */
152	  op = (op << 4) & 0xfff0;
153	  if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
154	      != _UVRSR_OK)
155	    return _URC_FAILURE;
156	  if (op & (1 << R_PC))
157	    set_pc = 1;
158	  continue;
159	}
160      if ((op & 0xf0) == 0x90)
161	{
162	  op &= 0xf;
163	  if (op == 13 || op == 15)
164	    /* Reserved.  */
165	    return _URC_FAILURE;
166	  /* vsp = r[nnnn].  */
167	  _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
168	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
169	  continue;
170	}
171      if ((op & 0xf0) == 0xa0)
172	{
173	  /* Pop r4-r[4+nnn], [lr].  */
174	  _uw mask;
175
176	  mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
177	  if (op & 8)
178	    mask |= (1 << R_LR);
179	  if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
180	      != _UVRSR_OK)
181	    return _URC_FAILURE;
182	  continue;
183	}
184      if ((op & 0xf0) == 0xb0)
185	{
186	  /* op == 0xb0 already handled.  */
187	  if (op == 0xb1)
188	    {
189	      op = next_unwind_byte (uws);
190	      if (op == 0 || ((op & 0xf0) != 0))
191		/* Spare.  */
192		return _URC_FAILURE;
193	      /* Pop r0-r4 under mask.  */
194	      if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
195		  != _UVRSR_OK)
196		return _URC_FAILURE;
197	      continue;
198	    }
199	  if (op == 0xb2)
200	    {
201	      /* vsp = vsp + 0x204 + (uleb128 << 2).  */
202	      int shift;
203
204	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
205			       &reg);
206	      op = next_unwind_byte (uws);
207	      shift = 2;
208	      while (op & 0x80)
209		{
210		  reg += ((op & 0x7f) << shift);
211		  shift += 7;
212		  op = next_unwind_byte (uws);
213		}
214	      reg += ((op & 0x7f) << shift) + 0x204;
215	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
216			       &reg);
217	      continue;
218	    }
219	  if (op == 0xb3)
220	    {
221	      /* Pop VFP registers with fldmx.  */
222	      op = next_unwind_byte (uws);
223	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
224	      if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
225		  != _UVRSR_OK)
226		return _URC_FAILURE;
227	      continue;
228	    }
229	  if ((op & 0xfc) == 0xb4)  /* Obsolete FPA.  */
230	    return _URC_FAILURE;
231
232	  /* op & 0xf8 == 0xb8.  */
233	  /* Pop VFP D[8]-D[8+nnn] with fldmx.  */
234	  op = 0x80000 | ((op & 7) + 1);
235	  if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
236	      != _UVRSR_OK)
237	    return _URC_FAILURE;
238	  continue;
239	}
240      if ((op & 0xf0) == 0xc0)
241	{
242	  if (op == 0xc6)
243	    {
244	      /* Pop iWMMXt D registers.  */
245	      op = next_unwind_byte (uws);
246	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
247	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
248		  != _UVRSR_OK)
249		return _URC_FAILURE;
250	      continue;
251	    }
252	  if (op == 0xc7)
253	    {
254	      op = next_unwind_byte (uws);
255	      if (op == 0 || (op & 0xf0) != 0)
256		/* Spare.  */
257		return _URC_FAILURE;
258	      /* Pop iWMMXt wCGR{3,2,1,0} under mask.  */
259	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
260		  != _UVRSR_OK)
261		return _URC_FAILURE;
262	      continue;
263	    }
264	  if ((op & 0xf8) == 0xc0)
265	    {
266	      /* Pop iWMMXt wR[10]-wR[10+nnn].  */
267	      op = 0xa0000 | ((op & 0xf) + 1);
268	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
269		  != _UVRSR_OK)
270		return _URC_FAILURE;
271	      continue;
272	    }
273	  if (op == 0xc8)
274	    {
275              /* Pop VFPv3 registers D[16+ssss]-D[16+ssss+cccc] with vldm.  */
276              op = next_unwind_byte (uws);
277              op = (((op & 0xf0) + 16) << 12) | ((op & 0xf) + 1);
278              if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
279                  != _UVRSR_OK)
280                return _URC_FAILURE;
281              continue;
282	    }
283	  if (op == 0xc9)
284	    {
285	      /* Pop VFP registers with fldmd.  */
286	      op = next_unwind_byte (uws);
287	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
288	      if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
289		  != _UVRSR_OK)
290		return _URC_FAILURE;
291	      continue;
292	    }
293	  /* Spare.  */
294	  return _URC_FAILURE;
295	}
296      if ((op & 0xf8) == 0xd0)
297	{
298	  /* Pop VFP D[8]-D[8+nnn] with fldmd.  */
299	  op = 0x80000 | ((op & 7) + 1);
300	  if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
301	      != _UVRSR_OK)
302	    return _URC_FAILURE;
303	  continue;
304	}
305      /* Spare.  */
306      return _URC_FAILURE;
307    }
308  return _URC_OK;
309}
310
311
312/* Execute the unwinding instructions associated with a frame.  UCBP and
313   CONTEXT are the current exception object and virtual CPU state
314   respectively.  */
315
316_Unwind_Reason_Code
317__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
318{
319  _uw *ptr;
320  __gnu_unwind_state uws;
321
322  ptr = (_uw *) ucbp->pr_cache.ehtp;
323  /* Skip over the personality routine address.  */
324  ptr++;
325  /* Setup the unwinder state.  */
326  uws.data = (*ptr) << 8;
327  uws.next = ptr + 1;
328  uws.bytes_left = 3;
329  uws.words_left = ((*ptr) >> 24) & 0xff;
330
331  return __gnu_unwind_execute (context, &uws);
332}
333
334/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
335
336static inline _Unwind_Control_Block *
337unwind_UCB_from_context (_Unwind_Context * context)
338{
339  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
340}
341
342/* Get the start address of the function being unwound.  */
343
344_Unwind_Ptr
345_Unwind_GetRegionStart (_Unwind_Context * context)
346{
347  _Unwind_Control_Block *ucbp;
348
349  ucbp = unwind_UCB_from_context (context);
350  return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
351}
352
353/* Find the Language specific exception data.  */
354
355void *
356_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
357{
358  _Unwind_Control_Block *ucbp;
359  _uw *ptr;
360
361  /* Get a pointer to the exception table entry.  */
362  ucbp = unwind_UCB_from_context (context);
363  ptr = (_uw *) ucbp->pr_cache.ehtp;
364  /* Skip the personality routine address.  */
365  ptr++;
366  /* Skip the unwind opcodes.  */
367  ptr += (((*ptr) >> 24) & 0xff) + 1;
368
369  return ptr;
370}
371
372
373/* These two should never be used.  */
374
375_Unwind_Ptr
376_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused)))
377{
378  abort ();
379}
380
381_Unwind_Ptr
382_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
383{
384  abort ();
385}
386