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