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