]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libcxxrt/exception.cc
Merge ACPICA 20120215.
[FreeBSD/FreeBSD.git] / contrib / libcxxrt / exception.cc
1 #include <stdlib.h>
2 #include <dlfcn.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdint.h>
6 #include <pthread.h>
7 #include "typeinfo.h"
8 #include "dwarf_eh.h"
9 #include "cxxabi.h"
10
11 #pragma weak pthread_key_create
12 #pragma weak pthread_setspecific
13 #pragma weak pthread_getspecific
14 #pragma weak pthread_once
15 #pragma weak pthread_once
16 #pragma weak pthread_cond_signal
17 #pragma weak pthread_cond_wait
18 #pragma weak pthread_mutex_lock
19 #pragma weak pthread_mutex_unlock
20
21
22 using namespace ABI_NAMESPACE;
23
24 /**
25  * Saves the result of the landing pad that we have found.  For ARM, this is
26  * stored in the generic unwind structure, while on other platforms it is
27  * stored in the C++ exception.
28  */
29 static void saveLandingPad(struct _Unwind_Context *context,
30                            struct _Unwind_Exception *ucb,
31                            struct __cxa_exception *ex,
32                            int selector,
33                            dw_eh_ptr_t landingPad)
34 {
35 #ifdef __arm__
36         // On ARM, we store the saved exception in the generic part of the structure
37         ucb->barrier_cache.sp = _Unwind_GetGR(context, 13);
38         ucb->barrier_cache.bitpattern[1] = (uint32_t)selector;
39         ucb->barrier_cache.bitpattern[3] = (uint32_t)landingPad;
40 #endif
41         // Cache the results for the phase 2 unwind, if we found a handler
42         // and this is not a foreign exception.  
43         if (ex)
44         {
45                 ex->handlerSwitchValue = selector;
46                 ex->catchTemp = landingPad;
47         }
48 }
49
50 /**
51  * Loads the saved landing pad.  Returns 1 on success, 0 on failure.
52  */
53 static int loadLandingPad(struct _Unwind_Context *context,
54                           struct _Unwind_Exception *ucb,
55                           struct __cxa_exception *ex,
56                           unsigned long *selector,
57                           dw_eh_ptr_t *landingPad)
58 {
59 #ifdef __arm__
60         *selector = ucb->barrier_cache.bitpattern[1];
61         *landingPad = (dw_eh_ptr_t)ucb->barrier_cache.bitpattern[3];
62         return 1;
63 #else
64         if (ex)
65         {
66                 *selector = ex->handlerSwitchValue;
67                 *landingPad = (dw_eh_ptr_t)ex->catchTemp;
68                 return 0;
69         }
70         return 0;
71 #endif
72 }
73
74 static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex,
75                                                     struct _Unwind_Context *context)
76 {
77 #ifdef __arm__
78         if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; }
79 #endif
80         return _URC_CONTINUE_UNWIND;
81 }
82
83
84 extern "C" void __cxa_free_exception(void *thrown_exception);
85 extern "C" void __cxa_free_dependent_exception(void *thrown_exception);
86 extern "C" void* __dynamic_cast(const void *sub,
87                                 const __class_type_info *src,
88                                 const __class_type_info *dst,
89                                 ptrdiff_t src2dst_offset);
90
91 /**
92  * The type of a handler that has been found.
93  */
94 typedef enum
95 {
96         /** No handler. */
97         handler_none,
98         /**
99          * A cleanup - the exception will propagate through this frame, but code
100          * must be run when this happens.
101          */
102         handler_cleanup,
103         /**
104          * A catch statement.  The exception will not propagate past this frame
105          * (without an explicit rethrow).
106          */
107         handler_catch
108 } handler_type;
109
110 /**
111  * Per-thread info required by the runtime.  We store a single structure
112  * pointer in thread-local storage, because this tends to be a scarce resource
113  * and it's impolite to steal all of it and not leave any for the rest of the
114  * program.
115  *
116  * Instances of this structure are allocated lazily - at most one per thread -
117  * and are destroyed on thread termination.
118  */
119 struct __cxa_thread_info
120 {
121         /** The termination handler for this thread. */
122         terminate_handler terminateHandler;
123         /** The unexpected exception handler for this thread. */
124         unexpected_handler unexpectedHandler;
125         /**
126          * The number of emergency buffers held by this thread.  This is 0 in
127          * normal operation - the emergency buffers are only used when malloc()
128          * fails to return memory for allocating an exception.  Threads are not
129          * permitted to hold more than 4 emergency buffers (as per recommendation
130          * in ABI spec [3.3.1]).
131          */
132         int emergencyBuffersHeld;
133         /**
134          * The exception currently running in a cleanup.
135          */
136         _Unwind_Exception *currentCleanup;
137         /**
138          * The public part of this structure, accessible from outside of this
139          * module.
140          */
141         __cxa_eh_globals globals;
142 };
143 /**
144  * Dependent exception.  This 
145  */
146 struct __cxa_dependent_exception
147 {
148 #if __LP64__
149         void *primaryException;
150 #endif
151         std::type_info *exceptionType;
152         void (*exceptionDestructor) (void *); 
153         unexpected_handler unexpectedHandler;
154         terminate_handler terminateHandler;
155         __cxa_exception *nextException;
156         int handlerCount;
157 #ifdef __arm__
158         _Unwind_Exception *nextCleanup;
159         int cleanupCount;
160 #endif
161         int handlerSwitchValue;
162         const char *actionRecord;
163         const char *languageSpecificData;
164         void *catchTemp;
165         void *adjustedPtr;
166 #if !__LP64__
167         void *primaryException;
168 #endif
169         _Unwind_Exception unwindHeader;
170 };
171
172
173 namespace std
174 {
175         void unexpected();
176         class exception
177         {
178                 public:
179                         virtual ~exception() throw();
180                         virtual const char* what() const throw();
181         };
182
183 }
184
185 extern "C" std::type_info *__cxa_current_exception_type();
186
187 /**
188  * Class of exceptions to distinguish between this and other exception types.
189  *
190  * The first four characters are the vendor ID.  Currently, we use GNUC,
191  * because we aim for ABI-compatibility with the GNU implementation, and
192  * various checks may test for equality of the class, which is incorrect.
193  */
194 static const uint64_t exception_class =
195         EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\0');
196 /**
197  * Class used for dependent exceptions.  
198  */
199 static const uint64_t dependent_exception_class =
200         EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01');
201 /**
202  * The low four bytes of the exception class, indicating that we conform to the
203  * Itanium C++ ABI.  This is currently unused, but should be used in the future
204  * if we change our exception class, to allow this library and libsupc++ to be
205  * linked to the same executable and both to interoperate.
206  */
207 static const uint32_t abi_exception_class = 
208         GENERIC_EXCEPTION_CLASS('C', '+', '+', '\0');
209
210 static bool isCXXException(uint64_t cls)
211 {
212         return (cls == exception_class) || (cls == dependent_exception_class);
213 }
214
215 static bool isDependentException(uint64_t cls)
216 {
217         return cls == dependent_exception_class;
218 }
219
220 static __cxa_exception *exceptionFromPointer(void *ex)
221 {
222         return (__cxa_exception*)((char*)ex -
223                         offsetof(struct __cxa_exception, unwindHeader));
224 }
225 static __cxa_exception *realExceptionFromException(__cxa_exception *ex)
226 {
227         if (!isDependentException(ex->unwindHeader.exception_class)) { return ex; }
228         return ((__cxa_exception*)(((__cxa_dependent_exception*)ex)->primaryException))-1;
229 }
230
231
232 namespace std
233 {
234         // Forward declaration of standard library terminate() function used to
235         // abort execution.
236         void terminate(void);
237 }
238
239 using namespace ABI_NAMESPACE;
240
241
242
243 /** The global termination handler. */
244 static terminate_handler terminateHandler = abort;
245 /** The global unexpected exception handler. */
246 static unexpected_handler unexpectedHandler = std::terminate;
247
248 /** Key used for thread-local data. */
249 static pthread_key_t eh_key;
250
251
252 /**
253  * Cleanup function, allowing foreign exception handlers to correctly destroy
254  * this exception if they catch it.
255  */
256 static void exception_cleanup(_Unwind_Reason_Code reason, 
257                               struct _Unwind_Exception *ex)
258 {
259         __cxa_free_exception((void*)ex);
260 }
261 static void dependent_exception_cleanup(_Unwind_Reason_Code reason, 
262                               struct _Unwind_Exception *ex)
263 {
264
265         __cxa_free_dependent_exception((void*)ex);
266 }
267
268 /**
269  * Recursively walk a list of exceptions and delete them all in post-order.
270  */
271 static void free_exception_list(__cxa_exception *ex)
272 {
273         if (0 != ex->nextException)
274         {
275                 free_exception_list(ex->nextException);
276         }
277         // __cxa_free_exception() expects to be passed the thrown object, which
278         // immediately follows the exception, not the exception itself
279         __cxa_free_exception(ex+1);
280 }
281
282 /**
283  * Cleanup function called when a thread exists to make certain that all of the
284  * per-thread data is deleted.
285  */
286 static void thread_cleanup(void* thread_info)
287 {
288         __cxa_thread_info *info = (__cxa_thread_info*)thread_info;
289         if (info->globals.caughtExceptions)
290         {
291                 free_exception_list(info->globals.caughtExceptions);
292         }
293         free(thread_info);
294 }
295
296
297 /**
298  * Once control used to protect the key creation.
299  */
300 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
301
302 /**
303  * We may not be linked against a full pthread implementation.  If we're not,
304  * then we need to fake the thread-local storage by storing 'thread-local'
305  * things in a global.
306  */
307 static bool fakeTLS;
308 /**
309  * Thread-local storage for a single-threaded program.
310  */
311 static __cxa_thread_info singleThreadInfo;
312 /**
313  * Initialise eh_key.
314  */
315 static void init_key(void)
316 {
317         if ((0 == pthread_key_create) ||
318             (0 == pthread_setspecific) ||
319             (0 == pthread_getspecific))
320         {
321                 fakeTLS = true;
322                 return;
323         }
324         pthread_key_create(&eh_key, thread_cleanup);
325         pthread_setspecific(eh_key, (void*)0x42);
326         fakeTLS = (pthread_getspecific(eh_key) != (void*)0x42);
327         pthread_setspecific(eh_key, 0);
328 }
329
330 /**
331  * Returns the thread info structure, creating it if it is not already created.
332  */
333 static __cxa_thread_info *thread_info()
334 {
335         if ((0 == pthread_once) || pthread_once(&once_control, init_key))
336         {
337                 fakeTLS = true;
338         }
339         if (fakeTLS) { return &singleThreadInfo; }
340         __cxa_thread_info *info = (__cxa_thread_info*)pthread_getspecific(eh_key);
341         if (0 == info)
342         {
343                 info = (__cxa_thread_info*)calloc(1, sizeof(__cxa_thread_info));
344                 pthread_setspecific(eh_key, info);
345         }
346         return info;
347 }
348 /**
349  * Fast version of thread_info().  May fail if thread_info() is not called on
350  * this thread at least once already.
351  */
352 static __cxa_thread_info *thread_info_fast()
353 {
354         if (fakeTLS) { return &singleThreadInfo; }
355         return (__cxa_thread_info*)pthread_getspecific(eh_key);
356 }
357 /**
358  * ABI function returning the __cxa_eh_globals structure.
359  */
360 extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void)
361 {
362         return &(thread_info()->globals);
363 }
364 /**
365  * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already
366  * been called at least once by this thread.
367  */
368 extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void)
369 {
370         return &(thread_info_fast()->globals);
371 }
372
373 /**
374  * An emergency allocation reserved for when malloc fails.  This is treated as
375  * 16 buffers of 1KB each.
376  */
377 static char emergency_buffer[16384];
378 /**
379  * Flag indicating whether each buffer is allocated.
380  */
381 static bool buffer_allocated[16];
382 /**
383  * Lock used to protect emergency allocation.
384  */
385 static pthread_mutex_t emergency_malloc_lock = PTHREAD_MUTEX_INITIALIZER;
386 /**
387  * Condition variable used to wait when two threads are both trying to use the
388  * emergency malloc() buffer at once.
389  */
390 static pthread_cond_t emergency_malloc_wait = PTHREAD_COND_INITIALIZER;
391
392 /**
393  * Allocates size bytes from the emergency allocation mechanism, if possible.
394  * This function will fail if size is over 1KB or if this thread already has 4
395  * emergency buffers.  If all emergency buffers are allocated, it will sleep
396  * until one becomes available.
397  */
398 static char *emergency_malloc(size_t size)
399 {
400         if (size > 1024) { return 0; }
401
402         __cxa_thread_info *info = thread_info();
403         // Only 4 emergency buffers allowed per thread!
404         if (info->emergencyBuffersHeld > 3) { return 0; }
405
406         if (pthread_mutex_lock)
407         {
408                 pthread_mutex_lock(&emergency_malloc_lock);
409         }
410         int buffer = -1;
411         while (buffer < 0)
412         {
413                 // While we were sleeping on the lock, another thread might have free'd
414                 // enough memory for us to use, so try the allocation again - no point
415                 // using the emergency buffer if there is some real memory that we can
416                 // use...
417                 void *m = calloc(1, size);
418                 if (0 != m)
419                 {
420                         if (pthread_mutex_unlock)
421                         {
422                                 pthread_mutex_unlock(&emergency_malloc_lock);
423                         }
424                         return (char*)m;
425                 }
426                 for (int i=0 ; i<16 ; i++)
427                 {
428                         if (!buffer_allocated[i])
429                         {
430                                 buffer = i;
431                                 buffer_allocated[i] = true;
432                                 break;
433                         }
434                 }
435                 // If there still isn't a buffer available, then sleep on the condition
436                 // variable.  This will be signalled when another thread releases one
437                 // of the emergency buffers.
438                 if (buffer < 0)
439                 {
440                         // If we don't have pthread_cond_wait, then there is only one
441                         // thread and it's already used all of the emergency buffers, so we
442                         // have no alternative but to die.  Calling abort() instead of
443                         // terminate, because terminate can throw exceptions, which can
444                         // bring us back here and infinite loop.
445                         if (!pthread_cond_wait)
446                         {
447                                 fputs("Terminating while out of memory trying to throw an exception",
448                                       stderr);
449                                 abort();
450                         }
451                         pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock);
452                 }
453         }
454         if (pthread_mutex_unlock)
455         {
456                 pthread_mutex_unlock(&emergency_malloc_lock);
457         }
458         info->emergencyBuffersHeld++;
459         return emergency_buffer + (1024 * buffer);
460 }
461
462 /**
463  * Frees a buffer returned by emergency_malloc().
464  *
465  * Note: Neither this nor emergency_malloc() is particularly efficient.  This
466  * should not matter, because neither will be called in normal operation - they
467  * are only used when the program runs out of memory, which should not happen
468  * often.
469  */
470 static void emergency_malloc_free(char *ptr)
471 {
472         int buffer = -1;
473         // Find the buffer corresponding to this pointer.
474         for (int i=0 ; i<16 ; i++)
475         {
476                 if (ptr == (void*)(emergency_buffer + (1024 * i)))
477                 {
478                         buffer = i;
479                         break;
480                 }
481         }
482         assert(buffer > 0 &&
483                "Trying to free something that is not an emergency buffer!");
484         // emergency_malloc() is expected to return 0-initialized data.  We don't
485         // zero the buffer when allocating it, because the static buffers will
486         // begin life containing 0 values.
487         memset((void*)ptr, 0, 1024);
488         // Signal the condition variable to wake up any threads that are blocking
489         // waiting for some space in the emergency buffer
490         if (pthread_mutex_lock)
491         {
492                 pthread_mutex_lock(&emergency_malloc_lock);
493         }
494         // In theory, we don't need to do this with the lock held.  In practice,
495         // our array of bools will probably be updated using 32-bit or 64-bit
496         // memory operations, so this update may clobber adjacent values.
497         buffer_allocated[buffer] = false;
498         if (pthread_cond_signal && pthread_mutex_unlock)
499         {
500                 pthread_cond_signal(&emergency_malloc_wait);
501                 pthread_mutex_unlock(&emergency_malloc_lock);
502         }
503 }
504
505 static char *alloc_or_die(size_t size)
506 {
507         char *buffer = (char*)calloc(1, size);
508
509         // If calloc() doesn't want to give us any memory, try using an emergency
510         // buffer.
511         if (0 == buffer)
512         {
513                 buffer = emergency_malloc(size);
514                 // This is only reached if the allocation is greater than 1KB, and
515                 // anyone throwing objects that big really should know better.  
516                 if (0 == buffer)
517                 {
518                         fprintf(stderr, "Out of memory attempting to allocate exception\n");
519                         std::terminate();
520                 }
521         }
522         return buffer;
523 }
524 static void free_exception(char *e)
525 {
526         // If this allocation is within the address range of the emergency buffer,
527         // don't call free() because it was not allocated with malloc()
528         if ((e > emergency_buffer) &&
529             (e < (emergency_buffer + sizeof(emergency_buffer))))
530         {
531                 emergency_malloc_free(e);
532         }
533         else
534         {
535                 free(e);
536         }
537 }
538
539 /**
540  * Allocates an exception structure.  Returns a pointer to the space that can
541  * be used to store an object of thrown_size bytes.  This function will use an
542  * emergency buffer if malloc() fails, and may block if there are no such
543  * buffers available.
544  */
545 extern "C" void *__cxa_allocate_exception(size_t thrown_size)
546 {
547         size_t size = thrown_size + sizeof(__cxa_exception);
548         char *buffer = alloc_or_die(size);
549         return buffer+sizeof(__cxa_exception);
550 }
551
552 extern "C" void *__cxa_allocate_dependent_exception(void)
553 {
554         size_t size = sizeof(__cxa_dependent_exception);
555         char *buffer = alloc_or_die(size);
556         return buffer+sizeof(__cxa_dependent_exception);
557 }
558
559 /**
560  * __cxa_free_exception() is called when an exception was thrown in between
561  * calling __cxa_allocate_exception() and actually throwing the exception.
562  * This happens when the object's copy constructor throws an exception.
563  *
564  * In this implementation, it is also called by __cxa_end_catch() and during
565  * thread cleanup.
566  */
567 extern "C" void __cxa_free_exception(void *thrown_exception)
568 {
569         __cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
570         // Free the object that was thrown, calling its destructor
571         if (0 != ex->exceptionDestructor)
572         {
573                 try
574                 {
575                         ex->exceptionDestructor(thrown_exception);
576                 }
577                 catch(...)
578                 {
579                         // FIXME: Check that this is really what the spec says to do.
580                         std::terminate();
581                 }
582         }
583
584         free_exception((char*)ex);
585 }
586
587 static void releaseException(__cxa_exception *exception)
588 {
589         if (isDependentException(exception->unwindHeader.exception_class))
590         {
591                 __cxa_free_dependent_exception(exception+1);
592                 return;
593         }
594         if (__sync_sub_and_fetch(&exception->referenceCount, 1) == 0)
595         {
596                 // __cxa_free_exception() expects to be passed the thrown object,
597                 // which immediately follows the exception, not the exception
598                 // itself
599                 __cxa_free_exception(exception+1);
600         }
601 }
602
603 void __cxa_free_dependent_exception(void *thrown_exception)
604 {
605         __cxa_dependent_exception *ex = ((__cxa_dependent_exception*)thrown_exception) - 1;
606         assert(isDependentException(ex->unwindHeader.exception_class));
607         if (ex->primaryException)
608         {
609                 releaseException(realExceptionFromException((__cxa_exception*)ex));
610         }
611         free_exception((char*)ex);
612 }
613
614 /**
615  * Callback function used with _Unwind_Backtrace().
616  *
617  * Prints a stack trace.  Used only for debugging help.
618  *
619  * Note: As of FreeBSD 8.1, dladd() still doesn't work properly, so this only
620  * correctly prints function names from public, relocatable, symbols.
621  */
622 static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c)
623 {
624         Dl_info myinfo;
625         int mylookup =
626                 dladdr((void*)(uintptr_t)__cxa_current_exception_type, &myinfo);
627         void *ip = (void*)_Unwind_GetIP(context);
628         Dl_info info;
629         if (dladdr(ip, &info) != 0)
630         {
631                 if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
632                 {
633                         printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
634                 }
635         }
636         return _URC_CONTINUE_UNWIND;
637 }
638
639 /**
640  * Report a failure that occurred when attempting to throw an exception.
641  *
642  * If the failure happened by falling off the end of the stack without finding
643  * a handler, prints a back trace before aborting.
644  */
645 static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exception)
646 {
647         switch (err)
648         {
649                 default: break;
650                 case _URC_FATAL_PHASE1_ERROR:
651                         fprintf(stderr, "Fatal error during phase 1 unwinding\n");
652                         break;
653 #ifndef __arm__
654                 case _URC_FATAL_PHASE2_ERROR:
655                         fprintf(stderr, "Fatal error during phase 2 unwinding\n");
656                         break;
657 #endif
658                 case _URC_END_OF_STACK:
659                         fprintf(stderr, "Terminating due to uncaught exception %p", 
660                                         (void*)thrown_exception);
661                         thrown_exception = realExceptionFromException(thrown_exception);
662                         static const __class_type_info *e_ti =
663                                 static_cast<const __class_type_info*>(&typeid(std::exception));
664                         const __class_type_info *throw_ti =
665                                 dynamic_cast<const __class_type_info*>(thrown_exception->exceptionType);
666                         if (throw_ti)
667                         {
668                                 std::exception *e =
669                                         (std::exception*)e_ti->cast_to((void*)(thrown_exception+1),
670                                                         throw_ti);
671                                 if (e)
672                                 {
673                                         fprintf(stderr, " '%s'", e->what());
674                                 }
675                         }
676
677                         size_t bufferSize = 128;
678                         char *demangled = (char*)malloc(bufferSize);
679                         const char *mangled = thrown_exception->exceptionType->name();
680                         int status;
681                         demangled = __cxa_demangle(mangled, demangled, &bufferSize, &status);
682                         fprintf(stderr, " of type %s\n", 
683                                 status == 0 ? (const char*)demangled : mangled);
684                         if (status == 0) { free(demangled); }
685                         // Print a back trace if no handler is found.
686                         // TODO: Make this optional
687                         _Unwind_Backtrace(trace, 0);
688                         break;
689         }
690         std::terminate();
691 }
692
693 static void throw_exception(__cxa_exception *ex)
694 {
695         __cxa_thread_info *info = thread_info();
696         ex->unexpectedHandler = info->unexpectedHandler;
697         if (0 == ex->unexpectedHandler)
698         {
699                 ex->unexpectedHandler = unexpectedHandler;
700         }
701         ex->terminateHandler  = info->terminateHandler;
702         if (0 == ex->terminateHandler)
703         {
704                 ex->terminateHandler = terminateHandler;
705         }
706         info->globals.uncaughtExceptions++;
707
708         _Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader);
709         // The _Unwind_RaiseException() function should not return, it should
710         // unwind the stack past this function.  If it does return, then something
711         // has gone wrong.
712         report_failure(err, ex);
713 }
714
715
716 /**
717  * ABI function for throwing an exception.  Takes the object to be thrown (the
718  * pointer returned by __cxa_allocate_exception()), the type info for the
719  * pointee, and the destructor (if there is one) as arguments.
720  */
721 extern "C" void __cxa_throw(void *thrown_exception,
722                             std::type_info *tinfo,
723                             void(*dest)(void*))
724 {
725         __cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
726
727         ex->referenceCount = 1;
728         ex->exceptionType = tinfo;
729         
730         ex->exceptionDestructor = dest;
731         
732         ex->unwindHeader.exception_class = exception_class;
733         ex->unwindHeader.exception_cleanup = exception_cleanup;
734
735         throw_exception(ex);
736 }
737
738 extern "C" void __cxa_rethrow_primary_exception(void* thrown_exception)
739 {
740         if (NULL == thrown_exception) { return; }
741
742         __cxa_exception *original = exceptionFromPointer(thrown_exception);
743         __cxa_dependent_exception *ex = ((__cxa_dependent_exception*)__cxa_allocate_dependent_exception())-1;
744
745         ex->primaryException = thrown_exception;
746         __cxa_increment_exception_refcount(thrown_exception);
747
748         ex->exceptionType = original->exceptionType;
749         ex->unwindHeader.exception_class = dependent_exception_class;
750         ex->unwindHeader.exception_cleanup = dependent_exception_cleanup;
751
752         throw_exception((__cxa_exception*)ex);
753 }
754
755 extern "C" void *__cxa_current_primary_exception(void)
756 {
757         __cxa_eh_globals* globals = __cxa_get_globals();
758         __cxa_exception *ex = globals->caughtExceptions;
759
760         if (0 == ex) { return NULL; }
761         ex = realExceptionFromException(ex);
762         __sync_fetch_and_add(&ex->referenceCount, 1);
763         return ex + 1;
764 }
765
766 extern "C" void __cxa_increment_exception_refcount(void* thrown_exception)
767 {
768         if (NULL == thrown_exception) { return; }
769         __cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
770         if (isDependentException(ex->unwindHeader.exception_class)) { return; }
771         __sync_fetch_and_add(&ex->referenceCount, 1);
772 }
773 extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception)
774 {
775         if (NULL == thrown_exception) { return; }
776         __cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
777         releaseException(ex);
778 }
779
780 /**
781  * ABI function.  Rethrows the current exception.  Does not remove the
782  * exception from the stack or decrement its handler count - the compiler is
783  * expected to set the landing pad for this function to the end of the catch
784  * block, and then call _Unwind_Resume() to continue unwinding once
785  * __cxa_end_catch() has been called and any cleanup code has been run.
786  */
787 extern "C" void __cxa_rethrow()
788 {
789         __cxa_eh_globals *globals = __cxa_get_globals();
790         // Note: We don't remove this from the caught list here, because
791         // __cxa_end_catch will be called when we unwind out of the try block.  We
792         // could probably make this faster by providing an alternative rethrow
793         // function and ensuring that all cleanup code is run before calling it, so
794         // we can skip the top stack frame when unwinding.
795         __cxa_exception *ex = globals->caughtExceptions;
796
797         if (0 == ex)
798         {
799                 fprintf(stderr,
800                         "Attempting to rethrow an exception that doesn't exist!\n");
801                 std::terminate();
802         }
803
804         assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!");
805
806         // ex->handlerCount will be decremented in __cxa_end_catch in enclosing
807         // catch block
808         
809         // Make handler count negative. This will tell __cxa_end_catch that
810         // exception was rethrown and exception object should not be destroyed
811         // when handler count become zero
812         ex->handlerCount = -ex->handlerCount;
813
814         // Continue unwinding the stack with this exception.  This should unwind to
815         // the place in the caller where __cxa_end_catch() is called.  The caller
816         // will then run cleanup code and bounce the exception back with
817         // _Unwind_Resume().
818         _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(&ex->unwindHeader);
819         report_failure(err, ex);
820 }
821
822 /**
823  * Returns the type_info object corresponding to the filter.
824  */
825 static std::type_info *get_type_info_entry(_Unwind_Context *context,
826                                            dwarf_eh_lsda *lsda,
827                                            int filter)
828 {
829         // Get the address of the record in the table.
830         dw_eh_ptr_t record = lsda->type_table - 
831                 dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter;
832         //record -= 4;
833         dw_eh_ptr_t start = record;
834         // Read the value, but it's probably an indirect reference...
835         int64_t offset = read_value(lsda->type_table_encoding, &record);
836
837         // (If the entry is 0, don't try to dereference it.  That would be bad.)
838         if (offset == 0) { return 0; }
839
840         // ...so we need to resolve it
841         return (std::type_info*)resolve_indirect_value(context,
842                         lsda->type_table_encoding, offset, start);
843 }
844
845
846
847 /**
848  * Checks the type signature found in a handler against the type of the thrown
849  * object.  If ex is 0 then it is assumed to be a foreign exception and only
850  * matches cleanups.
851  */
852 static bool check_type_signature(__cxa_exception *ex,
853                                  const std::type_info *type,
854                                  void *&adjustedPtr)
855 {
856         // TODO: For compatibility with the GNU implementation, we should move this
857         // out into a __do_catch() virtual function in std::type_info
858         void *exception_ptr = (void*)(ex+1);
859     const std::type_info *ex_type = ex->exceptionType;
860
861         const __pointer_type_info *ptr_type =
862                 dynamic_cast<const __pointer_type_info*>(ex_type);
863         if (0 != ptr_type)
864         {
865                 exception_ptr = *(void**)exception_ptr;
866         }
867         // Always match a catchall, even with a foreign exception
868         //
869         // Note: A 0 here is a catchall, not a cleanup, so we return true to
870         // indicate that we found a catch.
871         //
872         // TODO: Provide a class for matching against foreign exceptions.  This is
873         // already done in libobjc2, allowing C++ exceptions to be boxed as
874         // Objective-C objects.  We should do something similar, allowing foreign
875         // exceptions to be wrapped in a C++ exception and delivered.
876         if (0 == type)
877         {
878                 if (ex)
879                 {
880                         adjustedPtr = exception_ptr;
881                 }
882                 return true;
883         }
884
885         if (0 == ex) { return false; }
886
887         const __pointer_type_info *target_ptr_type =
888                 dynamic_cast<const __pointer_type_info*>(type);
889
890         if (0 != ptr_type && 0 != target_ptr_type)
891         {
892                 if (ptr_type->__flags & ~target_ptr_type->__flags)
893                 {
894                         // Handler pointer is less qualified
895                         return false;
896                 }
897
898                 // Special case for void* handler.  
899                 if(*target_ptr_type->__pointee == typeid(void))
900                 {
901                         adjustedPtr = exception_ptr;
902                         return true;
903                 }
904
905                 ex_type = ptr_type->__pointee;
906                 type = target_ptr_type->__pointee;
907         }
908
909         // If the types are the same, no casting is needed.
910         if (*type == *ex_type)
911         {
912                 adjustedPtr = exception_ptr;
913                 return true;
914         }
915
916         const __class_type_info *cls_type =
917                 dynamic_cast<const __class_type_info*>(ex_type);
918         const __class_type_info *target_cls_type =
919                 dynamic_cast<const __class_type_info*>(type);
920
921         if (0 != cls_type &&
922                 0 != target_cls_type &&
923                 cls_type->can_cast_to(target_cls_type))
924         {
925                 adjustedPtr = cls_type->cast_to(exception_ptr, target_cls_type);
926                 return true;
927         }
928         return false;
929 }
930 /**
931  * Checks whether the exception matches the type specifiers in this action
932  * record.  If the exception only matches cleanups, then this returns false.
933  * If it matches a catch (including a catchall) then it returns true.
934  *
935  * The selector argument is used to return the selector that is passed in the
936  * second exception register when installing the context.
937  */
938 static handler_type check_action_record(_Unwind_Context *context,
939                                         dwarf_eh_lsda *lsda,
940                                         dw_eh_ptr_t action_record,
941                                         __cxa_exception *ex,
942                                         unsigned long *selector,
943                                         void *&adjustedPtr)
944 {
945         if (!action_record) { return handler_cleanup; }
946         handler_type found = handler_none;
947         while (action_record)
948         {
949                 int filter = read_sleb128(&action_record);
950                 dw_eh_ptr_t action_record_offset_base = action_record;
951                 int displacement = read_sleb128(&action_record);
952                 action_record = displacement ? 
953                         action_record_offset_base + displacement : 0;
954                 // We only check handler types for C++ exceptions - foreign exceptions
955                 // are only allowed for cleanup.
956                 if (filter > 0 && 0 != ex)
957                 {
958                         std::type_info *handler_type = get_type_info_entry(context, lsda, filter);
959                         if (check_type_signature(ex, handler_type, adjustedPtr))
960                         {
961                                 *selector = filter;
962                                 return handler_catch;
963                         }
964                 }
965                 else if (filter < 0 && 0 != ex)
966                 {
967                         bool matched = false;
968                         *selector = filter;
969 #ifdef __arm__
970                         filter++;
971                         std::type_info *handler_type = get_type_info_entry(context, lsda, filter--);
972                         while (handler_type)
973                         {
974                                 if (check_type_signature(ex, handler_type, adjustedPtr))
975                                 {
976                                         matched = true;
977                                         break;
978                                 }
979                                 handler_type = get_type_info_entry(context, lsda, filter--);
980                         }
981 #else
982                         unsigned char *type_index = ((unsigned char*)lsda->type_table - filter - 1);
983                         while (*type_index)
984                         {
985                                 std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++));
986                                 // If the exception spec matches a permitted throw type for
987                                 // this function, don't report a handler - we are allowed to
988                                 // propagate this exception out.
989                                 if (check_type_signature(ex, handler_type, adjustedPtr))
990                                 {
991                                         matched = true;
992                                         break;
993                                 }
994                         }
995 #endif
996                         if (matched) { continue; }
997                         // If we don't find an allowed exception spec, we need to install
998                         // the context for this action.  The landing pad will then call the
999                         // unexpected exception function.  Treat this as a catch
1000                         return handler_catch;
1001                 }
1002                 else if (filter == 0)
1003                 {
1004                         *selector = filter;
1005                         found = handler_cleanup;
1006                 }
1007         }
1008         return found;
1009 }
1010
1011 static void pushCleanupException(_Unwind_Exception *exceptionObject,
1012                                  __cxa_exception *ex)
1013 {
1014 #ifdef __arm__
1015         __cxa_thread_info *info = thread_info_fast();
1016         if (ex)
1017         {
1018                 ex->cleanupCount++;
1019                 if (ex->cleanupCount > 1)
1020                 {
1021                         assert(exceptionObject == info->currentCleanup);
1022                         return;
1023                 }
1024                 ex->nextCleanup = info->currentCleanup;
1025         }
1026         info->currentCleanup = exceptionObject;
1027 #endif
1028 }
1029
1030 /**
1031  * The exception personality function.  This is referenced in the unwinding
1032  * DWARF metadata and is called by the unwind library for each C++ stack frame
1033  * containing catch or cleanup code.
1034  */
1035 extern "C"
1036 BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)
1037         // This personality function is for version 1 of the ABI.  If you use it
1038         // with a future version of the ABI, it won't know what to do, so it
1039         // reports a fatal error and give up before it breaks anything.
1040         if (1 != version)
1041         {
1042                 return _URC_FATAL_PHASE1_ERROR;
1043         }
1044         __cxa_exception *ex = 0;
1045         __cxa_exception *realEx = 0;
1046
1047         // If this exception is throw by something else then we can't make any
1048         // assumptions about its layout beyond the fields declared in
1049         // _Unwind_Exception.
1050         bool foreignException = !isCXXException(exceptionClass);
1051
1052         // If this isn't a foreign exception, then we have a C++ exception structure
1053         if (!foreignException)
1054         {
1055                 ex = exceptionFromPointer(exceptionObject);
1056                 realEx = realExceptionFromException(ex);
1057         }
1058
1059         unsigned char *lsda_addr =
1060                 (unsigned char*)_Unwind_GetLanguageSpecificData(context);
1061
1062         // No LSDA implies no landing pads - try the next frame
1063         if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); }
1064
1065         // These two variables define how the exception will be handled.
1066         dwarf_eh_action action = {0};
1067         unsigned long selector = 0;
1068         
1069         // During the search phase, we do a complete lookup.  If we return
1070         // _URC_HANDLER_FOUND, then the phase 2 unwind will call this function with
1071         // a _UA_HANDLER_FRAME action, telling us to install the handler frame.  If
1072         // we return _URC_CONTINUE_UNWIND, we may be called again later with a
1073         // _UA_CLEANUP_PHASE action for this frame.
1074         //
1075         // The point of the two-stage unwind allows us to entirely avoid any stack
1076         // unwinding if there is no handler.  If there are just cleanups found,
1077         // then we can just panic call an abort function.
1078         //
1079         // Matching a handler is much more expensive than matching a cleanup,
1080         // because we don't need to bother doing type comparisons (or looking at
1081         // the type table at all) for a cleanup.  This means that there is no need
1082         // to cache the result of finding a cleanup, because it's (quite) quick to
1083         // look it up again from the action table.
1084         if (actions & _UA_SEARCH_PHASE)
1085         {
1086                 struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1087
1088                 if (!dwarf_eh_find_callsite(context, &lsda, &action))
1089                 {
1090                         // EH range not found. This happens if exception is thrown and not
1091                         // caught inside a cleanup (destructor).  We should call
1092                         // terminate() in this case.  The catchTemp (landing pad) field of
1093                         // exception object will contain null when personality function is
1094                         // called with _UA_HANDLER_FRAME action for phase 2 unwinding.  
1095                         return _URC_HANDLER_FOUND;
1096                 }
1097
1098                 handler_type found_handler = check_action_record(context, &lsda,
1099                                 action.action_record, realEx, &selector, ex->adjustedPtr);
1100                 // If there's no action record, we've only found a cleanup, so keep
1101                 // searching for something real
1102                 if (found_handler == handler_catch)
1103                 {
1104                         // Cache the results for the phase 2 unwind, if we found a handler
1105                         // and this is not a foreign exception.
1106                         if (ex)
1107                         {
1108                                 saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad);
1109                                 ex->languageSpecificData = (const char*)lsda_addr;
1110                                 ex->actionRecord = (const char*)action.action_record;
1111                                 // ex->adjustedPtr is set when finding the action record.
1112                         }
1113                         return _URC_HANDLER_FOUND;
1114                 }
1115                 return continueUnwinding(exceptionObject, context);
1116         }
1117
1118
1119         // If this is a foreign exception, we didn't have anywhere to cache the
1120         // lookup stuff, so we need to do it again.  If this is either a forced
1121         // unwind, a foreign exception, or a cleanup, then we just install the
1122         // context for a cleanup.
1123         if (!(actions & _UA_HANDLER_FRAME))
1124         {
1125                 // cleanup
1126                 struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1127                 dwarf_eh_find_callsite(context, &lsda, &action);
1128                 if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); }
1129                 handler_type found_handler = check_action_record(context, &lsda,
1130                                 action.action_record, realEx, &selector, ex->adjustedPtr);
1131                 // Ignore handlers this time.
1132                 if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); }
1133                 pushCleanupException(exceptionObject, ex);
1134         }
1135         else if (foreignException)
1136         {
1137                 struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1138                 dwarf_eh_find_callsite(context, &lsda, &action);
1139                 check_action_record(context, &lsda, action.action_record, realEx,
1140                                 &selector, ex->adjustedPtr);
1141         }
1142         else if (ex->catchTemp == 0)
1143         {
1144                 // Uncaught exception in cleanup, calling terminate
1145                 std::terminate();
1146         }
1147         else
1148         {
1149                 // Restore the saved info if we saved some last time.
1150                 loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad);
1151                 ex->catchTemp = 0;
1152                 ex->handlerSwitchValue = 0;
1153         }
1154
1155
1156         _Unwind_SetIP(context, (unsigned long)action.landing_pad);
1157         _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
1158                       (unsigned long)exceptionObject);
1159         _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector);
1160
1161         return _URC_INSTALL_CONTEXT;
1162 }
1163
1164 /**
1165  * ABI function called when entering a catch statement.  The argument is the
1166  * pointer passed out of the personality function.  This is always the start of
1167  * the _Unwind_Exception object.  The return value for this function is the
1168  * pointer to the caught exception, which is either the adjusted pointer (for
1169  * C++ exceptions) of the unadjusted pointer (for foreign exceptions).
1170  */
1171 #if __GNUC__ > 3 && __GNUC_MINOR__ > 2
1172 extern "C" void *__cxa_begin_catch(void *e) throw()
1173 #else
1174 extern "C" void *__cxa_begin_catch(void *e)
1175 #endif
1176 {
1177         // Decrement the uncaught exceptions count
1178         __cxa_eh_globals *globals = __cxa_get_globals();
1179         globals->uncaughtExceptions--;
1180         _Unwind_Exception *exceptionObject = (_Unwind_Exception*)e;
1181
1182         if (isCXXException(exceptionObject->exception_class))
1183         {
1184                 __cxa_exception *ex =  exceptionFromPointer(exceptionObject);
1185
1186                 if (ex->handlerCount == 0)
1187                 {
1188                         // Add this to the front of the list of exceptions being handled
1189                         // and increment its handler count so that it won't be deleted
1190                         // prematurely.
1191                         ex->nextException = globals->caughtExceptions;
1192                         globals->caughtExceptions = ex;
1193                 }
1194
1195                 if (ex->handlerCount < 0)
1196                 {
1197                         // Rethrown exception is catched before end of catch block.
1198                         // Clear the rethrow flag (make value positive) - we are allowed
1199                         // to delete this exception at the end of the catch block, as long
1200                         // as it isn't thrown again later.
1201                         
1202                         // Code pattern:
1203                         //
1204                         // try {
1205                         //     throw x;
1206                         // }
1207                         // catch() {
1208                         //     try {
1209                         //         throw;
1210                         //     }
1211                         //     catch() {
1212                         //         __cxa_begin_catch() <- we are here
1213                         //     }
1214                         // }
1215                         ex->handlerCount = -ex->handlerCount + 1;
1216                 }
1217                 else
1218                 {
1219                         ex->handlerCount++;
1220                 }
1221                 
1222                 return ex->adjustedPtr;
1223         }
1224         // exceptionObject is the pointer to the _Unwind_Exception within the
1225         // __cxa_exception.  The throw object is after this
1226         return ((char*)exceptionObject + sizeof(_Unwind_Exception));
1227 }
1228
1229
1230
1231 /**
1232  * ABI function called when exiting a catch block.  This will free the current
1233  * exception if it is no longer referenced in other catch blocks.
1234  */
1235 extern "C" void __cxa_end_catch()
1236 {
1237         // We can call the fast version here because the slow version is called in
1238         // __cxa_throw(), which must have been called before we end a catch block
1239         __cxa_eh_globals *globals = __cxa_get_globals_fast();
1240         __cxa_exception *ex = globals->caughtExceptions;
1241
1242         assert(0 != ex && "Ending catch when no exception is on the stack!");
1243
1244         bool deleteException = true;
1245
1246         if (ex->handlerCount < 0)
1247         {
1248                 // exception was rethrown. Exception should not be deleted even if
1249                 // handlerCount become zero.
1250                 // Code pattern:
1251                 // try {
1252                 //     throw x;
1253                 // }
1254                 // catch() {
1255                 //     {
1256                 //         throw;
1257                 //     }
1258                 //     cleanup {
1259                 //         __cxa_end_catch();   <- we are here
1260                 //     }
1261                 // }
1262                 //
1263                 
1264                 ex->handlerCount++;
1265                 deleteException = false;
1266         }
1267         else
1268         {
1269                 ex->handlerCount--;
1270         }
1271
1272         if (ex->handlerCount == 0)
1273         {
1274                 globals->caughtExceptions = ex->nextException;
1275                 if (deleteException)
1276                 {
1277                         releaseException(ex);
1278                 }
1279         }
1280 }
1281
1282 /**
1283  * ABI function.  Returns the type of the current exception.
1284  */
1285 extern "C" std::type_info *__cxa_current_exception_type()
1286 {
1287         __cxa_eh_globals *globals = __cxa_get_globals();
1288         __cxa_exception *ex = globals->caughtExceptions;
1289         return ex ? ex->exceptionType : 0;
1290 }
1291
1292 /**
1293  * ABI function, called when an exception specification is violated.
1294  *
1295  * This function does not return.
1296  */
1297 extern "C" void __cxa_call_unexpected(void*exception) 
1298 {
1299         _Unwind_Exception *exceptionObject = (_Unwind_Exception*)exception;
1300         if (exceptionObject->exception_class == exception_class)
1301         {
1302                 __cxa_exception *ex =  exceptionFromPointer(exceptionObject);
1303                 if (ex->unexpectedHandler)
1304                 {
1305                         ex->unexpectedHandler();
1306                         // Should not be reached.  
1307                         abort();
1308                 }
1309         }
1310         std::unexpected();
1311         // Should not be reached.  
1312         abort();
1313 }
1314
1315 /**
1316  * ABI function, returns the adjusted pointer to the exception object.
1317  */
1318 extern "C" void *__cxa_get_exception_ptr(void *exceptionObject)
1319 {
1320         return exceptionFromPointer(exceptionObject)->adjustedPtr;
1321 }
1322
1323 /**
1324  * As an extension, we provide the ability for the unexpected and terminate
1325  * handlers to be thread-local.  We default to the standards-compliant
1326  * behaviour where they are global.
1327  */
1328 static bool thread_local_handlers = false;
1329
1330
1331 namespace pathscale
1332 {
1333         /**
1334          * Sets whether unexpected and terminate handlers should be thread-local.
1335          */
1336         void set_use_thread_local_handlers(bool flag) throw()
1337         {
1338                 thread_local_handlers = flag;
1339         }
1340         /**
1341          * Sets a thread-local unexpected handler.  
1342          */
1343         unexpected_handler set_unexpected(unexpected_handler f) throw()
1344         {
1345                 static __cxa_thread_info *info = thread_info();
1346                 unexpected_handler old = info->unexpectedHandler;
1347                 info->unexpectedHandler = f;
1348                 return old;
1349         }
1350         /**
1351          * Sets a thread-local terminate handler.  
1352          */
1353         terminate_handler set_terminate(terminate_handler f) throw()
1354         {
1355                 static __cxa_thread_info *info = thread_info();
1356                 terminate_handler old = info->terminateHandler;
1357                 info->terminateHandler = f;
1358                 return old;
1359         }
1360 }
1361
1362 namespace std
1363 {
1364         /**
1365          * Sets the function that will be called when an exception specification is
1366          * violated.
1367          */
1368         unexpected_handler set_unexpected(unexpected_handler f) throw()
1369         {
1370                 if (thread_local_handlers) { return pathscale::set_unexpected(f); }
1371
1372                 return __sync_lock_test_and_set(&unexpectedHandler, f);
1373         }
1374         /**
1375          * Sets the function that is called to terminate the program.
1376          */
1377         terminate_handler set_terminate(terminate_handler f) throw()
1378         {
1379                 if (thread_local_handlers) { return pathscale::set_terminate(f); }
1380                 return __sync_lock_test_and_set(&terminateHandler, f);
1381         }
1382         /**
1383          * Terminates the program, calling a custom terminate implementation if
1384          * required.
1385          */
1386         void terminate()
1387         {
1388                 static __cxa_thread_info *info = thread_info_fast();
1389                 if (0 != info && 0 != info->terminateHandler)
1390                 {
1391                         info->terminateHandler();
1392                         // Should not be reached - a terminate handler is not expected to
1393                         // return.
1394                         abort();
1395                 }
1396                 terminateHandler();
1397         }
1398         /**
1399          * Called when an unexpected exception is encountered (i.e. an exception
1400          * violates an exception specification).  This calls abort() unless a
1401          * custom handler has been set..
1402          */
1403         void unexpected()
1404         {
1405                 static __cxa_thread_info *info = thread_info_fast();
1406                 if (0 != info && 0 != info->unexpectedHandler)
1407                 {
1408                         info->unexpectedHandler();
1409                         // Should not be reached - a terminate handler is not expected to
1410                         // return.
1411                         abort();
1412                 }
1413                 unexpectedHandler();
1414         }
1415         /**
1416          * Returns whether there are any exceptions currently being thrown that
1417          * have not been caught.  This can occur inside a nested catch statement.
1418          */
1419         bool uncaught_exception() throw()
1420         {
1421                 __cxa_thread_info *info = thread_info();
1422                 return info->globals.uncaughtExceptions != 0;
1423         }
1424         /**
1425          * Returns the current unexpected handler.
1426          */
1427         unexpected_handler get_unexpected() throw()
1428         {
1429                 __cxa_thread_info *info = thread_info();
1430                 if (info->unexpectedHandler)
1431                 {
1432                         return info->unexpectedHandler;
1433                 }
1434                 return unexpectedHandler;
1435         }
1436         /**
1437          * Returns the current terminate handler.
1438          */
1439         terminate_handler get_terminate() throw()
1440         {
1441                 __cxa_thread_info *info = thread_info();
1442                 if (info->terminateHandler)
1443                 {
1444                         return info->terminateHandler;
1445                 }
1446                 return terminateHandler;
1447         }
1448 }
1449 #ifdef __arm__
1450 extern "C" _Unwind_Exception *__cxa_get_cleanup(void)
1451 {
1452         __cxa_thread_info *info = thread_info_fast();
1453         _Unwind_Exception *exceptionObject = info->currentCleanup;
1454         if (isCXXException(exceptionObject->exception_class))
1455         {
1456                 __cxa_exception *ex =  exceptionFromPointer(exceptionObject);
1457                 ex->cleanupCount--;
1458                 if (ex->cleanupCount == 0)
1459                 {
1460                         info->currentCleanup = ex->nextCleanup;
1461                         ex->nextCleanup = 0;
1462                 }
1463         }
1464         else
1465         {
1466                 info->currentCleanup = 0;
1467         }
1468         return exceptionObject;
1469 }
1470
1471 asm (
1472 ".pushsection .text.__cxa_end_cleanup    \n"
1473 ".global __cxa_end_cleanup               \n"
1474 ".type __cxa_end_cleanup, \"function\"   \n"
1475 "__cxa_end_cleanup:                      \n"
1476 "       push {r1, r2, r3, r4}                \n"
1477 "       bl __cxa_get_cleanup                 \n"
1478 "       push {r1, r2, r3, r4}                \n"
1479 "       b _Unwind_Resume                     \n"
1480 "       bl abort                             \n"
1481 ".popsection                             \n"
1482 );
1483 #endif