1169689Skan/* ARM EABI compliant unwinding routines
2169689Skan   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3169689Skan   Contributed by Paul Brook
4169689Skan
5169689Skan   This file is free software; you can redistribute it and/or modify it
6169689Skan   under the terms of the GNU General Public License as published by the
7169689Skan   Free Software Foundation; either version 2, or (at your option) any
8169689Skan   later version.
9169689Skan
10169689Skan   In addition to the permissions in the GNU General Public License, the
11169689Skan   Free Software Foundation gives you unlimited permission to link the
12169689Skan   compiled version of this file into combinations with other programs,
13169689Skan   and to distribute those combinations without any restriction coming
14169689Skan   from the use of this file.  (The General Public License restrictions
15169689Skan   do apply in other respects; for example, they cover modification of
16169689Skan   the file, and distribution when not linked into a combine
17169689Skan   executable.)
18169689Skan
19169689Skan   This file is distributed in the hope that it will be useful, but
20169689Skan   WITHOUT ANY WARRANTY; without even the implied warranty of
21169689Skan   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22169689Skan   General Public License for more details.
23169689Skan
24169689Skan   You should have received a copy of the GNU General Public License
25169689Skan   along with this program; see the file COPYING.  If not, write to
26169689Skan   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27169689Skan   Boston, MA 02110-1301, USA.  */
28169689Skan#include "unwind.h"
29169689Skan
30169689Skan/* We add a prototype for abort here to avoid creating a dependency on
31169689Skan   target headers.  */
32169689Skanextern void abort (void);
33169689Skan
34169689Skantypedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
35169689Skan
36169689Skan/* Misc constants.  */
37169689Skan#define R_IP    12
38169689Skan#define R_SP    13
39169689Skan#define R_LR    14
40169689Skan#define R_PC    15
41169689Skan
42169689Skan#define uint32_highbit (((_uw) 1) << 31)
43169689Skan
44169689Skanvoid __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
45169689Skan
46169689Skan/* Unwind descriptors.  */
47169689Skan
48169689Skantypedef struct
49169689Skan{
50169689Skan  _uw16 length;
51169689Skan  _uw16 offset;
52169689Skan} EHT16;
53169689Skan
54169689Skantypedef struct
55169689Skan{
56169689Skan  _uw length;
57169689Skan  _uw offset;
58169689Skan} EHT32;
59169689Skan
60169689Skan/* Calculate the address encoded by a 31-bit self-relative offset at address
61169689Skan   P.  Copy of routine in unwind-arm.c.  */
62169689Skan
63169689Skanstatic inline _uw
64169689Skanselfrel_offset31 (const _uw *p)
65169689Skan{
66169689Skan  _uw offset;
67169689Skan
68169689Skan  offset = *p;
69169689Skan  /* Sign extend to 32 bits.  */
70169689Skan  if (offset & (1 << 30))
71169689Skan    offset |= 1u << 31;
72169689Skan
73169689Skan  return offset + (_uw) p;
74169689Skan}
75169689Skan
76169689Skan
77169689Skan/* Personality routine helper functions.  */
78169689Skan
79169689Skan#define CODE_FINISH (0xb0)
80169689Skan
81169689Skan/* Return the next byte of unwinding information, or CODE_FINISH if there is
82169689Skan   no data remaining.  */
83169689Skanstatic inline _uw8
84169689Skannext_unwind_byte (__gnu_unwind_state * uws)
85169689Skan{
86169689Skan  _uw8 b;
87169689Skan
88169689Skan  if (uws->bytes_left == 0)
89169689Skan    {
90169689Skan      /* Load another word */
91169689Skan      if (uws->words_left == 0)
92169689Skan	return CODE_FINISH; /* Nothing left.  */
93169689Skan      uws->words_left--;
94169689Skan      uws->data = *(uws->next++);
95169689Skan      uws->bytes_left = 3;
96169689Skan    }
97169689Skan  else
98169689Skan    uws->bytes_left--;
99169689Skan
100169689Skan  /* Extract the most significant byte.  */
101169689Skan  b = (uws->data >> 24) & 0xff;
102169689Skan  uws->data <<= 8;
103169689Skan  return b;
104169689Skan}
105169689Skan
106169689Skan/* Execute the unwinding instructions described by UWS.  */
107169689Skan_Unwind_Reason_Code
108169689Skan__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
109169689Skan{
110169689Skan  _uw op;
111169689Skan  int set_pc;
112169689Skan  _uw reg;
113169689Skan
114169689Skan  set_pc = 0;
115169689Skan  for (;;)
116169689Skan    {
117169689Skan      op = next_unwind_byte (uws);
118169689Skan      if (op == CODE_FINISH)
119169689Skan	{
120169689Skan	  /* If we haven't already set pc then copy it from lr.  */
121169689Skan	  if (!set_pc)
122169689Skan	    {
123169689Skan	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
124169689Skan			       &reg);
125169689Skan	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
126169689Skan			       &reg);
127169689Skan	      set_pc = 1;
128169689Skan	    }
129169689Skan	  /* Drop out of the loop.  */
130169689Skan	  break;
131169689Skan	}
132169689Skan      if ((op & 0x80) == 0)
133169689Skan	{
134169689Skan	  /* vsp = vsp +- (imm6 << 2 + 4).  */
135169689Skan	  _uw offset;
136169689Skan
137169689Skan	  offset = ((op & 0x3f) << 2) + 4;
138169689Skan	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
139169689Skan	  if (op & 0x40)
140169689Skan	    reg -= offset;
141169689Skan	  else
142169689Skan	    reg += offset;
143169689Skan	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
144169689Skan	  continue;
145169689Skan	}
146169689Skan
147169689Skan      if ((op & 0xf0) == 0x80)
148169689Skan	{
149169689Skan	  op = (op << 8) | next_unwind_byte (uws);
150169689Skan	  if (op == 0x8000)
151169689Skan	    {
152169689Skan	      /* Refuse to unwind.  */
153169689Skan	      return _URC_FAILURE;
154169689Skan	    }
155169689Skan	  /* Pop r4-r15 under mask.  */
156169689Skan	  op = (op << 4) & 0xfff0;
157169689Skan	  if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
158169689Skan	      != _UVRSR_OK)
159169689Skan	    return _URC_FAILURE;
160169689Skan	  if (op & (1 << R_PC))
161169689Skan	    set_pc = 1;
162169689Skan	  continue;
163169689Skan	}
164169689Skan      if ((op & 0xf0) == 0x90)
165169689Skan	{
166169689Skan	  op &= 0xf;
167169689Skan	  if (op == 13 || op == 15)
168169689Skan	    /* Reserved.  */
169169689Skan	    return _URC_FAILURE;
170169689Skan	  /* vsp = r[nnnn].  */
171169689Skan	  _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
172169689Skan	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
173169689Skan	  continue;
174169689Skan	}
175169689Skan      if ((op & 0xf0) == 0xa0)
176169689Skan	{
177169689Skan	  /* Pop r4-r[4+nnn], [lr].  */
178169689Skan	  _uw mask;
179169689Skan
180169689Skan	  mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
181169689Skan	  if (op & 8)
182169689Skan	    mask |= (1 << R_LR);
183169689Skan	  if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
184169689Skan	      != _UVRSR_OK)
185169689Skan	    return _URC_FAILURE;
186169689Skan	  continue;
187169689Skan	}
188169689Skan      if ((op & 0xf0) == 0xb0)
189169689Skan	{
190169689Skan	  /* op == 0xb0 already handled.  */
191169689Skan	  if (op == 0xb1)
192169689Skan	    {
193169689Skan	      op = next_unwind_byte (uws);
194169689Skan	      if (op == 0 || ((op & 0xf0) != 0))
195169689Skan		/* Spare.  */
196169689Skan		return _URC_FAILURE;
197169689Skan	      /* Pop r0-r4 under mask.  */
198169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
199169689Skan		  != _UVRSR_OK)
200169689Skan		return _URC_FAILURE;
201169689Skan	      continue;
202169689Skan	    }
203169689Skan	  if (op == 0xb2)
204169689Skan	    {
205169689Skan	      /* vsp = vsp + 0x204 + (uleb128 << 2).  */
206169689Skan	      int shift;
207169689Skan
208169689Skan	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
209169689Skan			       &reg);
210169689Skan	      op = next_unwind_byte (uws);
211169689Skan	      shift = 2;
212169689Skan	      while (op & 0x80)
213169689Skan		{
214169689Skan		  reg += ((op & 0x7f) << shift);
215169689Skan		  shift += 7;
216169689Skan		  op = next_unwind_byte (uws);
217169689Skan		}
218169689Skan	      reg += ((op & 0x7f) << shift) + 0x204;
219169689Skan	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
220169689Skan			       &reg);
221169689Skan	      continue;
222169689Skan	    }
223169689Skan	  if (op == 0xb3)
224169689Skan	    {
225169689Skan	      /* Pop VFP registers with fldmx.  */
226169689Skan	      op = next_unwind_byte (uws);
227169689Skan	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
228169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
229169689Skan		  != _UVRSR_OK)
230169689Skan		return _URC_FAILURE;
231169689Skan	      continue;
232169689Skan	    }
233169689Skan	  if ((op & 0xfc) == 0xb4)
234169689Skan	    {
235169689Skan	      /* Pop FPA E[4]-E[4+nn].  */
236169689Skan	      op = 0x40000 | ((op & 3) + 1);
237169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
238169689Skan		  != _UVRSR_OK)
239169689Skan		return _URC_FAILURE;
240169689Skan	      continue;
241169689Skan	    }
242169689Skan	  /* op & 0xf8 == 0xb8.  */
243169689Skan	  /* Pop VFP D[8]-D[8+nnn] with fldmx.  */
244169689Skan	  op = 0x80000 | ((op & 7) + 1);
245169689Skan	  if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
246169689Skan	      != _UVRSR_OK)
247169689Skan	    return _URC_FAILURE;
248169689Skan	  continue;
249169689Skan	}
250169689Skan      if ((op & 0xf0) == 0xc0)
251169689Skan	{
252169689Skan	  if (op == 0xc6)
253169689Skan	    {
254169689Skan	      /* Pop iWMMXt D registers.  */
255169689Skan	      op = next_unwind_byte (uws);
256169689Skan	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
257169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
258169689Skan		  != _UVRSR_OK)
259169689Skan		return _URC_FAILURE;
260169689Skan	      continue;
261169689Skan	    }
262169689Skan	  if (op == 0xc7)
263169689Skan	    {
264169689Skan	      op = next_unwind_byte (uws);
265169689Skan	      if (op == 0 || (op & 0xf0) != 0)
266169689Skan		/* Spare.  */
267169689Skan		return _URC_FAILURE;
268169689Skan	      /* Pop iWMMXt wCGR{3,2,1,0} under mask.  */
269169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
270169689Skan		  != _UVRSR_OK)
271169689Skan		return _URC_FAILURE;
272169689Skan	      continue;
273169689Skan	    }
274169689Skan	  if ((op & 0xf8) == 0xc0)
275169689Skan	    {
276169689Skan	      /* Pop iWMMXt wR[10]-wR[10+nnn].  */
277169689Skan	      op = 0xa0000 | ((op & 0xf) + 1);
278169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
279169689Skan		  != _UVRSR_OK)
280169689Skan		return _URC_FAILURE;
281169689Skan	      continue;
282169689Skan	    }
283169689Skan	  if (op == 0xc8)
284169689Skan	    {
285169689Skan	      /* Pop FPA registers.  */
286169689Skan	      op = next_unwind_byte (uws);
287169689Skan	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
288169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
289169689Skan		  != _UVRSR_OK)
290169689Skan		return _URC_FAILURE;
291169689Skan	      continue;
292169689Skan	    }
293169689Skan	  if (op == 0xc9)
294169689Skan	    {
295169689Skan	      /* Pop VFP registers with fldmd.  */
296169689Skan	      op = next_unwind_byte (uws);
297169689Skan	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
298169689Skan	      if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
299169689Skan		  != _UVRSR_OK)
300169689Skan		return _URC_FAILURE;
301169689Skan	      continue;
302169689Skan	    }
303169689Skan	  /* Spare.  */
304169689Skan	  return _URC_FAILURE;
305169689Skan	}
306169689Skan      if ((op & 0xf8) == 0xd0)
307169689Skan	{
308169689Skan	  /* Pop VFP D[8]-D[8+nnn] with fldmd.  */
309169689Skan	  op = 0x80000 | ((op & 7) + 1);
310169689Skan	  if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
311169689Skan	      != _UVRSR_OK)
312169689Skan	    return _URC_FAILURE;
313169689Skan	  continue;
314169689Skan	}
315169689Skan      /* Spare.  */
316169689Skan      return _URC_FAILURE;
317169689Skan    }
318169689Skan  return _URC_OK;
319169689Skan}
320169689Skan
321169689Skan
322169689Skan/* Execute the unwinding instructions associated with a frame.  UCBP and
323169689Skan   CONTEXT are the current exception object and virtual CPU state
324169689Skan   respectively.  */
325169689Skan
326169689Skan_Unwind_Reason_Code
327169689Skan__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
328169689Skan{
329169689Skan  _uw *ptr;
330169689Skan  __gnu_unwind_state uws;
331169689Skan
332169689Skan  ptr = (_uw *) ucbp->pr_cache.ehtp;
333169689Skan  /* Skip over the personality routine address.  */
334169689Skan  ptr++;
335169689Skan  /* Setup the unwinder state.  */
336169689Skan  uws.data = (*ptr) << 8;
337169689Skan  uws.next = ptr + 1;
338169689Skan  uws.bytes_left = 3;
339169689Skan  uws.words_left = ((*ptr) >> 24) & 0xff;
340169689Skan
341169689Skan  return __gnu_unwind_execute (context, &uws);
342169689Skan}
343169689Skan
344169689Skan/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
345169689Skan
346169689Skanstatic inline _Unwind_Control_Block *
347169689Skanunwind_UCB_from_context (_Unwind_Context * context)
348169689Skan{
349169689Skan  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
350169689Skan}
351169689Skan
352169689Skan/* Get the start address of the function being unwound.  */
353169689Skan
354169689Skan_Unwind_Ptr
355169689Skan_Unwind_GetRegionStart (_Unwind_Context * context)
356169689Skan{
357169689Skan  _Unwind_Control_Block *ucbp;
358169689Skan
359169689Skan  ucbp = unwind_UCB_from_context (context);
360169689Skan  return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
361169689Skan}
362169689Skan
363169689Skan/* Find the Language specific exception data.  */
364169689Skan
365169689Skanvoid *
366169689Skan_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
367169689Skan{
368169689Skan  _Unwind_Control_Block *ucbp;
369169689Skan  _uw *ptr;
370169689Skan
371169689Skan  /* Get a pointer to the exception table entry.  */
372169689Skan  ucbp = unwind_UCB_from_context (context);
373169689Skan  ptr = (_uw *) ucbp->pr_cache.ehtp;
374169689Skan  /* Skip the personality routine address.  */
375169689Skan  ptr++;
376169689Skan  /* Skip the unwind opcodes.  */
377169689Skan  ptr += (((*ptr) >> 24) & 0xff) + 1;
378169689Skan
379169689Skan  return ptr;
380169689Skan}
381169689Skan
382