OSDN Git Service

2b194f2e4863fb3b5f310756e4557a3784156c33
[pf3gnuchains/gcc-fork.git] / 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, 2010
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 #ifdef __GXX_RTTI
553       // During forced unwinding, match a magic exception type.
554       if (actions & _UA_FORCE_UNWIND)
555         {
556           throw_type = &typeid(abi::__forced_unwind);
557         }
558       // With a foreign exception class, there's no exception type.
559       // ??? What to do about GNU Java and GNU Ada exceptions?
560       else if (foreign_exception)
561         {
562           throw_type = &typeid(abi::__foreign_exception);
563         }
564       else
565 #endif
566         {
567           thrown_ptr = __get_object_from_ue (ue_header);
568           throw_type = __get_exception_header_from_obj
569             (thrown_ptr)->exceptionType;
570         }
571 #endif
572
573       while (1)
574         {
575           p = action_record;
576           p = read_sleb128 (p, &ar_filter);
577           read_sleb128 (p, &ar_disp);
578
579           if (ar_filter == 0)
580             {
581               // Zero filter values are cleanups.
582               saw_cleanup = true;
583             }
584           else if (ar_filter > 0)
585             {
586               // Positive filter values are handlers.
587               catch_type = get_ttype_entry (&info, ar_filter);
588
589               // Null catch type is a catch-all handler; we can catch foreign
590               // exceptions with this.  Otherwise we must match types.
591               if (! catch_type
592                   || (throw_type
593                       && get_adjusted_ptr (catch_type, throw_type,
594                                            &thrown_ptr)))
595                 {
596                   saw_handler = true;
597                   break;
598                 }
599             }
600           else
601             {
602               // Negative filter values are exception specifications.
603               // ??? How do foreign exceptions fit in?  As far as I can
604               // see we can't match because there's no __cxa_exception
605               // object to stuff bits in for __cxa_call_unexpected to use.
606               // Allow them iff the exception spec is non-empty.  I.e.
607               // a throw() specification results in __unexpected.
608               if ((throw_type
609                    && !(actions & _UA_FORCE_UNWIND)
610                    && !foreign_exception)
611                   ? ! check_exception_spec (&info, throw_type, thrown_ptr,
612                                             ar_filter)
613                   : empty_exception_spec (&info, ar_filter))
614                 {
615                   saw_handler = true;
616                   break;
617                 }
618             }
619
620           if (ar_disp == 0)
621             break;
622           action_record = p + ar_disp;
623         }
624
625       if (saw_handler)
626         {
627           handler_switch_value = ar_filter;
628           found_type = found_handler;
629         }
630       else
631         found_type = (saw_cleanup ? found_cleanup : found_nothing);
632     }
633
634  do_something:
635    if (found_type == found_nothing)
636      CONTINUE_UNWINDING;
637
638   if (actions & _UA_SEARCH_PHASE)
639     {
640       if (found_type == found_cleanup)
641         CONTINUE_UNWINDING;
642
643       // For domestic exceptions, we cache data from phase 1 for phase 2.
644       if (!foreign_exception)
645         {
646           save_caught_exception(ue_header, context, thrown_ptr,
647                                 handler_switch_value, language_specific_data,
648                                 landing_pad, action_record);
649         }
650       return _URC_HANDLER_FOUND;
651     }
652
653  install_context:
654   
655   // We can't use any of the cxa routines with foreign exceptions,
656   // because they all expect ue_header to be a struct __cxa_exception.
657   // So in that case, call terminate or unexpected directly.
658   if ((actions & _UA_FORCE_UNWIND)
659       || foreign_exception)
660     {
661       if (found_type == found_terminate)
662         std::terminate ();
663       else if (handler_switch_value < 0)
664         {
665           __try 
666             { std::unexpected (); } 
667           __catch(...) 
668             { std::terminate (); }
669         }
670     }
671   else
672     {
673       if (found_type == found_terminate)
674         __cxa_call_terminate(ue_header);
675
676       // Cache the TType base value for __cxa_call_unexpected, as we won't
677       // have an _Unwind_Context then.
678       if (handler_switch_value < 0)
679         {
680           parse_lsda_header (context, language_specific_data, &info);
681
682 #ifdef __ARM_EABI_UNWINDER__
683           const _Unwind_Word* e;
684           _Unwind_Word n;
685           
686           e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1;
687           // Count the number of rtti objects.
688           n = 0;
689           while (e[n] != 0)
690             n++;
691
692           // Count.
693           ue_header->barrier_cache.bitpattern[1] = n;
694           // Base (obsolete)
695           ue_header->barrier_cache.bitpattern[2] = 0;
696           // Stride.
697           ue_header->barrier_cache.bitpattern[3] = 4;
698           // List head.
699           ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e;
700 #else
701           xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
702 #endif
703         }
704     }
705
706   /* For targets with pointers smaller than the word size, we must extend the
707      pointer, and this extension is target dependent.  */
708   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
709                  __builtin_extend_pointer (ue_header));
710   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
711                  handler_switch_value);
712   _Unwind_SetIP (context, landing_pad);
713 #ifdef __ARM_EABI_UNWINDER__
714   if (found_type == found_cleanup)
715     __cxa_begin_cleanup(ue_header);
716 #endif
717   return _URC_INSTALL_CONTEXT;
718 }
719
720 /* The ARM EABI implementation of __cxa_call_unexpected is in a
721    different file so that the personality routine (PR) can be used
722    standalone.  The generic routine shared datastructures with the PR
723    so it is most convenient to implement it here.  */
724 #ifndef __ARM_EABI_UNWINDER__
725 extern "C" void
726 __cxa_call_unexpected (void *exc_obj_in)
727 {
728   _Unwind_Exception *exc_obj
729     = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
730
731   __cxa_begin_catch (exc_obj);
732
733   // This function is a handler for our exception argument.  If we exit
734   // by throwing a different exception, we'll need the original cleaned up.
735   struct end_catch_protect
736   {
737     end_catch_protect() { }
738     ~end_catch_protect() { __cxa_end_catch(); }
739   } end_catch_protect_obj;
740
741   lsda_header_info info;
742   __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
743   const unsigned char *xh_lsda;
744   _Unwind_Sword xh_switch_value;
745   std::terminate_handler xh_terminate_handler;
746
747   // If the unexpectedHandler rethrows the exception (e.g. to categorize it),
748   // it will clobber data about the current handler.  So copy the data out now.
749   xh_lsda = xh->languageSpecificData;
750   xh_switch_value = xh->handlerSwitchValue;
751   xh_terminate_handler = xh->terminateHandler;
752   info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
753
754   __try 
755     { __unexpected (xh->unexpectedHandler); } 
756   __catch(...) 
757     {
758       // Get the exception thrown from unexpected.
759
760       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
761       __cxa_exception *new_xh = globals->caughtExceptions;
762       void *new_ptr = __get_object_from_ambiguous_exception (new_xh);
763
764       // We don't quite have enough stuff cached; re-parse the LSDA.
765       parse_lsda_header (0, xh_lsda, &info);
766
767       // If this new exception meets the exception spec, allow it.
768       if (check_exception_spec (&info, __get_exception_header_from_obj
769                                   (new_ptr)->exceptionType,
770                                 new_ptr, xh_switch_value))
771         __throw_exception_again;
772
773       // If the exception spec allows std::bad_exception, throw that.
774       // We don't have a thrown object to compare against, but since
775       // bad_exception doesn't have virtual bases, that's OK; just pass 0.
776 #if defined(__EXCEPTIONS) && defined(__GXX_RTTI)
777       const std::type_info &bad_exc = typeid (std::bad_exception);
778       if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
779         throw std::bad_exception();
780 #endif   
781
782       // Otherwise, die.
783       __terminate (xh_terminate_handler);
784     }
785 }
786 #endif
787
788 } // namespace __cxxabiv1