1*e4b17023SJohn Marino/* Common unwinding code for ARM EABI and C6X.
2*e4b17023SJohn Marino   Copyright (C) 2004, 2005, 2009, 2011 Free Software Foundation, Inc.
3*e4b17023SJohn Marino   Contributed by Paul Brook
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino   This file is free software; you can redistribute it and/or modify it
6*e4b17023SJohn Marino   under the terms of the GNU General Public License as published by the
7*e4b17023SJohn Marino   Free Software Foundation; either version 3, or (at your option) any
8*e4b17023SJohn Marino   later version.
9*e4b17023SJohn Marino
10*e4b17023SJohn Marino   This file is distributed in the hope that it will be useful, but
11*e4b17023SJohn Marino   WITHOUT ANY WARRANTY; without even the implied warranty of
12*e4b17023SJohn Marino   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*e4b17023SJohn Marino   General Public License for more details.
14*e4b17023SJohn Marino
15*e4b17023SJohn Marino   Under Section 7 of GPL version 3, you are granted additional
16*e4b17023SJohn Marino   permissions described in the GCC Runtime Library Exception, version
17*e4b17023SJohn Marino   3.1, as published by the Free Software Foundation.
18*e4b17023SJohn Marino
19*e4b17023SJohn Marino   You should have received a copy of the GNU General Public License and
20*e4b17023SJohn Marino   a copy of the GCC Runtime Library Exception along with this program;
21*e4b17023SJohn Marino   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22*e4b17023SJohn Marino   <http://www.gnu.org/licenses/>.  */
23*e4b17023SJohn Marino
24*e4b17023SJohn Marino#include "tconfig.h"
25*e4b17023SJohn Marino#include "tsystem.h"
26*e4b17023SJohn Marino#include "unwind.h"
27*e4b17023SJohn Marino
28*e4b17023SJohn Marino/* Used for SystemTap unwinder probe.  */
29*e4b17023SJohn Marino#ifdef HAVE_SYS_SDT_H
30*e4b17023SJohn Marino#include <sys/sdt.h>
31*e4b17023SJohn Marino#endif
32*e4b17023SJohn Marino
33*e4b17023SJohn Marino/* We add a prototype for abort here to avoid creating a dependency on
34*e4b17023SJohn Marino   target headers.  */
35*e4b17023SJohn Marinoextern void abort (void);
36*e4b17023SJohn Marino
37*e4b17023SJohn Marino/* Definitions for C++ runtime support routines.  We make these weak
38*e4b17023SJohn Marino   declarations to avoid pulling in libsupc++ unnecessarily.  */
39*e4b17023SJohn Marinotypedef unsigned char bool;
40*e4b17023SJohn Marino
41*e4b17023SJohn Marinotypedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
42*e4b17023SJohn Marinoenum __cxa_type_match_result
43*e4b17023SJohn Marino  {
44*e4b17023SJohn Marino    ctm_failed = 0,
45*e4b17023SJohn Marino    ctm_succeeded = 1,
46*e4b17023SJohn Marino    ctm_succeeded_with_ptr_to_base = 2
47*e4b17023SJohn Marino  };
48*e4b17023SJohn Marino
49*e4b17023SJohn Marinovoid __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
50*e4b17023SJohn Marinobool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
51*e4b17023SJohn Marinoenum __cxa_type_match_result __attribute__((weak)) __cxa_type_match
52*e4b17023SJohn Marino  (_Unwind_Control_Block *ucbp, const type_info *rttip,
53*e4b17023SJohn Marino   bool is_reference, void **matched_object);
54*e4b17023SJohn Marino
55*e4b17023SJohn Marino_Unwind_Ptr __attribute__((weak))
56*e4b17023SJohn Marino__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *);
57*e4b17023SJohn Marino
58*e4b17023SJohn Marino#define EXIDX_CANTUNWIND 1
59*e4b17023SJohn Marino#define uint32_highbit (((_uw) 1) << 31)
60*e4b17023SJohn Marino
61*e4b17023SJohn Marino#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
62*e4b17023SJohn Marino#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
63*e4b17023SJohn Marino#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
64*e4b17023SJohn Marino#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
65*e4b17023SJohn Marino
66*e4b17023SJohn Marino/* Unwind descriptors.  */
67*e4b17023SJohn Marino
68*e4b17023SJohn Marinotypedef struct
69*e4b17023SJohn Marino{
70*e4b17023SJohn Marino  _uw16 length;
71*e4b17023SJohn Marino  _uw16 offset;
72*e4b17023SJohn Marino} EHT16;
73*e4b17023SJohn Marino
74*e4b17023SJohn Marinotypedef struct
75*e4b17023SJohn Marino{
76*e4b17023SJohn Marino  _uw length;
77*e4b17023SJohn Marino  _uw offset;
78*e4b17023SJohn Marino} EHT32;
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino/* An exception index table entry.  */
81*e4b17023SJohn Marino
82*e4b17023SJohn Marinotypedef struct __EIT_entry
83*e4b17023SJohn Marino{
84*e4b17023SJohn Marino  _uw fnoffset;
85*e4b17023SJohn Marino  _uw content;
86*e4b17023SJohn Marino} __EIT_entry;
87*e4b17023SJohn Marino
88*e4b17023SJohn Marino/* Assembly helper functions.  */
89*e4b17023SJohn Marino
90*e4b17023SJohn Marino/* Restore core register state.  Never returns.  */
91*e4b17023SJohn Marinovoid __attribute__((noreturn)) restore_core_regs (struct core_regs *);
92*e4b17023SJohn Marino
93*e4b17023SJohn Marino
94*e4b17023SJohn Marino/* Restore coprocessor state after phase1 unwinding.  */
95*e4b17023SJohn Marinostatic void restore_non_core_regs (phase1_vrs * vrs);
96*e4b17023SJohn Marino
97*e4b17023SJohn Marino/* A better way to do this would probably be to compare the absolute address
98*e4b17023SJohn Marino   with a segment relative relocation of the same symbol.  */
99*e4b17023SJohn Marino
100*e4b17023SJohn Marinoextern int __text_start;
101*e4b17023SJohn Marinoextern int __data_start;
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino/* The exception index table location.  */
104*e4b17023SJohn Marinoextern __EIT_entry __exidx_start;
105*e4b17023SJohn Marinoextern __EIT_entry __exidx_end;
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino/* Core unwinding functions.  */
108*e4b17023SJohn Marino
109*e4b17023SJohn Marino/* Calculate the address encoded by a 31-bit self-relative offset at address
110*e4b17023SJohn Marino   P.  */
111*e4b17023SJohn Marinostatic inline _uw selfrel_offset31 (const _uw *p);
112*e4b17023SJohn Marino
113*e4b17023SJohn Marinostatic _uw __gnu_unwind_get_pr_addr (int idx);
114*e4b17023SJohn Marino
115*e4b17023SJohn Marinostatic void _Unwind_DebugHook (void *, void *)
116*e4b17023SJohn Marino  __attribute__ ((__noinline__, __used__, __noclone__));
117*e4b17023SJohn Marino
118*e4b17023SJohn Marino/* This function is called during unwinding.  It is intended as a hook
119*e4b17023SJohn Marino   for a debugger to intercept exceptions.  CFA is the CFA of the
120*e4b17023SJohn Marino   target frame.  HANDLER is the PC to which control will be
121*e4b17023SJohn Marino   transferred.  */
122*e4b17023SJohn Marino
123*e4b17023SJohn Marinostatic void
124*e4b17023SJohn Marino_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
125*e4b17023SJohn Marino		   void *handler __attribute__ ((__unused__)))
126*e4b17023SJohn Marino{
127*e4b17023SJohn Marino  /* We only want to use stap probes starting with v3.  Earlier
128*e4b17023SJohn Marino     versions added too much startup cost.  */
129*e4b17023SJohn Marino#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
130*e4b17023SJohn Marino  STAP_PROBE2 (libgcc, unwind, cfa, handler);
131*e4b17023SJohn Marino#else
132*e4b17023SJohn Marino  asm ("");
133*e4b17023SJohn Marino#endif
134*e4b17023SJohn Marino}
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino/* This is a wrapper to be called when we need to restore core registers.
137*e4b17023SJohn Marino   It will call `_Unwind_DebugHook' before restoring the registers, thus
138*e4b17023SJohn Marino   making it possible to intercept and debug exceptions.
139*e4b17023SJohn Marino
140*e4b17023SJohn Marino   When calling `_Unwind_DebugHook', the first argument (the CFA) is zero
141*e4b17023SJohn Marino   because we are not interested in it.  However, it must be there (even
142*e4b17023SJohn Marino   being zero) because GDB expects to find it when using the probe.  */
143*e4b17023SJohn Marino
144*e4b17023SJohn Marino#define uw_restore_core_regs(TARGET, CORE)				      \
145*e4b17023SJohn Marino  do									      \
146*e4b17023SJohn Marino    {									      \
147*e4b17023SJohn Marino      void *handler = __builtin_frob_return_addr ((void *) VRS_PC (TARGET));  \
148*e4b17023SJohn Marino      _Unwind_DebugHook (0, handler);					      \
149*e4b17023SJohn Marino      restore_core_regs (CORE);						      \
150*e4b17023SJohn Marino    }									      \
151*e4b17023SJohn Marino  while (0)
152*e4b17023SJohn Marino
153*e4b17023SJohn Marino/* Perform a binary search for RETURN_ADDRESS in TABLE.  The table contains
154*e4b17023SJohn Marino   NREC entries.  */
155*e4b17023SJohn Marino
156*e4b17023SJohn Marinostatic const __EIT_entry *
157*e4b17023SJohn Marinosearch_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
158*e4b17023SJohn Marino{
159*e4b17023SJohn Marino  _uw next_fn;
160*e4b17023SJohn Marino  _uw this_fn;
161*e4b17023SJohn Marino  int n, left, right;
162*e4b17023SJohn Marino
163*e4b17023SJohn Marino  if (nrec == 0)
164*e4b17023SJohn Marino    return (__EIT_entry *) 0;
165*e4b17023SJohn Marino
166*e4b17023SJohn Marino  left = 0;
167*e4b17023SJohn Marino  right = nrec - 1;
168*e4b17023SJohn Marino
169*e4b17023SJohn Marino  while (1)
170*e4b17023SJohn Marino    {
171*e4b17023SJohn Marino      n = (left + right) / 2;
172*e4b17023SJohn Marino      this_fn = selfrel_offset31 (&table[n].fnoffset);
173*e4b17023SJohn Marino      if (n != nrec - 1)
174*e4b17023SJohn Marino	next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
175*e4b17023SJohn Marino      else
176*e4b17023SJohn Marino	next_fn = (_uw)0 - 1;
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino      if (return_address < this_fn)
179*e4b17023SJohn Marino	{
180*e4b17023SJohn Marino	  if (n == left)
181*e4b17023SJohn Marino	    return (__EIT_entry *) 0;
182*e4b17023SJohn Marino	  right = n - 1;
183*e4b17023SJohn Marino	}
184*e4b17023SJohn Marino      else if (return_address <= next_fn)
185*e4b17023SJohn Marino	return &table[n];
186*e4b17023SJohn Marino      else
187*e4b17023SJohn Marino	left = n + 1;
188*e4b17023SJohn Marino    }
189*e4b17023SJohn Marino}
190*e4b17023SJohn Marino
191*e4b17023SJohn Marino/* Find the exception index table eintry for the given address.
192*e4b17023SJohn Marino   Fill in the relevant fields of the UCB.
193*e4b17023SJohn Marino   Returns _URC_FAILURE if an error occurred, _URC_OK on success.  */
194*e4b17023SJohn Marino
195*e4b17023SJohn Marinostatic _Unwind_Reason_Code
196*e4b17023SJohn Marinoget_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address)
197*e4b17023SJohn Marino{
198*e4b17023SJohn Marino  const __EIT_entry * eitp;
199*e4b17023SJohn Marino  int nrec;
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino  /* The return address is the address of the instruction following the
202*e4b17023SJohn Marino     call instruction (plus one in thumb mode).  If this was the last
203*e4b17023SJohn Marino     instruction in the function the address will lie in the following
204*e4b17023SJohn Marino     function.  Subtract 2 from the address so that it points within the call
205*e4b17023SJohn Marino     instruction itself.  */
206*e4b17023SJohn Marino  return_address -= 2;
207*e4b17023SJohn Marino
208*e4b17023SJohn Marino  if (__gnu_Unwind_Find_exidx)
209*e4b17023SJohn Marino    {
210*e4b17023SJohn Marino      eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address,
211*e4b17023SJohn Marino							    &nrec);
212*e4b17023SJohn Marino      if (!eitp)
213*e4b17023SJohn Marino	{
214*e4b17023SJohn Marino	  UCB_PR_ADDR (ucbp) = 0;
215*e4b17023SJohn Marino	  return _URC_FAILURE;
216*e4b17023SJohn Marino	}
217*e4b17023SJohn Marino    }
218*e4b17023SJohn Marino  else
219*e4b17023SJohn Marino    {
220*e4b17023SJohn Marino      eitp = &__exidx_start;
221*e4b17023SJohn Marino      nrec = &__exidx_end - &__exidx_start;
222*e4b17023SJohn Marino    }
223*e4b17023SJohn Marino
224*e4b17023SJohn Marino  eitp = search_EIT_table (eitp, nrec, return_address);
225*e4b17023SJohn Marino
226*e4b17023SJohn Marino  if (!eitp)
227*e4b17023SJohn Marino    {
228*e4b17023SJohn Marino      UCB_PR_ADDR (ucbp) = 0;
229*e4b17023SJohn Marino      return _URC_FAILURE;
230*e4b17023SJohn Marino    }
231*e4b17023SJohn Marino  ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
232*e4b17023SJohn Marino
233*e4b17023SJohn Marino  /* Can this frame be unwound at all?  */
234*e4b17023SJohn Marino  if (eitp->content == EXIDX_CANTUNWIND)
235*e4b17023SJohn Marino    {
236*e4b17023SJohn Marino      UCB_PR_ADDR (ucbp) = 0;
237*e4b17023SJohn Marino      return _URC_END_OF_STACK;
238*e4b17023SJohn Marino    }
239*e4b17023SJohn Marino
240*e4b17023SJohn Marino  /* Obtain the address of the "real" __EHT_Header word.  */
241*e4b17023SJohn Marino
242*e4b17023SJohn Marino  if (eitp->content & uint32_highbit)
243*e4b17023SJohn Marino    {
244*e4b17023SJohn Marino      /* It is immediate data.  */
245*e4b17023SJohn Marino      ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
246*e4b17023SJohn Marino      ucbp->pr_cache.additional = 1;
247*e4b17023SJohn Marino    }
248*e4b17023SJohn Marino  else
249*e4b17023SJohn Marino    {
250*e4b17023SJohn Marino      /* The low 31 bits of the content field are a self-relative
251*e4b17023SJohn Marino	 offset to an _Unwind_EHT_Entry structure.  */
252*e4b17023SJohn Marino      ucbp->pr_cache.ehtp =
253*e4b17023SJohn Marino	(_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content);
254*e4b17023SJohn Marino      ucbp->pr_cache.additional = 0;
255*e4b17023SJohn Marino    }
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino  /* Discover the personality routine address.  */
258*e4b17023SJohn Marino  if (*ucbp->pr_cache.ehtp & (1u << 31))
259*e4b17023SJohn Marino    {
260*e4b17023SJohn Marino      /* One of the predefined standard routines.  */
261*e4b17023SJohn Marino      _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf;
262*e4b17023SJohn Marino      UCB_PR_ADDR (ucbp) = __gnu_unwind_get_pr_addr (idx);
263*e4b17023SJohn Marino      if (UCB_PR_ADDR (ucbp) == 0)
264*e4b17023SJohn Marino	{
265*e4b17023SJohn Marino	  /* Failed */
266*e4b17023SJohn Marino	  return _URC_FAILURE;
267*e4b17023SJohn Marino	}
268*e4b17023SJohn Marino    }
269*e4b17023SJohn Marino  else
270*e4b17023SJohn Marino    {
271*e4b17023SJohn Marino      /* Execute region offset to PR */
272*e4b17023SJohn Marino      UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp);
273*e4b17023SJohn Marino    }
274*e4b17023SJohn Marino  return _URC_OK;
275*e4b17023SJohn Marino}
276*e4b17023SJohn Marino
277*e4b17023SJohn Marino
278*e4b17023SJohn Marino/* Perform phase2 unwinding.  VRS is the initial virtual register state.  */
279*e4b17023SJohn Marino
280*e4b17023SJohn Marinostatic void __attribute__((noreturn))
281*e4b17023SJohn Marinounwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs)
282*e4b17023SJohn Marino{
283*e4b17023SJohn Marino  _Unwind_Reason_Code pr_result;
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino  do
286*e4b17023SJohn Marino    {
287*e4b17023SJohn Marino      /* Find the entry for this routine.  */
288*e4b17023SJohn Marino      if (get_eit_entry (ucbp, VRS_PC(vrs)) != _URC_OK)
289*e4b17023SJohn Marino	abort ();
290*e4b17023SJohn Marino
291*e4b17023SJohn Marino      UCB_SAVED_CALLSITE_ADDR (ucbp) = VRS_PC(vrs);
292*e4b17023SJohn Marino
293*e4b17023SJohn Marino      /* Call the pr to decide what to do.  */
294*e4b17023SJohn Marino      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
295*e4b17023SJohn Marino	(_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
296*e4b17023SJohn Marino    }
297*e4b17023SJohn Marino  while (pr_result == _URC_CONTINUE_UNWIND);
298*e4b17023SJohn Marino
299*e4b17023SJohn Marino  if (pr_result != _URC_INSTALL_CONTEXT)
300*e4b17023SJohn Marino    abort();
301*e4b17023SJohn Marino
302*e4b17023SJohn Marino  uw_restore_core_regs (vrs, &vrs->core);
303*e4b17023SJohn Marino}
304*e4b17023SJohn Marino
305*e4b17023SJohn Marino/* Perform phase2 forced unwinding.  */
306*e4b17023SJohn Marino
307*e4b17023SJohn Marinostatic _Unwind_Reason_Code
308*e4b17023SJohn Marinounwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs,
309*e4b17023SJohn Marino		      int resuming)
310*e4b17023SJohn Marino{
311*e4b17023SJohn Marino  _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
312*e4b17023SJohn Marino  void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
313*e4b17023SJohn Marino  _Unwind_Reason_Code pr_result = 0;
314*e4b17023SJohn Marino  /* We use phase1_vrs here even though we do not demand save, for the
315*e4b17023SJohn Marino     prev_sp field.  */
316*e4b17023SJohn Marino  phase1_vrs saved_vrs, next_vrs;
317*e4b17023SJohn Marino
318*e4b17023SJohn Marino  /* Save the core registers.  */
319*e4b17023SJohn Marino  saved_vrs.core = entry_vrs->core;
320*e4b17023SJohn Marino  /* We don't need to demand-save the non-core registers, because we
321*e4b17023SJohn Marino     unwind in a single pass.  */
322*e4b17023SJohn Marino  saved_vrs.demand_save_flags = 0;
323*e4b17023SJohn Marino
324*e4b17023SJohn Marino  /* Unwind until we reach a propagation barrier.  */
325*e4b17023SJohn Marino  do
326*e4b17023SJohn Marino    {
327*e4b17023SJohn Marino      _Unwind_State action;
328*e4b17023SJohn Marino      _Unwind_Reason_Code entry_code;
329*e4b17023SJohn Marino      _Unwind_Reason_Code stop_code;
330*e4b17023SJohn Marino
331*e4b17023SJohn Marino      /* Find the entry for this routine.  */
332*e4b17023SJohn Marino      entry_code = get_eit_entry (ucbp, VRS_PC (&saved_vrs));
333*e4b17023SJohn Marino
334*e4b17023SJohn Marino      if (resuming)
335*e4b17023SJohn Marino	{
336*e4b17023SJohn Marino	  action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND;
337*e4b17023SJohn Marino	  resuming = 0;
338*e4b17023SJohn Marino	}
339*e4b17023SJohn Marino      else
340*e4b17023SJohn Marino	action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
341*e4b17023SJohn Marino
342*e4b17023SJohn Marino      if (entry_code == _URC_OK)
343*e4b17023SJohn Marino	{
344*e4b17023SJohn Marino	  UCB_SAVED_CALLSITE_ADDR (ucbp) = VRS_PC (&saved_vrs);
345*e4b17023SJohn Marino
346*e4b17023SJohn Marino	  next_vrs = saved_vrs;
347*e4b17023SJohn Marino
348*e4b17023SJohn Marino	  /* Call the pr to decide what to do.  */
349*e4b17023SJohn Marino	  pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
350*e4b17023SJohn Marino	    (action, ucbp, (void *) &next_vrs);
351*e4b17023SJohn Marino
352*e4b17023SJohn Marino	  saved_vrs.prev_sp = VRS_SP (&next_vrs);
353*e4b17023SJohn Marino	}
354*e4b17023SJohn Marino      else
355*e4b17023SJohn Marino	{
356*e4b17023SJohn Marino	  /* Treat any failure as the end of unwinding, to cope more
357*e4b17023SJohn Marino	     gracefully with missing EH information.  Mixed EH and
358*e4b17023SJohn Marino	     non-EH within one object will usually result in failure,
359*e4b17023SJohn Marino	     because the .ARM.exidx tables do not indicate the end
360*e4b17023SJohn Marino	     of the code to which they apply; but mixed EH and non-EH
361*e4b17023SJohn Marino	     shared objects should return an unwind failure at the
362*e4b17023SJohn Marino	     entry of a non-EH shared object.  */
363*e4b17023SJohn Marino	  action |= _US_END_OF_STACK;
364*e4b17023SJohn Marino
365*e4b17023SJohn Marino	  saved_vrs.prev_sp = VRS_SP (&saved_vrs);
366*e4b17023SJohn Marino	}
367*e4b17023SJohn Marino
368*e4b17023SJohn Marino      stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
369*e4b17023SJohn Marino			   (void *)&saved_vrs, stop_arg);
370*e4b17023SJohn Marino      if (stop_code != _URC_NO_REASON)
371*e4b17023SJohn Marino	return _URC_FAILURE;
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino      if (entry_code != _URC_OK)
374*e4b17023SJohn Marino	return entry_code;
375*e4b17023SJohn Marino
376*e4b17023SJohn Marino      saved_vrs = next_vrs;
377*e4b17023SJohn Marino    }
378*e4b17023SJohn Marino  while (pr_result == _URC_CONTINUE_UNWIND);
379*e4b17023SJohn Marino
380*e4b17023SJohn Marino  if (pr_result != _URC_INSTALL_CONTEXT)
381*e4b17023SJohn Marino    {
382*e4b17023SJohn Marino      /* Some sort of failure has occurred in the pr and probably the
383*e4b17023SJohn Marino	 pr returned _URC_FAILURE.  */
384*e4b17023SJohn Marino      return _URC_FAILURE;
385*e4b17023SJohn Marino    }
386*e4b17023SJohn Marino
387*e4b17023SJohn Marino  uw_restore_core_regs (&saved_vrs, &saved_vrs.core);
388*e4b17023SJohn Marino}
389*e4b17023SJohn Marino
390*e4b17023SJohn Marino/* This is a very limited implementation of _Unwind_GetCFA.  It returns
391*e4b17023SJohn Marino   the stack pointer as it is about to be unwound, and is only valid
392*e4b17023SJohn Marino   while calling the stop function during forced unwinding.  If the
393*e4b17023SJohn Marino   current personality routine result is going to run a cleanup, this
394*e4b17023SJohn Marino   will not be the CFA; but when the frame is really unwound, it will
395*e4b17023SJohn Marino   be.  */
396*e4b17023SJohn Marino
397*e4b17023SJohn Marino_Unwind_Word
398*e4b17023SJohn Marino_Unwind_GetCFA (_Unwind_Context *context)
399*e4b17023SJohn Marino{
400*e4b17023SJohn Marino  return ((phase1_vrs *) context)->prev_sp;
401*e4b17023SJohn Marino}
402*e4b17023SJohn Marino
403*e4b17023SJohn Marino/* Perform phase1 unwinding.  UCBP is the exception being thrown, and
404*e4b17023SJohn Marino   entry_VRS is the register state on entry to _Unwind_RaiseException.  */
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino_Unwind_Reason_Code
407*e4b17023SJohn Marino__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *);
408*e4b17023SJohn Marino
409*e4b17023SJohn Marino_Unwind_Reason_Code
410*e4b17023SJohn Marino__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp,
411*e4b17023SJohn Marino			     phase2_vrs * entry_vrs)
412*e4b17023SJohn Marino{
413*e4b17023SJohn Marino  phase1_vrs saved_vrs;
414*e4b17023SJohn Marino  _Unwind_Reason_Code pr_result;
415*e4b17023SJohn Marino
416*e4b17023SJohn Marino  /* Set the pc to the call site.  */
417*e4b17023SJohn Marino  VRS_PC (entry_vrs) = VRS_RETURN(entry_vrs);
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino  /* Save the core registers.  */
420*e4b17023SJohn Marino  saved_vrs.core = entry_vrs->core;
421*e4b17023SJohn Marino  /* Set demand-save flags.  */
422*e4b17023SJohn Marino  saved_vrs.demand_save_flags = ~(_uw) 0;
423*e4b17023SJohn Marino
424*e4b17023SJohn Marino  /* Unwind until we reach a propagation barrier.  */
425*e4b17023SJohn Marino  do
426*e4b17023SJohn Marino    {
427*e4b17023SJohn Marino      /* Find the entry for this routine.  */
428*e4b17023SJohn Marino      if (get_eit_entry (ucbp, VRS_PC (&saved_vrs)) != _URC_OK)
429*e4b17023SJohn Marino	return _URC_FAILURE;
430*e4b17023SJohn Marino
431*e4b17023SJohn Marino      /* Call the pr to decide what to do.  */
432*e4b17023SJohn Marino      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
433*e4b17023SJohn Marino	(_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
434*e4b17023SJohn Marino    }
435*e4b17023SJohn Marino  while (pr_result == _URC_CONTINUE_UNWIND);
436*e4b17023SJohn Marino
437*e4b17023SJohn Marino  /* We've unwound as far as we want to go, so restore the original
438*e4b17023SJohn Marino     register state.  */
439*e4b17023SJohn Marino  restore_non_core_regs (&saved_vrs);
440*e4b17023SJohn Marino  if (pr_result != _URC_HANDLER_FOUND)
441*e4b17023SJohn Marino    {
442*e4b17023SJohn Marino      /* Some sort of failure has occurred in the pr and probably the
443*e4b17023SJohn Marino	 pr returned _URC_FAILURE.  */
444*e4b17023SJohn Marino      return _URC_FAILURE;
445*e4b17023SJohn Marino    }
446*e4b17023SJohn Marino
447*e4b17023SJohn Marino  unwind_phase2 (ucbp, entry_vrs);
448*e4b17023SJohn Marino}
449*e4b17023SJohn Marino
450*e4b17023SJohn Marino/* Resume unwinding after a cleanup has been run.  UCBP is the exception
451*e4b17023SJohn Marino   being thrown and ENTRY_VRS is the register state on entry to
452*e4b17023SJohn Marino   _Unwind_Resume.  */
453*e4b17023SJohn Marino_Unwind_Reason_Code
454*e4b17023SJohn Marino__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
455*e4b17023SJohn Marino			   _Unwind_Stop_Fn, void *, phase2_vrs *);
456*e4b17023SJohn Marino
457*e4b17023SJohn Marino_Unwind_Reason_Code
458*e4b17023SJohn Marino__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
459*e4b17023SJohn Marino			   _Unwind_Stop_Fn stop_fn, void *stop_arg,
460*e4b17023SJohn Marino			   phase2_vrs *entry_vrs)
461*e4b17023SJohn Marino{
462*e4b17023SJohn Marino  UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
463*e4b17023SJohn Marino  UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
464*e4b17023SJohn Marino
465*e4b17023SJohn Marino  /* Set the pc to the call site.  */
466*e4b17023SJohn Marino  VRS_PC (entry_vrs) = VRS_RETURN(entry_vrs);
467*e4b17023SJohn Marino
468*e4b17023SJohn Marino  return unwind_phase2_forced (ucbp, entry_vrs, 0);
469*e4b17023SJohn Marino}
470*e4b17023SJohn Marino
471*e4b17023SJohn Marino_Unwind_Reason_Code
472*e4b17023SJohn Marino__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
473*e4b17023SJohn Marino
474*e4b17023SJohn Marino_Unwind_Reason_Code
475*e4b17023SJohn Marino__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
476*e4b17023SJohn Marino{
477*e4b17023SJohn Marino  _Unwind_Reason_Code pr_result;
478*e4b17023SJohn Marino
479*e4b17023SJohn Marino  /* Recover the saved address.  */
480*e4b17023SJohn Marino  VRS_PC (entry_vrs) = UCB_SAVED_CALLSITE_ADDR (ucbp);
481*e4b17023SJohn Marino
482*e4b17023SJohn Marino  if (UCB_FORCED_STOP_FN (ucbp))
483*e4b17023SJohn Marino    {
484*e4b17023SJohn Marino      unwind_phase2_forced (ucbp, entry_vrs, 1);
485*e4b17023SJohn Marino
486*e4b17023SJohn Marino      /* We can't return failure at this point.  */
487*e4b17023SJohn Marino      abort ();
488*e4b17023SJohn Marino    }
489*e4b17023SJohn Marino
490*e4b17023SJohn Marino  /* Call the cached PR.  */
491*e4b17023SJohn Marino  pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
492*e4b17023SJohn Marino	(_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
493*e4b17023SJohn Marino
494*e4b17023SJohn Marino  switch (pr_result)
495*e4b17023SJohn Marino    {
496*e4b17023SJohn Marino    case _URC_INSTALL_CONTEXT:
497*e4b17023SJohn Marino      /* Upload the registers to enter the landing pad.  */
498*e4b17023SJohn Marino      uw_restore_core_regs (entry_vrs, &entry_vrs->core);
499*e4b17023SJohn Marino
500*e4b17023SJohn Marino    case _URC_CONTINUE_UNWIND:
501*e4b17023SJohn Marino      /* Continue unwinding the next frame.  */
502*e4b17023SJohn Marino      unwind_phase2 (ucbp, entry_vrs);
503*e4b17023SJohn Marino
504*e4b17023SJohn Marino    default:
505*e4b17023SJohn Marino      abort ();
506*e4b17023SJohn Marino    }
507*e4b17023SJohn Marino}
508*e4b17023SJohn Marino
509*e4b17023SJohn Marino_Unwind_Reason_Code
510*e4b17023SJohn Marino__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
511*e4b17023SJohn Marino
512*e4b17023SJohn Marino_Unwind_Reason_Code
513*e4b17023SJohn Marino__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
514*e4b17023SJohn Marino				phase2_vrs * entry_vrs)
515*e4b17023SJohn Marino{
516*e4b17023SJohn Marino  if (!UCB_FORCED_STOP_FN (ucbp))
517*e4b17023SJohn Marino    return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
518*e4b17023SJohn Marino
519*e4b17023SJohn Marino  /* Set the pc to the call site.  */
520*e4b17023SJohn Marino  VRS_PC (entry_vrs) = VRS_RETURN (entry_vrs);
521*e4b17023SJohn Marino  /* Continue unwinding the next frame.  */
522*e4b17023SJohn Marino  return unwind_phase2_forced (ucbp, entry_vrs, 0);
523*e4b17023SJohn Marino}
524*e4b17023SJohn Marino
525*e4b17023SJohn Marino/* Clean up an exception object when unwinding is complete.  */
526*e4b17023SJohn Marinovoid
527*e4b17023SJohn Marino_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
528*e4b17023SJohn Marino{
529*e4b17023SJohn Marino}
530*e4b17023SJohn Marino
531*e4b17023SJohn Marino
532*e4b17023SJohn Marino/* Free an exception.  */
533*e4b17023SJohn Marino
534*e4b17023SJohn Marinovoid
535*e4b17023SJohn Marino_Unwind_DeleteException (_Unwind_Exception * exc)
536*e4b17023SJohn Marino{
537*e4b17023SJohn Marino  if (exc->exception_cleanup)
538*e4b17023SJohn Marino    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
539*e4b17023SJohn Marino}
540*e4b17023SJohn Marino
541*e4b17023SJohn Marino
542*e4b17023SJohn Marino/* Perform stack backtrace through unwind data.  */
543*e4b17023SJohn Marino_Unwind_Reason_Code
544*e4b17023SJohn Marino__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
545*e4b17023SJohn Marino		       phase2_vrs * entry_vrs);
546*e4b17023SJohn Marino_Unwind_Reason_Code
547*e4b17023SJohn Marino__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
548*e4b17023SJohn Marino		       phase2_vrs * entry_vrs)
549*e4b17023SJohn Marino{
550*e4b17023SJohn Marino  phase1_vrs saved_vrs;
551*e4b17023SJohn Marino  _Unwind_Reason_Code code;
552*e4b17023SJohn Marino
553*e4b17023SJohn Marino  _Unwind_Control_Block ucb;
554*e4b17023SJohn Marino  _Unwind_Control_Block *ucbp = &ucb;
555*e4b17023SJohn Marino
556*e4b17023SJohn Marino  /* Set the pc to the call site.  */
557*e4b17023SJohn Marino  VRS_PC (entry_vrs) = VRS_RETURN (entry_vrs);
558*e4b17023SJohn Marino
559*e4b17023SJohn Marino  /* Save the core registers.  */
560*e4b17023SJohn Marino  saved_vrs.core = entry_vrs->core;
561*e4b17023SJohn Marino  /* Set demand-save flags.  */
562*e4b17023SJohn Marino  saved_vrs.demand_save_flags = ~(_uw) 0;
563*e4b17023SJohn Marino
564*e4b17023SJohn Marino  do
565*e4b17023SJohn Marino    {
566*e4b17023SJohn Marino      /* Find the entry for this routine.  */
567*e4b17023SJohn Marino      if (get_eit_entry (ucbp, VRS_PC (&saved_vrs)) != _URC_OK)
568*e4b17023SJohn Marino	{
569*e4b17023SJohn Marino	  code = _URC_FAILURE;
570*e4b17023SJohn Marino	  break;
571*e4b17023SJohn Marino	}
572*e4b17023SJohn Marino
573*e4b17023SJohn Marino      /* The dwarf unwinder assumes the context structure holds things
574*e4b17023SJohn Marino	 like the function and LSDA pointers.  The ARM implementation
575*e4b17023SJohn Marino	 caches these in the exception header (UCB).  To avoid
576*e4b17023SJohn Marino	 rewriting everything we make the virtual IP register point at
577*e4b17023SJohn Marino	 the UCB.  */
578*e4b17023SJohn Marino      _Unwind_SetGR((_Unwind_Context *)&saved_vrs, UNWIND_POINTER_REG, (_Unwind_Ptr) ucbp);
579*e4b17023SJohn Marino
580*e4b17023SJohn Marino      /* Call trace function.  */
581*e4b17023SJohn Marino      if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument)
582*e4b17023SJohn Marino	  != _URC_NO_REASON)
583*e4b17023SJohn Marino	{
584*e4b17023SJohn Marino	  code = _URC_FAILURE;
585*e4b17023SJohn Marino	  break;
586*e4b17023SJohn Marino	}
587*e4b17023SJohn Marino
588*e4b17023SJohn Marino      /* Call the pr to decide what to do.  */
589*e4b17023SJohn Marino      code = ((personality_routine) UCB_PR_ADDR (ucbp))
590*e4b17023SJohn Marino	(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND,
591*e4b17023SJohn Marino	 ucbp, (void *) &saved_vrs);
592*e4b17023SJohn Marino    }
593*e4b17023SJohn Marino  while (code != _URC_END_OF_STACK
594*e4b17023SJohn Marino	 && code != _URC_FAILURE);
595*e4b17023SJohn Marino
596*e4b17023SJohn Marino  restore_non_core_regs (&saved_vrs);
597*e4b17023SJohn Marino  return code;
598*e4b17023SJohn Marino}
599*e4b17023SJohn Marino
600*e4b17023SJohn Marino
601*e4b17023SJohn Marino/* Common implementation for ARM ABI defined personality routines.
602*e4b17023SJohn Marino   ID is the index of the personality routine, other arguments are as defined
603*e4b17023SJohn Marino   by __aeabi_unwind_cpp_pr{0,1,2}.  */
604*e4b17023SJohn Marino
605*e4b17023SJohn Marinostatic _Unwind_Reason_Code
606*e4b17023SJohn Marino__gnu_unwind_pr_common (_Unwind_State state,
607*e4b17023SJohn Marino			_Unwind_Control_Block *ucbp,
608*e4b17023SJohn Marino			_Unwind_Context *context,
609*e4b17023SJohn Marino			int id)
610*e4b17023SJohn Marino{
611*e4b17023SJohn Marino  __gnu_unwind_state uws;
612*e4b17023SJohn Marino  _uw *data;
613*e4b17023SJohn Marino  _uw offset;
614*e4b17023SJohn Marino  _uw len;
615*e4b17023SJohn Marino  _uw rtti_count;
616*e4b17023SJohn Marino  int phase2_call_unexpected_after_unwind = 0;
617*e4b17023SJohn Marino  int in_range = 0;
618*e4b17023SJohn Marino  int forced_unwind = state & _US_FORCE_UNWIND;
619*e4b17023SJohn Marino
620*e4b17023SJohn Marino  state &= _US_ACTION_MASK;
621*e4b17023SJohn Marino
622*e4b17023SJohn Marino  data = (_uw *) ucbp->pr_cache.ehtp;
623*e4b17023SJohn Marino  uws.data = *(data++);
624*e4b17023SJohn Marino  uws.next = data;
625*e4b17023SJohn Marino  if (id == 0)
626*e4b17023SJohn Marino    {
627*e4b17023SJohn Marino      uws.data <<= 8;
628*e4b17023SJohn Marino      uws.words_left = 0;
629*e4b17023SJohn Marino      uws.bytes_left = 3;
630*e4b17023SJohn Marino    }
631*e4b17023SJohn Marino  else if (id < 3)
632*e4b17023SJohn Marino    {
633*e4b17023SJohn Marino      uws.words_left = (uws.data >> 16) & 0xff;
634*e4b17023SJohn Marino      uws.data <<= 16;
635*e4b17023SJohn Marino      uws.bytes_left = 2;
636*e4b17023SJohn Marino      data += uws.words_left;
637*e4b17023SJohn Marino    }
638*e4b17023SJohn Marino
639*e4b17023SJohn Marino  /* Restore the saved pointer.  */
640*e4b17023SJohn Marino  if (state == _US_UNWIND_FRAME_RESUME)
641*e4b17023SJohn Marino    data = (_uw *) ucbp->cleanup_cache.bitpattern[0];
642*e4b17023SJohn Marino
643*e4b17023SJohn Marino  if ((ucbp->pr_cache.additional & 1) == 0)
644*e4b17023SJohn Marino    {
645*e4b17023SJohn Marino      /* Process descriptors.  */
646*e4b17023SJohn Marino      while (*data)
647*e4b17023SJohn Marino	{
648*e4b17023SJohn Marino	  _uw addr;
649*e4b17023SJohn Marino	  _uw fnstart;
650*e4b17023SJohn Marino
651*e4b17023SJohn Marino	  if (id == 2)
652*e4b17023SJohn Marino	    {
653*e4b17023SJohn Marino	      len = ((EHT32 *) data)->length;
654*e4b17023SJohn Marino	      offset = ((EHT32 *) data)->offset;
655*e4b17023SJohn Marino	      data += 2;
656*e4b17023SJohn Marino	    }
657*e4b17023SJohn Marino	  else
658*e4b17023SJohn Marino	    {
659*e4b17023SJohn Marino	      len = ((EHT16 *) data)->length;
660*e4b17023SJohn Marino	      offset = ((EHT16 *) data)->offset;
661*e4b17023SJohn Marino	      data++;
662*e4b17023SJohn Marino	    }
663*e4b17023SJohn Marino
664*e4b17023SJohn Marino	  fnstart = ucbp->pr_cache.fnstart + (offset & ~1);
665*e4b17023SJohn Marino	  addr = _Unwind_GetGR (context, R_PC);
666*e4b17023SJohn Marino	  in_range = (fnstart <= addr && addr < fnstart + (len & ~1));
667*e4b17023SJohn Marino
668*e4b17023SJohn Marino	  switch (((offset & 1) << 1) | (len & 1))
669*e4b17023SJohn Marino	    {
670*e4b17023SJohn Marino	    case 0:
671*e4b17023SJohn Marino	      /* Cleanup.  */
672*e4b17023SJohn Marino	      if (state != _US_VIRTUAL_UNWIND_FRAME
673*e4b17023SJohn Marino		  && in_range)
674*e4b17023SJohn Marino		{
675*e4b17023SJohn Marino		  /* Cleanup in range, and we are running cleanups.  */
676*e4b17023SJohn Marino		  _uw lp;
677*e4b17023SJohn Marino
678*e4b17023SJohn Marino		  /* Landing pad address is 31-bit pc-relative offset.  */
679*e4b17023SJohn Marino		  lp = selfrel_offset31 (data);
680*e4b17023SJohn Marino		  data++;
681*e4b17023SJohn Marino		  /* Save the exception data pointer.  */
682*e4b17023SJohn Marino		  ucbp->cleanup_cache.bitpattern[0] = (_uw) data;
683*e4b17023SJohn Marino		  if (!__cxa_begin_cleanup (ucbp))
684*e4b17023SJohn Marino		    return _URC_FAILURE;
685*e4b17023SJohn Marino		  /* Setup the VRS to enter the landing pad.  */
686*e4b17023SJohn Marino		  _Unwind_SetGR (context, R_PC, lp);
687*e4b17023SJohn Marino		  return _URC_INSTALL_CONTEXT;
688*e4b17023SJohn Marino		}
689*e4b17023SJohn Marino	      /* Cleanup not in range, or we are in stage 1.  */
690*e4b17023SJohn Marino	      data++;
691*e4b17023SJohn Marino	      break;
692*e4b17023SJohn Marino
693*e4b17023SJohn Marino	    case 1:
694*e4b17023SJohn Marino	      /* Catch handler.  */
695*e4b17023SJohn Marino	      if (state == _US_VIRTUAL_UNWIND_FRAME)
696*e4b17023SJohn Marino		{
697*e4b17023SJohn Marino		  if (in_range)
698*e4b17023SJohn Marino		    {
699*e4b17023SJohn Marino		      /* Check for a barrier.  */
700*e4b17023SJohn Marino		      _uw rtti;
701*e4b17023SJohn Marino		      bool is_reference = (data[0] & uint32_highbit) != 0;
702*e4b17023SJohn Marino		      void *matched;
703*e4b17023SJohn Marino		      enum __cxa_type_match_result match_type;
704*e4b17023SJohn Marino
705*e4b17023SJohn Marino		      /* Check for no-throw areas.  */
706*e4b17023SJohn Marino		      if (data[1] == (_uw) -2)
707*e4b17023SJohn Marino			return _URC_FAILURE;
708*e4b17023SJohn Marino
709*e4b17023SJohn Marino		      /* The thrown object immediately follows the ECB.  */
710*e4b17023SJohn Marino		      matched = (void *)(ucbp + 1);
711*e4b17023SJohn Marino		      if (data[1] != (_uw) -1)
712*e4b17023SJohn Marino			{
713*e4b17023SJohn Marino			  /* Match a catch specification.  */
714*e4b17023SJohn Marino			  rtti = _Unwind_decode_typeinfo_ptr (0,
715*e4b17023SJohn Marino							      (_uw) &data[1]);
716*e4b17023SJohn Marino			  match_type = __cxa_type_match (ucbp,
717*e4b17023SJohn Marino							 (type_info *) rtti,
718*e4b17023SJohn Marino							 is_reference,
719*e4b17023SJohn Marino							 &matched);
720*e4b17023SJohn Marino			}
721*e4b17023SJohn Marino		      else
722*e4b17023SJohn Marino			match_type = ctm_succeeded;
723*e4b17023SJohn Marino
724*e4b17023SJohn Marino		      if (match_type)
725*e4b17023SJohn Marino			{
726*e4b17023SJohn Marino			  ucbp->barrier_cache.sp =
727*e4b17023SJohn Marino			    _Unwind_GetGR (context, R_SP);
728*e4b17023SJohn Marino			  // ctm_succeeded_with_ptr_to_base really
729*e4b17023SJohn Marino			  // means _c_t_m indirected the pointer
730*e4b17023SJohn Marino			  // object.  We have to reconstruct the
731*e4b17023SJohn Marino			  // additional pointer layer by using a temporary.
732*e4b17023SJohn Marino			  if (match_type == ctm_succeeded_with_ptr_to_base)
733*e4b17023SJohn Marino			    {
734*e4b17023SJohn Marino			      ucbp->barrier_cache.bitpattern[2]
735*e4b17023SJohn Marino				= (_uw) matched;
736*e4b17023SJohn Marino			      ucbp->barrier_cache.bitpattern[0]
737*e4b17023SJohn Marino				= (_uw) &ucbp->barrier_cache.bitpattern[2];
738*e4b17023SJohn Marino			    }
739*e4b17023SJohn Marino			  else
740*e4b17023SJohn Marino			    ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
741*e4b17023SJohn Marino			  ucbp->barrier_cache.bitpattern[1] = (_uw) data;
742*e4b17023SJohn Marino			  return _URC_HANDLER_FOUND;
743*e4b17023SJohn Marino			}
744*e4b17023SJohn Marino		    }
745*e4b17023SJohn Marino		  /* Handler out of range, or not matched.  */
746*e4b17023SJohn Marino		}
747*e4b17023SJohn Marino	      else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
748*e4b17023SJohn Marino		       && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
749*e4b17023SJohn Marino		{
750*e4b17023SJohn Marino		  /* Matched a previous propagation barrier.  */
751*e4b17023SJohn Marino		  _uw lp;
752*e4b17023SJohn Marino
753*e4b17023SJohn Marino		  /* Setup for entry to the handler.  */
754*e4b17023SJohn Marino		  lp = selfrel_offset31 (data);
755*e4b17023SJohn Marino		  _Unwind_SetGR (context, R_PC, lp);
756*e4b17023SJohn Marino		  _Unwind_SetGR (context, 0, (_uw) ucbp);
757*e4b17023SJohn Marino		  return _URC_INSTALL_CONTEXT;
758*e4b17023SJohn Marino		}
759*e4b17023SJohn Marino	      /* Catch handler not matched.  Advance to the next descriptor.  */
760*e4b17023SJohn Marino	      data += 2;
761*e4b17023SJohn Marino	      break;
762*e4b17023SJohn Marino
763*e4b17023SJohn Marino	    case 2:
764*e4b17023SJohn Marino	      rtti_count = data[0] & 0x7fffffff;
765*e4b17023SJohn Marino	      /* Exception specification.  */
766*e4b17023SJohn Marino	      if (state == _US_VIRTUAL_UNWIND_FRAME)
767*e4b17023SJohn Marino		{
768*e4b17023SJohn Marino		  if (in_range && (!forced_unwind || !rtti_count))
769*e4b17023SJohn Marino		    {
770*e4b17023SJohn Marino		      /* Match against the exception specification.  */
771*e4b17023SJohn Marino		      _uw i;
772*e4b17023SJohn Marino		      _uw rtti;
773*e4b17023SJohn Marino		      void *matched;
774*e4b17023SJohn Marino
775*e4b17023SJohn Marino		      for (i = 0; i < rtti_count; i++)
776*e4b17023SJohn Marino			{
777*e4b17023SJohn Marino			  matched = (void *)(ucbp + 1);
778*e4b17023SJohn Marino			  rtti = _Unwind_decode_typeinfo_ptr (0,
779*e4b17023SJohn Marino			      (_uw) &data[i + 1]);
780*e4b17023SJohn Marino			  if (__cxa_type_match (ucbp, (type_info *) rtti, 0,
781*e4b17023SJohn Marino						&matched))
782*e4b17023SJohn Marino			    break;
783*e4b17023SJohn Marino			}
784*e4b17023SJohn Marino
785*e4b17023SJohn Marino		      if (i == rtti_count)
786*e4b17023SJohn Marino			{
787*e4b17023SJohn Marino			  /* Exception does not match the spec.  */
788*e4b17023SJohn Marino			  ucbp->barrier_cache.sp =
789*e4b17023SJohn Marino			    _Unwind_GetGR (context, R_SP);
790*e4b17023SJohn Marino			  ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
791*e4b17023SJohn Marino			  ucbp->barrier_cache.bitpattern[1] = (_uw) data;
792*e4b17023SJohn Marino			  return _URC_HANDLER_FOUND;
793*e4b17023SJohn Marino			}
794*e4b17023SJohn Marino		    }
795*e4b17023SJohn Marino		  /* Handler out of range, or exception is permitted.  */
796*e4b17023SJohn Marino		}
797*e4b17023SJohn Marino	      else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
798*e4b17023SJohn Marino		       && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
799*e4b17023SJohn Marino		{
800*e4b17023SJohn Marino		  /* Matched a previous propagation barrier.  */
801*e4b17023SJohn Marino		  _uw lp;
802*e4b17023SJohn Marino		  /* Record the RTTI list for __cxa_call_unexpected.  */
803*e4b17023SJohn Marino		  ucbp->barrier_cache.bitpattern[1] = rtti_count;
804*e4b17023SJohn Marino		  ucbp->barrier_cache.bitpattern[2] = 0;
805*e4b17023SJohn Marino		  ucbp->barrier_cache.bitpattern[3] = 4;
806*e4b17023SJohn Marino		  ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1];
807*e4b17023SJohn Marino
808*e4b17023SJohn Marino		  if (data[0] & uint32_highbit)
809*e4b17023SJohn Marino		    {
810*e4b17023SJohn Marino		      data += rtti_count + 1;
811*e4b17023SJohn Marino		      /* Setup for entry to the handler.  */
812*e4b17023SJohn Marino		      lp = selfrel_offset31 (data);
813*e4b17023SJohn Marino		      data++;
814*e4b17023SJohn Marino		      _Unwind_SetGR (context, R_PC, lp);
815*e4b17023SJohn Marino		      _Unwind_SetGR (context, 0, (_uw) ucbp);
816*e4b17023SJohn Marino		      return _URC_INSTALL_CONTEXT;
817*e4b17023SJohn Marino		    }
818*e4b17023SJohn Marino		  else
819*e4b17023SJohn Marino		    phase2_call_unexpected_after_unwind = 1;
820*e4b17023SJohn Marino		}
821*e4b17023SJohn Marino	      if (data[0] & uint32_highbit)
822*e4b17023SJohn Marino		data++;
823*e4b17023SJohn Marino	      data += rtti_count + 1;
824*e4b17023SJohn Marino	      break;
825*e4b17023SJohn Marino
826*e4b17023SJohn Marino	    default:
827*e4b17023SJohn Marino	      /* Should never happen.  */
828*e4b17023SJohn Marino	      return _URC_FAILURE;
829*e4b17023SJohn Marino	    }
830*e4b17023SJohn Marino	  /* Finished processing this descriptor.  */
831*e4b17023SJohn Marino	}
832*e4b17023SJohn Marino    }
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino  if (id >= 3)
835*e4b17023SJohn Marino    {
836*e4b17023SJohn Marino      /* 24-bit ecoding */
837*e4b17023SJohn Marino      if (__gnu_unwind_24bit (context, uws.data, id == 4) != _URC_OK)
838*e4b17023SJohn Marino	return _URC_FAILURE;
839*e4b17023SJohn Marino    }
840*e4b17023SJohn Marino  else
841*e4b17023SJohn Marino    {
842*e4b17023SJohn Marino      if (__gnu_unwind_execute (context, &uws) != _URC_OK)
843*e4b17023SJohn Marino	return _URC_FAILURE;
844*e4b17023SJohn Marino    }
845*e4b17023SJohn Marino
846*e4b17023SJohn Marino  if (phase2_call_unexpected_after_unwind)
847*e4b17023SJohn Marino    {
848*e4b17023SJohn Marino      /* Enter __cxa_unexpected as if called from the call site.  */
849*e4b17023SJohn Marino      _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC));
850*e4b17023SJohn Marino      _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected);
851*e4b17023SJohn Marino      return _URC_INSTALL_CONTEXT;
852*e4b17023SJohn Marino    }
853*e4b17023SJohn Marino
854*e4b17023SJohn Marino  return _URC_CONTINUE_UNWIND;
855*e4b17023SJohn Marino}
856