xref: /openbsd-src/gnu/gcc/libstdc++-v3/libsupc++/eh_personality.cc (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert // -*- C++ -*- The GNU C++ exception personality routine.
2*404b540aSrobert // Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
3*404b540aSrobert //
4*404b540aSrobert // This file is part of GCC.
5*404b540aSrobert //
6*404b540aSrobert // GCC is free software; you can redistribute it and/or modify
7*404b540aSrobert // it under the terms of the GNU General Public License as published by
8*404b540aSrobert // the Free Software Foundation; either version 2, or (at your option)
9*404b540aSrobert // any later version.
10*404b540aSrobert //
11*404b540aSrobert // GCC is distributed in the hope that it will be useful,
12*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*404b540aSrobert // GNU General Public License for more details.
15*404b540aSrobert //
16*404b540aSrobert // You should have received a copy of the GNU General Public License
17*404b540aSrobert // along with GCC; see the file COPYING.  If not, write to
18*404b540aSrobert // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19*404b540aSrobert // Boston, MA 02110-1301, USA.
20*404b540aSrobert 
21*404b540aSrobert // As a special exception, you may use this file as part of a free software
22*404b540aSrobert // library without restriction.  Specifically, if other files instantiate
23*404b540aSrobert // templates or use macros or inline functions from this file, or you compile
24*404b540aSrobert // this file and link it with other files to produce an executable, this
25*404b540aSrobert // file does not by itself cause the resulting executable to be covered by
26*404b540aSrobert // the GNU General Public License.  This exception does not however
27*404b540aSrobert // invalidate any other reasons why the executable file might be covered by
28*404b540aSrobert // the GNU General Public License.
29*404b540aSrobert 
30*404b540aSrobert #include <bits/c++config.h>
31*404b540aSrobert #include <cstdlib>
32*404b540aSrobert #include <exception_defines.h>
33*404b540aSrobert #include "unwind-cxx.h"
34*404b540aSrobert 
35*404b540aSrobert using namespace __cxxabiv1;
36*404b540aSrobert 
37*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
38*404b540aSrobert #define NO_SIZE_OF_ENCODED_VALUE
39*404b540aSrobert #endif
40*404b540aSrobert 
41*404b540aSrobert #include "unwind-pe.h"
42*404b540aSrobert 
43*404b540aSrobert 
44*404b540aSrobert struct lsda_header_info
45*404b540aSrobert {
46*404b540aSrobert   _Unwind_Ptr Start;
47*404b540aSrobert   _Unwind_Ptr LPStart;
48*404b540aSrobert   _Unwind_Ptr ttype_base;
49*404b540aSrobert   const unsigned char *TType;
50*404b540aSrobert   const unsigned char *action_table;
51*404b540aSrobert   unsigned char ttype_encoding;
52*404b540aSrobert   unsigned char call_site_encoding;
53*404b540aSrobert };
54*404b540aSrobert 
55*404b540aSrobert static const unsigned char *
parse_lsda_header(_Unwind_Context * context,const unsigned char * p,lsda_header_info * info)56*404b540aSrobert parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
57*404b540aSrobert 		   lsda_header_info *info)
58*404b540aSrobert {
59*404b540aSrobert   _Unwind_Word tmp;
60*404b540aSrobert   unsigned char lpstart_encoding;
61*404b540aSrobert 
62*404b540aSrobert   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
63*404b540aSrobert 
64*404b540aSrobert   // Find @LPStart, the base to which landing pad offsets are relative.
65*404b540aSrobert   lpstart_encoding = *p++;
66*404b540aSrobert   if (lpstart_encoding != DW_EH_PE_omit)
67*404b540aSrobert     p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
68*404b540aSrobert   else
69*404b540aSrobert     info->LPStart = info->Start;
70*404b540aSrobert 
71*404b540aSrobert   // Find @TType, the base of the handler and exception spec type data.
72*404b540aSrobert   info->ttype_encoding = *p++;
73*404b540aSrobert   if (info->ttype_encoding != DW_EH_PE_omit)
74*404b540aSrobert     {
75*404b540aSrobert       p = read_uleb128 (p, &tmp);
76*404b540aSrobert       info->TType = p + tmp;
77*404b540aSrobert     }
78*404b540aSrobert   else
79*404b540aSrobert     info->TType = 0;
80*404b540aSrobert 
81*404b540aSrobert   // The encoding and length of the call-site table; the action table
82*404b540aSrobert   // immediately follows.
83*404b540aSrobert   info->call_site_encoding = *p++;
84*404b540aSrobert   p = read_uleb128 (p, &tmp);
85*404b540aSrobert   info->action_table = p + tmp;
86*404b540aSrobert 
87*404b540aSrobert   return p;
88*404b540aSrobert }
89*404b540aSrobert 
90*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
91*404b540aSrobert 
92*404b540aSrobert // Return an element from a type table.
93*404b540aSrobert 
94*404b540aSrobert static const std::type_info*
get_ttype_entry(lsda_header_info * info,_Unwind_Word i)95*404b540aSrobert get_ttype_entry(lsda_header_info* info, _Unwind_Word i)
96*404b540aSrobert {
97*404b540aSrobert   _Unwind_Ptr ptr;
98*404b540aSrobert 
99*404b540aSrobert   ptr = (_Unwind_Ptr) (info->TType - (i * 4));
100*404b540aSrobert   ptr = _Unwind_decode_target2(ptr);
101*404b540aSrobert 
102*404b540aSrobert   return reinterpret_cast<const std::type_info *>(ptr);
103*404b540aSrobert }
104*404b540aSrobert 
105*404b540aSrobert // The ABI provides a routine for matching exception object types.
106*404b540aSrobert typedef _Unwind_Control_Block _throw_typet;
107*404b540aSrobert #define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \
108*404b540aSrobert   (__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \
109*404b540aSrobert    != ctm_failed)
110*404b540aSrobert 
111*404b540aSrobert // Return true if THROW_TYPE matches one if the filter types.
112*404b540aSrobert 
113*404b540aSrobert static bool
check_exception_spec(lsda_header_info * info,_throw_typet * throw_type,void * thrown_ptr,_Unwind_Sword filter_value)114*404b540aSrobert check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
115*404b540aSrobert 		     void* thrown_ptr, _Unwind_Sword filter_value)
116*404b540aSrobert {
117*404b540aSrobert   const _Unwind_Word* e = ((const _Unwind_Word*) info->TType)
118*404b540aSrobert 			  - filter_value - 1;
119*404b540aSrobert 
120*404b540aSrobert   while (1)
121*404b540aSrobert     {
122*404b540aSrobert       const std::type_info* catch_type;
123*404b540aSrobert       _Unwind_Word tmp;
124*404b540aSrobert 
125*404b540aSrobert       tmp = *e;
126*404b540aSrobert 
127*404b540aSrobert       // Zero signals the end of the list.  If we've not found
128*404b540aSrobert       // a match by now, then we've failed the specification.
129*404b540aSrobert       if (tmp == 0)
130*404b540aSrobert         return false;
131*404b540aSrobert 
132*404b540aSrobert       tmp = _Unwind_decode_target2((_Unwind_Word) e);
133*404b540aSrobert 
134*404b540aSrobert       // Match a ttype entry.
135*404b540aSrobert       catch_type = reinterpret_cast<const std::type_info*>(tmp);
136*404b540aSrobert 
137*404b540aSrobert       // ??? There is currently no way to ask the RTTI code about the
138*404b540aSrobert       // relationship between two types without reference to a specific
139*404b540aSrobert       // object.  There should be; then we wouldn't need to mess with
140*404b540aSrobert       // thrown_ptr here.
141*404b540aSrobert       if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr))
142*404b540aSrobert 	return true;
143*404b540aSrobert 
144*404b540aSrobert       // Advance to the next entry.
145*404b540aSrobert       e++;
146*404b540aSrobert     }
147*404b540aSrobert }
148*404b540aSrobert 
149*404b540aSrobert 
150*404b540aSrobert // Save stage1 handler information in the exception object
151*404b540aSrobert 
152*404b540aSrobert static inline void
save_caught_exception(struct _Unwind_Exception * ue_header,struct _Unwind_Context * context,void * thrown_ptr,int handler_switch_value,const unsigned char * language_specific_data,_Unwind_Ptr landing_pad,const unsigned char * action_record)153*404b540aSrobert save_caught_exception(struct _Unwind_Exception* ue_header,
154*404b540aSrobert 		      struct _Unwind_Context* context,
155*404b540aSrobert 		      void* thrown_ptr,
156*404b540aSrobert 		      int handler_switch_value,
157*404b540aSrobert 		      const unsigned char* language_specific_data,
158*404b540aSrobert 		      _Unwind_Ptr landing_pad,
159*404b540aSrobert 		      const unsigned char* action_record
160*404b540aSrobert 			__attribute__((__unused__)))
161*404b540aSrobert {
162*404b540aSrobert     ue_header->barrier_cache.sp = _Unwind_GetGR(context, 13);
163*404b540aSrobert     ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr;
164*404b540aSrobert     ue_header->barrier_cache.bitpattern[1]
165*404b540aSrobert       = (_uw) handler_switch_value;
166*404b540aSrobert     ue_header->barrier_cache.bitpattern[2]
167*404b540aSrobert       = (_uw) language_specific_data;
168*404b540aSrobert     ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
169*404b540aSrobert }
170*404b540aSrobert 
171*404b540aSrobert 
172*404b540aSrobert // Restore the catch handler data saved during phase1.
173*404b540aSrobert 
174*404b540aSrobert static inline void
restore_caught_exception(struct _Unwind_Exception * ue_header,int & handler_switch_value,const unsigned char * & language_specific_data,_Unwind_Ptr & landing_pad)175*404b540aSrobert restore_caught_exception(struct _Unwind_Exception* ue_header,
176*404b540aSrobert 			 int& handler_switch_value,
177*404b540aSrobert 			 const unsigned char*& language_specific_data,
178*404b540aSrobert 			 _Unwind_Ptr& landing_pad)
179*404b540aSrobert {
180*404b540aSrobert   handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
181*404b540aSrobert   language_specific_data =
182*404b540aSrobert     (const unsigned char*) ue_header->barrier_cache.bitpattern[2];
183*404b540aSrobert   landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
184*404b540aSrobert }
185*404b540aSrobert 
186*404b540aSrobert #define CONTINUE_UNWINDING \
187*404b540aSrobert   do								\
188*404b540aSrobert     {								\
189*404b540aSrobert       if (__gnu_unwind_frame(ue_header, context) != _URC_OK)	\
190*404b540aSrobert 	return _URC_FAILURE;					\
191*404b540aSrobert       return _URC_CONTINUE_UNWIND;				\
192*404b540aSrobert     }								\
193*404b540aSrobert   while (0)
194*404b540aSrobert 
195*404b540aSrobert #else
196*404b540aSrobert typedef const std::type_info _throw_typet;
197*404b540aSrobert 
198*404b540aSrobert 
199*404b540aSrobert // Return an element from a type table.
200*404b540aSrobert 
201*404b540aSrobert static const std::type_info *
get_ttype_entry(lsda_header_info * info,_Unwind_Word i)202*404b540aSrobert get_ttype_entry (lsda_header_info *info, _Unwind_Word i)
203*404b540aSrobert {
204*404b540aSrobert   _Unwind_Ptr ptr;
205*404b540aSrobert 
206*404b540aSrobert   i *= size_of_encoded_value (info->ttype_encoding);
207*404b540aSrobert   read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
208*404b540aSrobert 				info->TType - i, &ptr);
209*404b540aSrobert 
210*404b540aSrobert   return reinterpret_cast<const std::type_info *>(ptr);
211*404b540aSrobert }
212*404b540aSrobert 
213*404b540aSrobert // Given the thrown type THROW_TYPE, pointer to a variable containing a
214*404b540aSrobert // pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to
215*404b540aSrobert // compare against, return whether or not there is a match and if so,
216*404b540aSrobert // update *THROWN_PTR_P.
217*404b540aSrobert 
218*404b540aSrobert static bool
get_adjusted_ptr(const std::type_info * catch_type,const std::type_info * throw_type,void ** thrown_ptr_p)219*404b540aSrobert get_adjusted_ptr (const std::type_info *catch_type,
220*404b540aSrobert 		  const std::type_info *throw_type,
221*404b540aSrobert 		  void **thrown_ptr_p)
222*404b540aSrobert {
223*404b540aSrobert   void *thrown_ptr = *thrown_ptr_p;
224*404b540aSrobert 
225*404b540aSrobert   // Pointer types need to adjust the actual pointer, not
226*404b540aSrobert   // the pointer to pointer that is the exception object.
227*404b540aSrobert   // This also has the effect of passing pointer types
228*404b540aSrobert   // "by value" through the __cxa_begin_catch return value.
229*404b540aSrobert   if (throw_type->__is_pointer_p ())
230*404b540aSrobert     thrown_ptr = *(void **) thrown_ptr;
231*404b540aSrobert 
232*404b540aSrobert   if (catch_type->__do_catch (throw_type, &thrown_ptr, 1))
233*404b540aSrobert     {
234*404b540aSrobert       *thrown_ptr_p = thrown_ptr;
235*404b540aSrobert       return true;
236*404b540aSrobert     }
237*404b540aSrobert 
238*404b540aSrobert   return false;
239*404b540aSrobert }
240*404b540aSrobert 
241*404b540aSrobert // Return true if THROW_TYPE matches one if the filter types.
242*404b540aSrobert 
243*404b540aSrobert static bool
check_exception_spec(lsda_header_info * info,_throw_typet * throw_type,void * thrown_ptr,_Unwind_Sword filter_value)244*404b540aSrobert check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
245*404b540aSrobert 		      void* thrown_ptr, _Unwind_Sword filter_value)
246*404b540aSrobert {
247*404b540aSrobert   const unsigned char *e = info->TType - filter_value - 1;
248*404b540aSrobert 
249*404b540aSrobert   while (1)
250*404b540aSrobert     {
251*404b540aSrobert       const std::type_info *catch_type;
252*404b540aSrobert       _Unwind_Word tmp;
253*404b540aSrobert 
254*404b540aSrobert       e = read_uleb128 (e, &tmp);
255*404b540aSrobert 
256*404b540aSrobert       // Zero signals the end of the list.  If we've not found
257*404b540aSrobert       // a match by now, then we've failed the specification.
258*404b540aSrobert       if (tmp == 0)
259*404b540aSrobert         return false;
260*404b540aSrobert 
261*404b540aSrobert       // Match a ttype entry.
262*404b540aSrobert       catch_type = get_ttype_entry (info, tmp);
263*404b540aSrobert 
264*404b540aSrobert       // ??? There is currently no way to ask the RTTI code about the
265*404b540aSrobert       // relationship between two types without reference to a specific
266*404b540aSrobert       // object.  There should be; then we wouldn't need to mess with
267*404b540aSrobert       // thrown_ptr here.
268*404b540aSrobert       if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
269*404b540aSrobert 	return true;
270*404b540aSrobert     }
271*404b540aSrobert }
272*404b540aSrobert 
273*404b540aSrobert 
274*404b540aSrobert // Save stage1 handler information in the exception object
275*404b540aSrobert 
276*404b540aSrobert static inline void
save_caught_exception(struct _Unwind_Exception * ue_header,struct _Unwind_Context * context,void * thrown_ptr,int handler_switch_value,const unsigned char * language_specific_data,_Unwind_Ptr landing_pad,const unsigned char * action_record)277*404b540aSrobert save_caught_exception(struct _Unwind_Exception* ue_header,
278*404b540aSrobert 		      struct _Unwind_Context* context
279*404b540aSrobert 			__attribute__((__unused__)),
280*404b540aSrobert 		      void* thrown_ptr,
281*404b540aSrobert 		      int handler_switch_value,
282*404b540aSrobert 		      const unsigned char* language_specific_data,
283*404b540aSrobert 		      _Unwind_Ptr landing_pad __attribute__((__unused__)),
284*404b540aSrobert 		      const unsigned char* action_record)
285*404b540aSrobert {
286*404b540aSrobert   __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
287*404b540aSrobert 
288*404b540aSrobert   xh->handlerSwitchValue = handler_switch_value;
289*404b540aSrobert   xh->actionRecord = action_record;
290*404b540aSrobert   xh->languageSpecificData = language_specific_data;
291*404b540aSrobert   xh->adjustedPtr = thrown_ptr;
292*404b540aSrobert 
293*404b540aSrobert   // ??? Completely unknown what this field is supposed to be for.
294*404b540aSrobert   // ??? Need to cache TType encoding base for call_unexpected.
295*404b540aSrobert   xh->catchTemp = landing_pad;
296*404b540aSrobert }
297*404b540aSrobert 
298*404b540aSrobert 
299*404b540aSrobert // Restore the catch handler information saved during phase1.
300*404b540aSrobert 
301*404b540aSrobert static inline void
restore_caught_exception(struct _Unwind_Exception * ue_header,int & handler_switch_value,const unsigned char * & language_specific_data,_Unwind_Ptr & landing_pad)302*404b540aSrobert restore_caught_exception(struct _Unwind_Exception* ue_header,
303*404b540aSrobert 			 int& handler_switch_value,
304*404b540aSrobert 			 const unsigned char*& language_specific_data,
305*404b540aSrobert 			 _Unwind_Ptr& landing_pad)
306*404b540aSrobert {
307*404b540aSrobert   __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
308*404b540aSrobert   handler_switch_value = xh->handlerSwitchValue;
309*404b540aSrobert   language_specific_data = xh->languageSpecificData;
310*404b540aSrobert   landing_pad = (_Unwind_Ptr) xh->catchTemp;
311*404b540aSrobert }
312*404b540aSrobert 
313*404b540aSrobert #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
314*404b540aSrobert 
315*404b540aSrobert #endif // !__ARM_EABI_UNWINDER__
316*404b540aSrobert 
317*404b540aSrobert // Return true if the filter spec is empty, ie throw().
318*404b540aSrobert 
319*404b540aSrobert static bool
empty_exception_spec(lsda_header_info * info,_Unwind_Sword filter_value)320*404b540aSrobert empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
321*404b540aSrobert {
322*404b540aSrobert   const unsigned char *e = info->TType - filter_value - 1;
323*404b540aSrobert   _Unwind_Word tmp;
324*404b540aSrobert 
325*404b540aSrobert   e = read_uleb128 (e, &tmp);
326*404b540aSrobert   return tmp == 0;
327*404b540aSrobert }
328*404b540aSrobert 
329*404b540aSrobert namespace __cxxabiv1
330*404b540aSrobert {
331*404b540aSrobert 
332*404b540aSrobert // Using a different personality function name causes link failures
333*404b540aSrobert // when trying to mix code using different exception handling models.
334*404b540aSrobert #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
335*404b540aSrobert #define PERSONALITY_FUNCTION	__gxx_personality_sj0
336*404b540aSrobert #define __builtin_eh_return_data_regno(x) x
337*404b540aSrobert #else
338*404b540aSrobert #define PERSONALITY_FUNCTION	__gxx_personality_v0
339*404b540aSrobert #endif
340*404b540aSrobert 
341*404b540aSrobert extern "C" _Unwind_Reason_Code
342*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)343*404b540aSrobert PERSONALITY_FUNCTION (_Unwind_State state,
344*404b540aSrobert 		      struct _Unwind_Exception* ue_header,
345*404b540aSrobert 		      struct _Unwind_Context* context)
346*404b540aSrobert #else
347*404b540aSrobert PERSONALITY_FUNCTION (int version,
348*404b540aSrobert 		      _Unwind_Action actions,
349*404b540aSrobert 		      _Unwind_Exception_Class exception_class,
350*404b540aSrobert 		      struct _Unwind_Exception *ue_header,
351*404b540aSrobert 		      struct _Unwind_Context *context)
352*404b540aSrobert #endif
353*404b540aSrobert {
354*404b540aSrobert   enum found_handler_type
355*404b540aSrobert   {
356*404b540aSrobert     found_nothing,
357*404b540aSrobert     found_terminate,
358*404b540aSrobert     found_cleanup,
359*404b540aSrobert     found_handler
360*404b540aSrobert   } found_type;
361*404b540aSrobert 
362*404b540aSrobert   lsda_header_info info;
363*404b540aSrobert   const unsigned char *language_specific_data;
364*404b540aSrobert   const unsigned char *action_record;
365*404b540aSrobert   const unsigned char *p;
366*404b540aSrobert   _Unwind_Ptr landing_pad, ip;
367*404b540aSrobert   int handler_switch_value;
368*404b540aSrobert   void* thrown_ptr = ue_header + 1;
369*404b540aSrobert   bool foreign_exception;
370*404b540aSrobert   int ip_before_insn = 0;
371*404b540aSrobert 
372*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
373*404b540aSrobert   _Unwind_Action actions;
374*404b540aSrobert 
375*404b540aSrobert   switch (state & _US_ACTION_MASK)
376*404b540aSrobert     {
377*404b540aSrobert     case _US_VIRTUAL_UNWIND_FRAME:
378*404b540aSrobert       actions = _UA_SEARCH_PHASE;
379*404b540aSrobert       break;
380*404b540aSrobert 
381*404b540aSrobert     case _US_UNWIND_FRAME_STARTING:
382*404b540aSrobert       actions = _UA_CLEANUP_PHASE;
383*404b540aSrobert       if (!(state & _US_FORCE_UNWIND)
384*404b540aSrobert 	  && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
385*404b540aSrobert 	actions |= _UA_HANDLER_FRAME;
386*404b540aSrobert       break;
387*404b540aSrobert 
388*404b540aSrobert     case _US_UNWIND_FRAME_RESUME:
389*404b540aSrobert       CONTINUE_UNWINDING;
390*404b540aSrobert       break;
391*404b540aSrobert 
392*404b540aSrobert     default:
393*404b540aSrobert       std::abort();
394*404b540aSrobert     }
395*404b540aSrobert   actions |= state & _US_FORCE_UNWIND;
396*404b540aSrobert 
397*404b540aSrobert   // We don't know which runtime we're working with, so can't check this.
398*404b540aSrobert   // However the ABI routines hide this from us, and we don't actually need
399*404b540aSrobert   // to know.
400*404b540aSrobert   foreign_exception = false;
401*404b540aSrobert 
402*404b540aSrobert   // The dwarf unwinder assumes the context structure holds things like the
403*404b540aSrobert   // function and LSDA pointers.  The ARM implementation caches these in
404*404b540aSrobert   // the exception header (UCB).  To avoid rewriting everything we make the
405*404b540aSrobert   // virtual IP register point at the UCB.
406*404b540aSrobert   ip = (_Unwind_Ptr) ue_header;
407*404b540aSrobert   _Unwind_SetGR(context, 12, ip);
408*404b540aSrobert #else
409*404b540aSrobert   __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
410*404b540aSrobert 
411*404b540aSrobert   // Interface version check.
412*404b540aSrobert   if (version != 1)
413*404b540aSrobert     return _URC_FATAL_PHASE1_ERROR;
414*404b540aSrobert   foreign_exception = !__is_gxx_exception_class(exception_class);
415*404b540aSrobert #endif
416*404b540aSrobert 
417*404b540aSrobert   // Shortcut for phase 2 found handler for domestic exception.
418*404b540aSrobert   if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
419*404b540aSrobert       && !foreign_exception)
420*404b540aSrobert     {
421*404b540aSrobert       restore_caught_exception(ue_header, handler_switch_value,
422*404b540aSrobert 			       language_specific_data, landing_pad);
423*404b540aSrobert       found_type = (landing_pad == 0 ? found_terminate : found_handler);
424*404b540aSrobert       goto install_context;
425*404b540aSrobert     }
426*404b540aSrobert 
427*404b540aSrobert   language_specific_data = (const unsigned char *)
428*404b540aSrobert     _Unwind_GetLanguageSpecificData (context);
429*404b540aSrobert 
430*404b540aSrobert   // If no LSDA, then there are no handlers or cleanups.
431*404b540aSrobert   if (! language_specific_data)
432*404b540aSrobert     CONTINUE_UNWINDING;
433*404b540aSrobert 
434*404b540aSrobert   // Parse the LSDA header.
435*404b540aSrobert   p = parse_lsda_header (context, language_specific_data, &info);
436*404b540aSrobert   info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
437*404b540aSrobert #ifdef HAVE_GETIPINFO
438*404b540aSrobert   ip = _Unwind_GetIPInfo (context, &ip_before_insn);
439*404b540aSrobert #else
440*404b540aSrobert   ip = _Unwind_GetIP (context);
441*404b540aSrobert #endif
442*404b540aSrobert   if (! ip_before_insn)
443*404b540aSrobert     --ip;
444*404b540aSrobert   landing_pad = 0;
445*404b540aSrobert   action_record = 0;
446*404b540aSrobert   handler_switch_value = 0;
447*404b540aSrobert 
448*404b540aSrobert #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
449*404b540aSrobert   // The given "IP" is an index into the call-site table, with two
450*404b540aSrobert   // exceptions -- -1 means no-action, and 0 means terminate.  But
451*404b540aSrobert   // since we're using uleb128 values, we've not got random access
452*404b540aSrobert   // to the array.
453*404b540aSrobert   if ((int) ip < 0)
454*404b540aSrobert     return _URC_CONTINUE_UNWIND;
455*404b540aSrobert   else if (ip == 0)
456*404b540aSrobert     {
457*404b540aSrobert       // Fall through to set found_terminate.
458*404b540aSrobert     }
459*404b540aSrobert   else
460*404b540aSrobert     {
461*404b540aSrobert       _Unwind_Word cs_lp, cs_action;
462*404b540aSrobert       do
463*404b540aSrobert 	{
464*404b540aSrobert 	  p = read_uleb128 (p, &cs_lp);
465*404b540aSrobert 	  p = read_uleb128 (p, &cs_action);
466*404b540aSrobert 	}
467*404b540aSrobert       while (--ip);
468*404b540aSrobert 
469*404b540aSrobert       // Can never have null landing pad for sjlj -- that would have
470*404b540aSrobert       // been indicated by a -1 call site index.
471*404b540aSrobert       landing_pad = cs_lp + 1;
472*404b540aSrobert       if (cs_action)
473*404b540aSrobert 	action_record = info.action_table + cs_action - 1;
474*404b540aSrobert       goto found_something;
475*404b540aSrobert     }
476*404b540aSrobert #else
477*404b540aSrobert   // Search the call-site table for the action associated with this IP.
478*404b540aSrobert   while (p < info.action_table)
479*404b540aSrobert     {
480*404b540aSrobert       _Unwind_Ptr cs_start, cs_len, cs_lp;
481*404b540aSrobert       _Unwind_Word cs_action;
482*404b540aSrobert 
483*404b540aSrobert       // Note that all call-site encodings are "absolute" displacements.
484*404b540aSrobert       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
485*404b540aSrobert       p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
486*404b540aSrobert       p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
487*404b540aSrobert       p = read_uleb128 (p, &cs_action);
488*404b540aSrobert 
489*404b540aSrobert       // The table is sorted, so if we've passed the ip, stop.
490*404b540aSrobert       if (ip < info.Start + cs_start)
491*404b540aSrobert 	p = info.action_table;
492*404b540aSrobert       else if (ip < info.Start + cs_start + cs_len)
493*404b540aSrobert 	{
494*404b540aSrobert 	  if (cs_lp)
495*404b540aSrobert 	    landing_pad = info.LPStart + cs_lp;
496*404b540aSrobert 	  if (cs_action)
497*404b540aSrobert 	    action_record = info.action_table + cs_action - 1;
498*404b540aSrobert 	  goto found_something;
499*404b540aSrobert 	}
500*404b540aSrobert     }
501*404b540aSrobert #endif // _GLIBCXX_SJLJ_EXCEPTIONS
502*404b540aSrobert 
503*404b540aSrobert   // If ip is not present in the table, call terminate.  This is for
504*404b540aSrobert   // a destructor inside a cleanup, or a library routine the compiler
505*404b540aSrobert   // was not expecting to throw.
506*404b540aSrobert   found_type = found_terminate;
507*404b540aSrobert   goto do_something;
508*404b540aSrobert 
509*404b540aSrobert  found_something:
510*404b540aSrobert   if (landing_pad == 0)
511*404b540aSrobert     {
512*404b540aSrobert       // If ip is present, and has a null landing pad, there are
513*404b540aSrobert       // no cleanups or handlers to be run.
514*404b540aSrobert       found_type = found_nothing;
515*404b540aSrobert     }
516*404b540aSrobert   else if (action_record == 0)
517*404b540aSrobert     {
518*404b540aSrobert       // If ip is present, has a non-null landing pad, and a null
519*404b540aSrobert       // action table offset, then there are only cleanups present.
520*404b540aSrobert       // Cleanups use a zero switch value, as set above.
521*404b540aSrobert       found_type = found_cleanup;
522*404b540aSrobert     }
523*404b540aSrobert   else
524*404b540aSrobert     {
525*404b540aSrobert       // Otherwise we have a catch handler or exception specification.
526*404b540aSrobert 
527*404b540aSrobert       _Unwind_Sword ar_filter, ar_disp;
528*404b540aSrobert       const std::type_info* catch_type;
529*404b540aSrobert       _throw_typet* throw_type;
530*404b540aSrobert       bool saw_cleanup = false;
531*404b540aSrobert       bool saw_handler = false;
532*404b540aSrobert 
533*404b540aSrobert       // During forced unwinding, we only run cleanups.  With a foreign
534*404b540aSrobert       // exception class, there's no exception type.
535*404b540aSrobert       // ??? What to do about GNU Java and GNU Ada exceptions.
536*404b540aSrobert 
537*404b540aSrobert       if ((actions & _UA_FORCE_UNWIND)
538*404b540aSrobert 	  || foreign_exception)
539*404b540aSrobert 	throw_type = 0;
540*404b540aSrobert       else
541*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
542*404b540aSrobert 	throw_type = ue_header;
543*404b540aSrobert #else
544*404b540aSrobert 	throw_type = xh->exceptionType;
545*404b540aSrobert #endif
546*404b540aSrobert 
547*404b540aSrobert       while (1)
548*404b540aSrobert 	{
549*404b540aSrobert 	  p = action_record;
550*404b540aSrobert 	  p = read_sleb128 (p, &ar_filter);
551*404b540aSrobert 	  read_sleb128 (p, &ar_disp);
552*404b540aSrobert 
553*404b540aSrobert 	  if (ar_filter == 0)
554*404b540aSrobert 	    {
555*404b540aSrobert 	      // Zero filter values are cleanups.
556*404b540aSrobert 	      saw_cleanup = true;
557*404b540aSrobert 	    }
558*404b540aSrobert 	  else if (ar_filter > 0)
559*404b540aSrobert 	    {
560*404b540aSrobert 	      // Positive filter values are handlers.
561*404b540aSrobert 	      catch_type = get_ttype_entry (&info, ar_filter);
562*404b540aSrobert 
563*404b540aSrobert 	      // Null catch type is a catch-all handler; we can catch foreign
564*404b540aSrobert 	      // exceptions with this.  Otherwise we must match types.
565*404b540aSrobert 	      if (! catch_type
566*404b540aSrobert 		  || (throw_type
567*404b540aSrobert 		      && get_adjusted_ptr (catch_type, throw_type,
568*404b540aSrobert 					   &thrown_ptr)))
569*404b540aSrobert 		{
570*404b540aSrobert 		  saw_handler = true;
571*404b540aSrobert 		  break;
572*404b540aSrobert 		}
573*404b540aSrobert 	    }
574*404b540aSrobert 	  else
575*404b540aSrobert 	    {
576*404b540aSrobert 	      // Negative filter values are exception specifications.
577*404b540aSrobert 	      // ??? How do foreign exceptions fit in?  As far as I can
578*404b540aSrobert 	      // see we can't match because there's no __cxa_exception
579*404b540aSrobert 	      // object to stuff bits in for __cxa_call_unexpected to use.
580*404b540aSrobert 	      // Allow them iff the exception spec is non-empty.  I.e.
581*404b540aSrobert 	      // a throw() specification results in __unexpected.
582*404b540aSrobert 	      if (throw_type
583*404b540aSrobert 		  ? ! check_exception_spec (&info, throw_type, thrown_ptr,
584*404b540aSrobert 					    ar_filter)
585*404b540aSrobert 		  : empty_exception_spec (&info, ar_filter))
586*404b540aSrobert 		{
587*404b540aSrobert 		  saw_handler = true;
588*404b540aSrobert 		  break;
589*404b540aSrobert 		}
590*404b540aSrobert 	    }
591*404b540aSrobert 
592*404b540aSrobert 	  if (ar_disp == 0)
593*404b540aSrobert 	    break;
594*404b540aSrobert 	  action_record = p + ar_disp;
595*404b540aSrobert 	}
596*404b540aSrobert 
597*404b540aSrobert       if (saw_handler)
598*404b540aSrobert 	{
599*404b540aSrobert 	  handler_switch_value = ar_filter;
600*404b540aSrobert 	  found_type = found_handler;
601*404b540aSrobert 	}
602*404b540aSrobert       else
603*404b540aSrobert 	found_type = (saw_cleanup ? found_cleanup : found_nothing);
604*404b540aSrobert     }
605*404b540aSrobert 
606*404b540aSrobert  do_something:
607*404b540aSrobert    if (found_type == found_nothing)
608*404b540aSrobert      CONTINUE_UNWINDING;
609*404b540aSrobert 
610*404b540aSrobert   if (actions & _UA_SEARCH_PHASE)
611*404b540aSrobert     {
612*404b540aSrobert       if (found_type == found_cleanup)
613*404b540aSrobert 	CONTINUE_UNWINDING;
614*404b540aSrobert 
615*404b540aSrobert       // For domestic exceptions, we cache data from phase 1 for phase 2.
616*404b540aSrobert       if (!foreign_exception)
617*404b540aSrobert         {
618*404b540aSrobert 	  save_caught_exception(ue_header, context, thrown_ptr,
619*404b540aSrobert 				handler_switch_value, language_specific_data,
620*404b540aSrobert 				landing_pad, action_record);
621*404b540aSrobert 	}
622*404b540aSrobert       return _URC_HANDLER_FOUND;
623*404b540aSrobert     }
624*404b540aSrobert 
625*404b540aSrobert  install_context:
626*404b540aSrobert 
627*404b540aSrobert   // We can't use any of the cxa routines with foreign exceptions,
628*404b540aSrobert   // because they all expect ue_header to be a struct __cxa_exception.
629*404b540aSrobert   // So in that case, call terminate or unexpected directly.
630*404b540aSrobert   if ((actions & _UA_FORCE_UNWIND)
631*404b540aSrobert       || foreign_exception)
632*404b540aSrobert     {
633*404b540aSrobert       if (found_type == found_terminate)
634*404b540aSrobert 	std::terminate ();
635*404b540aSrobert       else if (handler_switch_value < 0)
636*404b540aSrobert 	{
637*404b540aSrobert 	  try
638*404b540aSrobert 	    { std::unexpected (); }
639*404b540aSrobert 	  catch(...)
640*404b540aSrobert 	    { std::terminate (); }
641*404b540aSrobert 	}
642*404b540aSrobert     }
643*404b540aSrobert   else
644*404b540aSrobert     {
645*404b540aSrobert       if (found_type == found_terminate)
646*404b540aSrobert 	__cxa_call_terminate(ue_header);
647*404b540aSrobert 
648*404b540aSrobert       // Cache the TType base value for __cxa_call_unexpected, as we won't
649*404b540aSrobert       // have an _Unwind_Context then.
650*404b540aSrobert       if (handler_switch_value < 0)
651*404b540aSrobert 	{
652*404b540aSrobert 	  parse_lsda_header (context, language_specific_data, &info);
653*404b540aSrobert 
654*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
655*404b540aSrobert 	  const _Unwind_Word* e;
656*404b540aSrobert 	  _Unwind_Word n;
657*404b540aSrobert 
658*404b540aSrobert 	  e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1;
659*404b540aSrobert 	  // Count the number of rtti objects.
660*404b540aSrobert 	  n = 0;
661*404b540aSrobert 	  while (e[n] != 0)
662*404b540aSrobert 	    n++;
663*404b540aSrobert 
664*404b540aSrobert 	  // Count.
665*404b540aSrobert 	  ue_header->barrier_cache.bitpattern[1] = n;
666*404b540aSrobert 	  // Base (obsolete)
667*404b540aSrobert 	  ue_header->barrier_cache.bitpattern[2] = 0;
668*404b540aSrobert 	  // Stride.
669*404b540aSrobert 	  ue_header->barrier_cache.bitpattern[3] = 4;
670*404b540aSrobert 	  // List head.
671*404b540aSrobert 	  ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e;
672*404b540aSrobert #else
673*404b540aSrobert 	  xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
674*404b540aSrobert #endif
675*404b540aSrobert 	}
676*404b540aSrobert     }
677*404b540aSrobert 
678*404b540aSrobert   /* For targets with pointers smaller than the word size, we must extend the
679*404b540aSrobert      pointer, and this extension is target dependent.  */
680*404b540aSrobert   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
681*404b540aSrobert 		 __builtin_extend_pointer (ue_header));
682*404b540aSrobert   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
683*404b540aSrobert 		 handler_switch_value);
684*404b540aSrobert   _Unwind_SetIP (context, landing_pad);
685*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
686*404b540aSrobert   if (found_type == found_cleanup)
687*404b540aSrobert     __cxa_begin_cleanup(ue_header);
688*404b540aSrobert #endif
689*404b540aSrobert   return _URC_INSTALL_CONTEXT;
690*404b540aSrobert }
691*404b540aSrobert 
692*404b540aSrobert /* The ARM EABI implementation of __cxa_call_unexpected is in a
693*404b540aSrobert    different file so that the personality routine (PR) can be used
694*404b540aSrobert    standalone.  The generic routine shared datastructures with the PR
695*404b540aSrobert    so it is most convenient to implement it here.  */
696*404b540aSrobert #ifndef __ARM_EABI_UNWINDER__
697*404b540aSrobert extern "C" void
__cxa_call_unexpected(void * exc_obj_in)698*404b540aSrobert __cxa_call_unexpected (void *exc_obj_in)
699*404b540aSrobert {
700*404b540aSrobert   _Unwind_Exception *exc_obj
701*404b540aSrobert     = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
702*404b540aSrobert 
703*404b540aSrobert   __cxa_begin_catch (exc_obj);
704*404b540aSrobert 
705*404b540aSrobert   // This function is a handler for our exception argument.  If we exit
706*404b540aSrobert   // by throwing a different exception, we'll need the original cleaned up.
707*404b540aSrobert   struct end_catch_protect
708*404b540aSrobert   {
709*404b540aSrobert     end_catch_protect() { }
710*404b540aSrobert     ~end_catch_protect() { __cxa_end_catch(); }
711*404b540aSrobert   } end_catch_protect_obj;
712*404b540aSrobert 
713*404b540aSrobert   lsda_header_info info;
714*404b540aSrobert   __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
715*404b540aSrobert   const unsigned char *xh_lsda;
716*404b540aSrobert   _Unwind_Sword xh_switch_value;
717*404b540aSrobert   std::terminate_handler xh_terminate_handler;
718*404b540aSrobert 
719*404b540aSrobert   // If the unexpectedHandler rethrows the exception (e.g. to categorize it),
720*404b540aSrobert   // it will clobber data about the current handler.  So copy the data out now.
721*404b540aSrobert   xh_lsda = xh->languageSpecificData;
722*404b540aSrobert   xh_switch_value = xh->handlerSwitchValue;
723*404b540aSrobert   xh_terminate_handler = xh->terminateHandler;
724*404b540aSrobert   info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
725*404b540aSrobert 
726*404b540aSrobert   try
727*404b540aSrobert     { __unexpected (xh->unexpectedHandler); }
728*404b540aSrobert   catch(...)
729*404b540aSrobert     {
730*404b540aSrobert       // Get the exception thrown from unexpected.
731*404b540aSrobert 
732*404b540aSrobert       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
733*404b540aSrobert       __cxa_exception *new_xh = globals->caughtExceptions;
734*404b540aSrobert       void *new_ptr = new_xh + 1;
735*404b540aSrobert 
736*404b540aSrobert       // We don't quite have enough stuff cached; re-parse the LSDA.
737*404b540aSrobert       parse_lsda_header (0, xh_lsda, &info);
738*404b540aSrobert 
739*404b540aSrobert       // If this new exception meets the exception spec, allow it.
740*404b540aSrobert       if (check_exception_spec (&info, new_xh->exceptionType,
741*404b540aSrobert 				new_ptr, xh_switch_value))
742*404b540aSrobert 	__throw_exception_again;
743*404b540aSrobert 
744*404b540aSrobert       // If the exception spec allows std::bad_exception, throw that.
745*404b540aSrobert       // We don't have a thrown object to compare against, but since
746*404b540aSrobert       // bad_exception doesn't have virtual bases, that's OK; just pass 0.
747*404b540aSrobert #ifdef __EXCEPTIONS
748*404b540aSrobert       const std::type_info &bad_exc = typeid (std::bad_exception);
749*404b540aSrobert       if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
750*404b540aSrobert 	throw std::bad_exception();
751*404b540aSrobert #endif
752*404b540aSrobert 
753*404b540aSrobert       // Otherwise, die.
754*404b540aSrobert       __terminate (xh_terminate_handler);
755*404b540aSrobert     }
756*404b540aSrobert }
757*404b540aSrobert #endif
758*404b540aSrobert 
759*404b540aSrobert } // namespace __cxxabiv1
760