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