Update contrib.
1 /* The C++ exceptions runtime support
3 * Copyright 2002-2005 ARM Limited. All rights reserved.
5 * Your rights to use this code are set out in the accompanying licence
6 * text file LICENCE.txt (ARM contract number LEC-ELA-00080 v1.0).
9 /* Portions copyright Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). */
12 * RCS $Revision: 92950 $
13 * Checkin $Date: 2005-10-12 11:08:47 +0100 (Wed, 12 Oct 2005) $
14 * Revising $Author: achapman $
17 /* This source file is compiled automatically by ARM's make system into
18 * multiple object files. The source regions constituting object file
19 * xxx.o are delimited by ifdef xxx_c / endif directives.
21 * The source regions currently marked are:
22 * arm_exceptions_globs_c
23 * arm_exceptions_mem_c
24 * arm_exceptions_uncaught_c
25 * arm_exceptions_terminate_c
26 * arm_exceptions_setterminate_c
27 * arm_exceptions_unexpected_c
28 * arm_exceptions_setunexpected_c
29 * arm_exceptions_support_c
30 * arm_exceptions_callterm_c
31 * arm_exceptions_callunex_c
32 * arm_exceptions_currenttype_c
33 * arm_exceptions_alloc_c
34 * arm_exceptions_free_c
35 * arm_exceptions_throw_c
36 * arm_exceptions_rethrow_c
37 * arm_exceptions_foreign_c
38 * arm_exceptions_cleanup_c
39 * arm_exceptions_getexceptionptr_c
40 * arm_exceptions_begincatch_c
41 * arm_exceptions_endcatch_c
42 * arm_exceptions_bad_typeid_c
43 * arm_exceptions_bad_cast_c
49 #include "unwind_env.h"
50 // Language-independent unwinder declarations:
54 /* Symbian specific support */
55 #include "symbian_support.h"
61 /* Requirement imposed by C++ semantics module - pointer to match object in slot 0: */
62 #define BARRIER_HANDLEROBJECT (0)
63 /* Requirement imposed by C++ semantics module - function exception spec info */
64 #define BARRIER_FNSPECCOUNT (1)
65 #define BARRIER_FNSPECBASE (2)
66 #define BARRIER_FNSPECSTRIDE (3)
67 #define BARRIER_FNSPECARRAY (4)
69 /* By default, none of these routines are unwindable: */
70 #pragma noexceptions_unwind
74 typedef _Unwind_Control_Block UCB;
76 using std::terminate_handler;
77 using std::unexpected_handler;
79 using std::unexpected;
82 /* Redeclare these interface routines as weak, so using them does not
83 * pull in the unwind library. We only want the unwind library if
84 * someone throws (or raises an exception from some other language).
86 WEAKDECL NORETURNDECL void _Unwind_Resume(UCB *);
87 WEAKDECL void _Unwind_Complete(UCB *);
90 * Define DEBUG to get extra interfaces which assist debugging this functionality.
91 * Define CPP_DIAGNOSTICS for printed diagnostics.
94 #define CPP_DIAGNOSTICS
97 #ifdef CPP_DIAGNOSTICS
99 extern "C" int printf(const char *, ...);
103 /* --------- "Exceptions_class" string for our implementation: --------- */
105 #define EXCEPTIONS_CLASS_SIZE 8
106 #define ARMCPP_EXCEPTIONS_CLASS "ARM\0C++\0"
109 /* --------- Exception control object: --------- */
111 // Type __cxa_exception is the combined C++ housekeeping (LEO) and UCB.
112 // It will be followed by the user exception object, hence must ensure
113 // the latter is aligned on an 8 byte boundary.
116 struct __cxa_exception {
117 const type_info *exceptionType; // RTTI object describing the type of the exception
118 void *(*exceptionDestructor)(void *); // Destructor for the exception object (may be NULL)
119 unexpected_handler unexpectedHandler; // Handler in force after evaluating throw expr
120 terminate_handler terminateHandler; // Handler in force after evaluating throw expr
121 __cxa_exception *nextCaughtException; // Chain of "currently caught" c++ exception objects
122 uint32_t handlerCount; // Count of how many handlers this EO is "caught" in
123 __cxa_exception *nextPropagatingException; // Chain of objects saved over cleanup
124 uint32_t propagationCount; // Count of live propagations (throws) of this EO
125 UCB ucb; // Forces alignment of next item to 8-byte boundary
130 /* --------- Control "globals": --------- */
132 // We do this by putting all the thread-specific "globals" into a single
133 // area of store, which we allocate space for dynamically.
134 // We don't define a constructor for this; see comments with __cxa_get_globals.
137 typedef void (*handler)(void);
139 struct __cxa_eh_globals {
140 uint32_t uncaughtExceptions; // counter
141 unexpected_handler unexpectedHandler; // per-thread handler
142 terminate_handler terminateHandler; // per-thread handler
143 bool implementation_ever_called_terminate; // true if it ever did
144 handler call_hook; // transient field to tell terminate/unexpected which hook to call
145 __cxa_exception *caughtExceptions; // chain of "caught" exceptions
146 __cxa_exception *propagatingExceptions; // chain of "propagating" (in cleanup) exceptions
147 void *emergency_buffer; // emergency buffer for when rest of heap full
152 /* ---------- Entry points: ---------- */
154 /* There is a little type-delicacy required here as __cxa_throw takes a
155 * function pointer. Setting aside the problem of not being able to form
156 * a pointer to a destructor in C++, if we simply say extern "C" here
157 * then the function pointer will also have C linkage and will be a
158 * pointer to a C function. This causes problems when __cxa_throw is
159 * defined (unless we repeat the extern "C" at the definition site) because
160 * the fnptr in the definition gets C++ linkage, hence that __cxa_throw has
161 * a different signature to the declared one, and so the function we wanted
162 * doesn't get defined at all.
163 * Maybe it should just take a void * but this seems more honest.
166 typedef void *(*cppdtorptr)(void *);
170 // Protocol routines called directly from application code
172 IMPORT_C void *__cxa_allocate_exception(size_t size);
173 IMPORT_C void __cxa_free_exception(void *);
174 WEAKDECL void __cxa_throw(void *, const type_info *, cppdtorptr);
175 IMPORT_C void __cxa_rethrow(void);
176 IMPORT_C void *__cxa_get_exception_ptr(UCB *);
177 void *__cxa_begin_catch(UCB *);
178 IMPORT_C void __cxa_end_catch(void);
179 IMPORT_C void __cxa_end_cleanup(void);
180 IMPORT_C const type_info *__cxa_current_exception_type(void);
182 // Protocol routines usually called only by the personality routine(s).
184 IMPORT_C void __cxa_call_terminate(UCB *);
185 IMPORT_C void __cxa_call_unexpected(UCB *);
186 IMPORT_C bool __cxa_begin_cleanup(UCB *);
190 ctm_succeeded_with_ptr_to_base = 2
191 } __cxa_type_match_result;
192 IMPORT_C __cxa_type_match_result __cxa_type_match(UCB *, const std::type_info *,
193 bool is_reference_type, void **);
195 // Auxilliary routines
197 __cxa_eh_globals *__cxa_get_globals(void);
198 IMPORT_C void __cxa_bad_typeid(void);
199 IMPORT_C void __cxa_bad_cast(void);
201 // Emergency memory buffer management routines
203 void *__ARM_exceptions_buffer_init(void);
204 void *__ARM_exceptions_buffer_allocate(void *, size_t);
205 void *__ARM_exceptions_buffer_free(void *, void *);
213 void default_unexpected_handler(void);
214 void call_terminate_handler(UCB *);
215 void eh_catch_semantics(UCB *);
216 bool is_foreign_exception(UCB *);
217 bool same_exceptions_class(const void *, const void *);
218 __cxa_exception *get_foreign_intermediary(__cxa_exception *, UCB *);
221 // Macro: convert ucb pointer to __cxa_exception pointer
223 #define ucbp_to_ep(UCB_P) ((__cxa_exception *)((char *)(UCB_P) - offsetof(__cxa_exception, ucb)))
226 #ifdef arm_exceptions_globs_c
228 /* --------- Allocating and retrieving "globals": --------- */
230 // The exception-handling globals should be allocated per-thread.
231 // This is done here assuming the existance of a zero-initialised void*
232 // pointer location obtainable by the macro EH_GLOBALS.
234 // Default terminate handler:
237 static void __default_terminate_handler(void) {
242 // If std::unexpected() is in the image, include a default handler for it:
243 namespace NAMES { WEAKDECL void default_unexpected_handler(void); }
245 // ARM's toolchain documentation states that if symbol
246 // __ARM_exceptions_buffer_required is present we should allocate
247 // an emergency buffer.
248 // As we aren't allowed static data in ARM library builds, reference the
249 // symbol by declaring it a function. This causes an additional problem when
250 // ARM libraries are built position-independent, namely that an absent
251 // function doesn't compare address-equal to NULL. So we have to get the
252 // "addresses" from two different compilation units and compare those.
253 // This is a known defect, to be fixed in the compiler.
254 extern "C" WEAKDECL void __ARM_exceptions_buffer_required(void);
255 extern void (*(__ARM_exceptions_buffer_required_address(void)))(void);
257 // The address comparison function only needs to be used when we are building
258 // position-independent. In other cases, comparing the address to NULL is more
261 # define ARM_EXCEPTIONS_BUFFER_NOT_REQUIRED() (&__ARM_exceptions_buffer_required != __ARM_exceptions_buffer_required_address())
263 # define ARM_EXCEPTIONS_BUFFER_NOT_REQUIRED() (&__ARM_exceptions_buffer_required == NULL)
266 // __cxa_eh_globals returns the per-thread memory. There are several complications,
267 // all of which relate to not touching the exceptions system while trying to
269 // 1) We can't obtain memory by calling new or nothrow new as both of these use
270 // exceptions internally, so we must use malloc
271 // 2) We choose not to initialise the memory via placement new and a constructor,
272 // since placement new is declared with an empty function exception specification,
273 // which causes more of the exceptions system to always be pulled in.
274 // 3) We can't call terminate, as terminate looks in the memory we are trying to
277 EXPORT_C __cxa_eh_globals *__cxa_get_globals(void)
279 __cxa_eh_globals *this_thread_globals = (__cxa_eh_globals *)(EH_GLOBALS);
282 /* The Symbian implementation allocates the required space on the threads stack
283 at thread creation and sets up thread local storage to point to the globals
284 which are also initialised
286 if (this_thread_globals == NULL) {
289 // Obtain some memory: this is thread-safe provided malloc is.
290 this_thread_globals = (__cxa_eh_globals *)malloc(sizeof(__cxa_eh_globals));
291 if (this_thread_globals == NULL) abort(); // NOT terminate(), which calls this fn
293 // Save the pointer in the specially-provided location
294 EH_GLOBALS = this_thread_globals;
296 // Finally initialise the memory by hand
297 this_thread_globals->uncaughtExceptions = 0;
298 this_thread_globals->unexpectedHandler = NAMES::default_unexpected_handler;
299 this_thread_globals->terminateHandler = __default_terminate_handler;
300 this_thread_globals->implementation_ever_called_terminate = false;
301 this_thread_globals->call_hook = NULL;
302 this_thread_globals->caughtExceptions = NULL;
303 this_thread_globals->propagatingExceptions = NULL;
304 if (ARM_EXCEPTIONS_BUFFER_NOT_REQUIRED())
305 this_thread_globals->emergency_buffer = NULL;
307 this_thread_globals->emergency_buffer = __ARM_exceptions_buffer_init();
310 return this_thread_globals;
314 #endif /* arm_exceptions_globs_c */
315 #ifdef arm_exceptions_mem_c
317 /* --------- Emergency memory: --------- */
319 // It is possible to reserve memory for throwing bad_alloc when the heap
320 // is otherwise full. The ARM implementation provides hooks to do this.
321 // The default implementation reserves just enough space for a bad_alloc
322 // object, so if memory is later exhausted bad_alloc can still be thrown.
323 // Note there is no guarantee or requirement that the exception being
324 // thrown is actually bad_alloc.
326 // A usage flag and enough space for a bad_alloc exception control object
328 struct emergency_eco {
333 struct emergency_buffer {
335 struct emergency_eco eco;
341 // The SymbianOS implementation allocates this space at thread creation
344 void* __ARM_exceptions_buffer_init(void)
346 emergency_buffer *buffer = (emergency_buffer *)malloc(sizeof(emergency_buffer));
347 if (buffer == NULL) return NULL;
348 buffer->inuse = false;
354 void *__ARM_exceptions_buffer_allocate(void *buffer, size_t size)
356 emergency_buffer *b = (emergency_buffer *)buffer;
357 if (size > sizeof(emergency_eco) || b == NULL || b->inuse) return NULL;
362 // Deallocator: Must return non-NULL if and only if it recognises
363 // and releases the supplied object
364 void *__ARM_exceptions_buffer_free(void *buffer, void *addr)
366 emergency_buffer *b = (emergency_buffer *)buffer;
367 if (b == NULL || addr != &b->eco) return NULL;
373 // Hook activation support - see comments earlier
374 extern "C" WEAKDECL void __ARM_exceptions_buffer_required(void);
375 void (*(__ARM_exceptions_buffer_required_address(void)))(void)
377 return &__ARM_exceptions_buffer_required;
382 #endif /* arm_exceptions_mem_c */
383 #ifdef arm_exceptions_uncaught_c
385 /* ---- uncaught_exception() ---- */
387 /* The EDG (and I think our) interpretation is that if the implementation
388 * ever called terminate(), uncaught_exception() should return true.
390 #if __ARMCC_VERSION < 220000
391 bool std::uncaught_exception(void)
393 EXPORT_C bool std::uncaught_exception(void)
396 __cxa_eh_globals *g = __cxa_get_globals();
397 return g->implementation_ever_called_terminate || g->uncaughtExceptions;
401 #endif /* arm_exceptions_uncaught_c */
402 #ifdef arm_exceptions_terminate_c
404 /* ---- terminate() etc ---- */
406 /* The behaviour of terminate() must differ between calls by the
407 * implementation and calls by the application. This is achieved by having the
408 * implementation set call_hook immediately before the call to terminate().
409 * The hook called by terminate() should terminate the program without
410 * returning to the caller. There is no requirement for terminate() itself to
414 EXPORT_C void std::terminate(void)
416 __cxa_eh_globals *g = __cxa_get_globals();
418 if (g->call_hook != NULL) {
419 // Clear then call hook fn we were passed
420 handler call_hook = g->call_hook;
424 // Call global hook fn
425 g->terminateHandler();
427 // If hook fn returns:
432 #endif /* arm_exceptions_terminate_c */
433 #ifdef arm_exceptions_setterminate_c
435 EXPORT_C terminate_handler std::set_terminate(terminate_handler h) throw()
437 __cxa_eh_globals *g = __cxa_get_globals();
438 terminate_handler old = g->terminateHandler;
439 g->terminateHandler = h;
444 #endif /* arm_exceptions_setterminate_c */
445 #ifdef arm_exceptions_unexpected_c
447 /* ---- unexpected() etc ---- */
448 /* Comments as per terminate() */
450 void NAMES::default_unexpected_handler(void) {
454 #pragma exceptions_unwind
456 EXPORT_C void std::unexpected(void)
458 __cxa_eh_globals *g = __cxa_get_globals();
460 if (g->call_hook != NULL) {
461 // Clear then call hook fn we were passed
462 handler call_hook = g->call_hook;
466 // Call global hook fn
467 g->unexpectedHandler();
470 // If hook fn returns:
475 #endif /* arm_exceptions_unexpected_c */
476 #ifdef arm_exceptions_setunexpected_c
478 EXPORT_C unexpected_handler std::set_unexpected(unexpected_handler h) throw()
480 __cxa_eh_globals *g = __cxa_get_globals();
481 unexpected_handler old = g->unexpectedHandler;
482 g->unexpectedHandler = h;
487 #endif /* arm_exceptions_setunexpected_c */
488 #ifdef arm_exceptions_support_c
490 /* ---------- Helper functions: ---------- */
492 /* Two routines to determine whether two exceptions objects share a layout.
493 * This is determined by checking whether the UCB exception_class members
495 * In principle we could use memcmp to perform this check (the code is
496 * given below) but the check is quite frequent and so that is costly.
497 * Therefore for efficiency we make use of the fact that the UCB is
498 * word aligned, that the exception_class member is consequently
499 * word aligned within it, and that we know the size of the member.
500 * We take care elsewhere to only ever call the routines with pointers
501 * to word-aligned addresses.
506 // Straightforward versions
508 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
510 return memcmp(ec1, ec2, EXCEPTIONS_CLASS_SIZE) == 0; // identical
513 // One of our exception objects, or not?
515 bool NAMES::is_foreign_exception(UCB *ucbp)
517 return !NAMES::same_exceptions_class(&ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS);
524 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
526 uint32_t *ip1 = (uint32_t *)ec1;
527 uint32_t *ip2 = (uint32_t *)ec2;
528 return ip1[0] == ip2[0] && ip1[1] == ip2[1];
531 // One of our exception objects, or not?
533 bool NAMES::is_foreign_exception(UCB *ucbp)
535 // Need a word-aligned copy of the string
537 const char s[EXCEPTIONS_CLASS_SIZE+1]; int dummy;
538 } is_foreign_exception_static = {ARMCPP_EXCEPTIONS_CLASS};
539 return !NAMES::same_exceptions_class(&ucbp->exception_class, &is_foreign_exception_static.s);
545 #endif /* arm_exceptions_support_c */
546 #ifdef arm_exceptions_callterm_c
548 /* When the implementation wants to call terminate(), do the following:
549 * Mark the object as "caught" so it can be rethrown.
550 * Set the hook function for terminate() to call;
551 * Mark the fact that terminate() has been called by the implementation;
552 * We have to be careful - the implementation might encounter an error while
553 * unwinding a foreign exception, and also it is possible this might be
554 * called after failing to obtain a ucb.
557 void NAMES::call_terminate_handler(UCB *ucbp)
559 __cxa_eh_globals *g = __cxa_get_globals();
563 g->call_hook = g->terminateHandler;
565 // Extract the hook to call
566 if (NAMES::is_foreign_exception(ucbp)) {
568 g->call_hook = g->terminateHandler; // best we can do under the circumstances
571 __cxa_exception *ep = ucbp_to_ep(ucbp);
572 g->call_hook = ep->terminateHandler; // the one in force at the point of throw
576 g->implementation_ever_called_terminate = true;
582 EXPORT_C void __cxa_call_terminate(UCB *ucbp)
584 if (ucbp != NULL) // Record entry to (implicit) handler
585 __cxa_begin_catch(ucbp);
587 NAMES::call_terminate_handler(ucbp);
592 #endif /* arm_exceptions_callterm_c */
593 #ifdef arm_exceptions_callunex_c
595 /* When the implementation wants to call unexpected(), do the following:
596 * Mark the object as "caught" so it can be rethrown.
597 * Set the hook function for unexpected() to call;
598 * Call unexpected and trap any throw to make sure it is acceptable.
599 * We have to be careful - the implementation might encounter an error while
600 * unwinding a foreign exception.
603 #pragma exceptions_unwind
605 EXPORT_C void __cxa_call_unexpected(UCB *ucbp)
608 // Extract data we will need from the barrier cache before
609 // anyone has a chance to overwrite it
611 uint32_t rtti_count = ucbp->barrier_cache.bitpattern[BARRIER_FNSPECCOUNT];
612 uint32_t base = ucbp->barrier_cache.bitpattern[BARRIER_FNSPECBASE];
613 uint32_t stride = ucbp->barrier_cache.bitpattern[BARRIER_FNSPECSTRIDE];
614 uint32_t rtti_offset_array_addr = ucbp->barrier_cache.bitpattern[BARRIER_FNSPECARRAY];
616 // Also get the globals here and the eop
618 __cxa_eh_globals *g = __cxa_get_globals();
619 __cxa_exception *ep = ucbp_to_ep(ucbp);
621 #ifdef ARM_EXCEPTIONS_ENABLED
625 // Record entry to (implicit) handler
627 __cxa_begin_catch(ucbp);
629 // Now extract the hook to call
631 if (NAMES::is_foreign_exception(ucbp)) {
633 g->call_hook = g->unexpectedHandler; // best we can do under the circumstances
636 g->call_hook = ep->unexpectedHandler; // the one in force at the point of throw
638 unexpected(); // never returns normally, but might throw something
640 #ifdef ARM_EXCEPTIONS_ENABLED
643 // Unexpected() threw. This requires some delicacy.
644 // There are 2 possibilities:
645 // i) rethrow of the same object
646 // ii) throw of a new object
647 // Unexpected() is an implicit handler, and we manually called
648 // __cxa_begin_catch on the ingoing object. We need to call
649 // __cxa_end_catch on that object and, if the object is no longer
650 // being handled (possible in case ii), this will cause its destruction.
651 // The wrinkle is that in case ii the object is not on top of the catch
652 // stack because we just caught something else.
654 // Get hold of what was thrown (which we just caught).
656 __cxa_exception *epnew = g->caughtExceptions;
658 // Call __cxa_end_catch on the original object, taking care with the catch chain
661 // rethrow - easy & safe - object is at top of chain and handlercount > 1
664 // not rethrow - unchain the top (new) object, clean up the next one,
665 // and put the top object back
668 g->caughtExceptions = epnew->nextCaughtException;
669 // assert g->caughtExceptions == ep now
670 // Decrement its handlercount (this might call a dtor if the count goes to 0,
671 // and the dtor might throw - if it does, just give up)
678 epnew->nextCaughtException = g->caughtExceptions;
679 g->caughtExceptions = epnew;
682 // See whether what was thrown is permitted, and in passing
683 // see if std::bad_exception is permitted
685 bool bad_exception_permitted = false;
687 for (i = 0; i < rtti_count; i++) {
688 void *matched_object;
691 fnspec = (type_info *)__ARM_resolve_target2((void *)rtti_offset_array_addr);
693 fnspec = (type_info *)(*(uint32_t *)rtti_offset_array_addr + base);
694 if (__cxa_type_match(&(epnew->ucb), fnspec, false, &matched_object)) {
695 #ifdef CPP_DIAGNOSTICS
696 printf("__cxa_call_unexpected: fnspec matched\n");
698 throw; // got a match - propagate it
700 if (typeid(std::bad_exception) == *fnspec)
701 bad_exception_permitted = true;
702 rtti_offset_array_addr += stride;
705 // There was no match...
706 if (bad_exception_permitted) throw std::bad_exception(); // transmute
708 // Otherwise call epnew's terminate handler
709 NAMES::call_terminate_handler(&epnew->ucb);
715 #endif /* arm_exceptions_callunex_c */
716 #ifdef arm_exceptions_currenttype_c
718 /* Yield the type of the currently handled exception, or null if none or the
722 EXPORT_C const type_info *__cxa_current_exception_type(void)
724 __cxa_eh_globals *g = __cxa_get_globals();
725 __cxa_exception *ep = g->caughtExceptions;
726 if (ep == NULL || NAMES::is_foreign_exception(&ep->ucb)) return NULL;
727 return ep->exceptionType;
731 #endif /* arm_exceptions_currenttype_c */
732 #ifdef arm_exceptions_alloc_c
734 /* Allocate store for controlling an exception propagation */
736 EXPORT_C void *__cxa_allocate_exception(size_t size)
738 __cxa_eh_globals *g = __cxa_get_globals();
740 // Allocate store for a __cxa_exception header and the EO.
741 // Allocated store should be thread-safe and persistent, and must do
742 // something sensible if the allocation fails
744 size_t total_size = size + sizeof(__cxa_exception);
745 // coverity[alloc_fn]
746 __cxa_exception *ep = (__cxa_exception *)malloc(total_size);
748 // Try the emergency memory pool
749 SYMBIAN_EH_SUPPORT_PRINTF("Trying emergency buffer: size %d\n", total_size);
750 ep = (__cxa_exception *)__ARM_exceptions_buffer_allocate(g->emergency_buffer, total_size);
753 SYMBIAN_EH_SUPPORT_PRINTF("Emergency buffer allocation failed. Terminating\n");
754 NAMES::call_terminate_handler(NULL);
758 UCB *ucbp = &ep->ucb;
760 // Initialise the UCB
762 memcpy(ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS, EXCEPTIONS_CLASS_SIZE);
763 ucbp->exception_cleanup = NULL; /* initialise properly before throwing */
764 ucbp->unwinder_cache.reserved1 = 0; /* required to do this */
766 // Initialise parts of the LEO, in case copy-construction of the EO results
767 // in a need to call terminate (via __cxa_call_terminate)
769 ep->handlerCount = 0; // Not in any handlers
770 ep->nextCaughtException = NULL; // Not in any handlers
771 ep->nextPropagatingException = NULL; // Not saved over cleanup
772 ep->propagationCount = 0; // Not propagating
773 ep->terminateHandler = g->terminateHandler; // Cache current terminate handler
774 ep->unexpectedHandler = g->unexpectedHandler; // Cache current unexpected handler
776 // Return pointer to the EO
777 // coverity[memory_leak]
782 #endif /* arm_exceptions_alloc_c */
783 #ifdef arm_exceptions_free_c
785 /* Free store allocated by __cxa_allocate_exception */
787 EXPORT_C void __cxa_free_exception(void *eop)
789 __cxa_eh_globals *g = __cxa_get_globals();
790 char *ep = (char *)eop - sizeof(__cxa_exception);
791 if (__ARM_exceptions_buffer_free(g->emergency_buffer, ep)) return;
796 #endif /* arm_exceptions_free_c */
797 #ifdef arm_exceptions_throw_c
799 /* This routine is called when a foreign runtime catches one of our exception
800 * objects and then exits its catch by a means other than rethrow.
801 * We should clean it up as if we had caught it ourselves.
804 static void external_exception_termination(_Unwind_Reason_Code c, UCB *ucbp)
806 NAMES::eh_catch_semantics(ucbp);
811 /* Initiate a throw */
814 #pragma exceptions_unwind
816 EXPORT_C void __cxa_throw(void *eop, const type_info *t, cppdtorptr d)
818 __cxa_exception *ep = (__cxa_exception *)((char *)eop - sizeof(__cxa_exception));
819 UCB *ucbp = &ep->ucb;
821 // Initialise the remaining LEO and UCB fields not done by __cxa_allocate_exception
823 ucbp->exception_cleanup = external_exception_termination;
824 ep->exceptionType = t;
825 ep->exceptionDestructor = d;
826 ep->propagationCount = 1; // Propagating by 1 throw
828 // Increment the uncaught C++ exceptions count
830 __cxa_eh_globals *g = __cxa_get_globals();
831 g->uncaughtExceptions++;
833 // Tell debugger what's happening
835 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, t);
837 // Initiate unwinding - if we get control back, call C++ routine terminate()
839 _Unwind_RaiseException(ucbp);
841 #ifdef CPP_DIAGNOSTICS
842 printf("__cxa_throw: throw failed\n");
845 __cxa_call_terminate(ucbp);
850 /* ----- Type matching: ----- */
852 /* This is located here so that (in ARM's implementation) it is only retained in
853 * an image if the application itself throws.
856 /* Type matching functions.
857 * C++ DR126 says the matching rules for fnspecs are intended to be the same as
859 * "A function is said to allow an exception of type E if its exception-specification
860 * contains a type T for which a handler of type T would be a match (15.3 except.handle)
861 * for an exception of type E."
862 * Thus we have a single type matching rule.
867 #define CV_quals_of_pointee(P) (((const abi::__pbase_type_info *)(P))->__flags & \
868 (abi::__pbase_type_info::__const_mask | \
869 abi::__pbase_type_info::__volatile_mask))
871 #define is_const(QUALS) (((QUALS) & abi::__pbase_type_info::__const_mask) != 0)
873 #define any_qualifier_missing(TEST_QUALS, REF_QUALS) ((~(TEST_QUALS) & (REF_QUALS)) != 0)
875 /* A routine is required for derived class to base class conversion.
876 * This is obtained via a macro definition DERIVED_TO_BASE_CONVERSION
880 /* External entry point:
881 * Type check the c++ rtti object for compatibility against the type of
882 * the object containing the ucb. Return a pointer to the matched object
883 * (possibly a non-leftmost baseclass of the exception object)
885 EXPORT_C __cxa_type_match_result __cxa_type_match(UCB *ucbp, const type_info *match_type,
886 bool is_reference_type, void **matched_objectpp)
888 if (NAMES::is_foreign_exception(ucbp))
891 __cxa_exception *ep = ucbp_to_ep(ucbp);
892 const type_info *throw_type = ep->exceptionType;
893 bool previous_qualifiers_include_const = true; // for pointer qualification conversion
894 unsigned int pointer_depth = 0;
895 void *original_objectp = ep + 1;
896 void *current_objectp = original_objectp;
900 // Match if identical
902 if (*throw_type == *match_type) {
903 *matched_objectpp = original_objectp;
904 #ifdef CPP_DIAGNOSTICS
905 printf("__cxa_type_match: success\n");
907 return ctm_succeeded;
910 // Fail if one is a pointer and the other isn't
912 const type_info &type_throw_type = typeid(*throw_type);
913 const type_info &type_match_type = typeid(*match_type);
915 if ((type_throw_type == typeid(abi::__pointer_type_info) ||
916 type_match_type == typeid(abi::__pointer_type_info)) &&
917 type_throw_type != type_match_type) {
918 #ifdef CPP_DIAGNOSTICS
919 printf("__cxa_type_match: failed (mixed ptr/non-ptr)\n");
924 // Both are pointers or neither is
925 if (type_throw_type == typeid(abi::__pointer_type_info)) {
927 #ifdef CPP_DIAGNOSTICS
928 printf("__cxa_type_match: throwing a ptr\n");
931 // Check match_type is at least as CV-qualified as throw_type
932 unsigned int match_quals = CV_quals_of_pointee(match_type);
933 unsigned int throw_quals = CV_quals_of_pointee(throw_type);
934 if (any_qualifier_missing(match_quals, throw_quals)) {
935 #ifdef CPP_DIAGNOSTICS
936 printf("__cxa_type_match: failed (missing qualifiers)\n");
940 // If the match type has additional qualifiers not found in the
941 // throw type, any previous qualifiers must have included const
942 if (any_qualifier_missing(throw_quals, match_quals) &&
943 !previous_qualifiers_include_const) {
944 #ifdef CPP_DIAGNOSTICS
945 printf("__cxa_type_match: failed (not all qualifiers have const)\n");
949 if (!is_const(match_quals))
950 previous_qualifiers_include_const = false;
951 throw_type = ((const abi::__pbase_type_info *)throw_type)->__pointee;
952 match_type = ((const abi::__pbase_type_info *)match_type)->__pointee;
953 if (current_objectp != NULL)
954 current_objectp = *(void **)current_objectp;
958 // Neither is a pointer now but qualification conversion has been done.
959 // See if pointer conversion on the original was possible.
960 // T* will match void*
962 if (pointer_depth == 1 && *match_type == typeid(void)) {
963 if (is_reference_type) {
964 #ifdef CPP_DIAGNOSTICS
965 printf("__cxa_type_match: failed (void *&)\n");
969 *matched_objectpp = original_objectp;
970 #ifdef CPP_DIAGNOSTICS
971 printf("__cxa_type_match: success (conversion to void *)\n");
973 return ctm_succeeded;
977 // Else if we have 2 (different) class types, a derived class is matched by a
978 // non-ambiguous public base class (perhaps not a leftmost one) and a
979 // pointer to a derived class is matched by a non-reference pointer to
980 // non-ambiguous public base class (perhaps not a leftmost one).
981 // __si_class_type_info and __vmi_class_type_info are classes with bases.
983 void *matched_base_p;
985 if ((pointer_depth == 0 || (pointer_depth == 1 && !is_reference_type)) &&
986 (type_throw_type == typeid(abi::__si_class_type_info) ||
987 type_throw_type == typeid(abi::__vmi_class_type_info))) {
988 if (DERIVED_TO_BASE_CONVERSION(current_objectp, &matched_base_p,
989 throw_type, match_type)) {
990 #ifdef CPP_DIAGNOSTICS
991 printf("__cxa_type_match: success (matched base 0x%x of 0x%x%s, thrown object 0x%x)\n",
992 matched_base_p, current_objectp,
993 pointer_depth == 0 ? "" : " via ptr",
996 *matched_objectpp = matched_base_p;
997 return pointer_depth == 0 ? ctm_succeeded : ctm_succeeded_with_ptr_to_base;
999 #ifdef CPP_DIAGNOSTICS
1000 printf("__cxa_type_match: failed (derived to base failed or ref to base pointer)\n");
1006 #ifdef CPP_DIAGNOSTICS
1007 printf("__cxa_type_match: failed (types simply differ)\n");
1014 /* For debugging purposes: */
1016 extern "C" bool debug__cxa_type_match(void *objptr,
1017 const type_info *throw_type,
1018 const type_info *catch_type,
1019 void **matched_objectpp)
1021 /* Create enough of an exception object that the type-matcher can run, then
1022 * check the type. Objptr is expected to be the result of a call to
1023 * __cxa_allocate_exception, which has then been copy-constructed.
1025 __cxa_exception *e = ((__cxa_exception *)objptr) - 1;
1026 e->exceptionType = throw_type;
1027 return __cxa_type_match(&e->ucb, catch_type, false, matched_objectpp);
1032 #endif /* arm_exceptions_throw_c */
1033 #ifdef arm_exceptions_rethrow_c
1035 /* Redeclare _Unwind_RaiseException as weak (if WEAKDECL is defined
1036 * appropriately) so the use from __cxa_rethrow does not on its own
1037 * force the unwind library to be loaded.
1040 extern "C" WEAKDECL _Unwind_Reason_Code _Unwind_RaiseException(UCB *ucbp);
1042 #pragma exceptions_unwind
1044 EXPORT_C void __cxa_rethrow(void)
1046 // Recover the exception object - it is the most recent caught exception object
1047 __cxa_eh_globals *g = __cxa_get_globals();
1048 __cxa_exception *ep = g->caughtExceptions;
1051 // Must call terminate here if no such exception
1052 if (ep == NULL) NAMES::call_terminate_handler(NULL);
1054 UCB *ucbp = &ep->ucb;
1056 // Mark the object as being propagated by throw, preventing multiple
1057 // propagation and also permitting __cxa_end_catch to do the right
1058 // thing when it is called from the handler's cleanup.
1060 ep->propagationCount++;
1062 // Now reraise, taking care with foreign exceptions
1064 foreign = NAMES::is_foreign_exception(ucbp);
1066 // Indirect through the intermediate object to the foreign ucb
1067 ucbp = (UCB *)ep->exceptionType;
1069 // Increment the uncaught C++ exceptions count
1070 g->uncaughtExceptions++;
1073 // Tell debugger what's happening
1075 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, foreign ? NULL : ep->exceptionType);
1077 // Initiate unwinding - if we get control back, call C++ routine terminate()
1079 _Unwind_RaiseException(ucbp);
1081 #ifdef CPP_DIAGNOSTICS
1082 printf("__cxa_rethrow: throw failed\n");
1085 __cxa_call_terminate(ucbp);
1088 #endif /* arm_exceptions_rethrow_c */
1089 #ifdef arm_exceptions_foreign_c
1091 /* During catch and cleanup, foreign exception objects are dealt with using
1092 * an intermediate __cxa_exception block in the appropriate exceptions
1093 * chain. This block has the same exception_class as the real foreign
1094 * ucb, and points to the real ucb via the intermediate block's exceptionType
1095 * field. This helper function checks whether it has been passed such an
1096 * intermediate block and sets one up if not. Only call it when the UCB
1097 * is known to belong to a foreign exception.
1100 __cxa_exception *NAMES::get_foreign_intermediary(__cxa_exception *head_ep, UCB *ucbp)
1102 if (head_ep != NULL) {
1103 UCB *head_ucbp = &head_ep->ucb;
1104 if (NAMES::same_exceptions_class(&head_ucbp->exception_class, &ucbp->exception_class) &&
1105 (UCB *)head_ep->exceptionType == ucbp)
1109 // Create an intermediate block. Only initialise as much as necessary
1110 __cxa_exception *ep = ((__cxa_exception *)__cxa_allocate_exception(0)) - 1;
1111 UCB *new_ucbp = &ep->ucb;
1112 memcpy(new_ucbp->exception_class, ucbp->exception_class, EXCEPTIONS_CLASS_SIZE);
1113 ep->propagationCount = 0; // Not propagating
1114 ep->handlerCount = 0; // Not handled
1115 ep->nextCaughtException = NULL; // Not in chain
1116 ep->exceptionType = (const type_info *)ucbp; // The foreign UCB
1121 #endif /* arm_exceptions_foreign_c */
1122 #ifdef arm_exceptions_cleanup_c
1124 EXPORT_C bool __cxa_begin_cleanup(UCB *ucbp)
1126 // Indicate that a cleanup is about to start.
1127 // Save the exception pointer over the cleanup for recovery later, using a chain.
1128 // If we allowed the exception to be rethrown in a cleanup, then
1129 // the object might appear multiple times at the head of this chain,
1130 // and the propagationCount could be used to track this - at this point,
1131 // the object is logically in the chain propagationCount-1 times, and
1132 // physically 0 or 1 times. Thus if propagationCount == 1 we should insert
1133 // it physically. A similar rule is used for physical removal in
1134 //__cxa_end_cleanup.
1135 // Foreign exceptions are handled via an intermediate __cxa_exception object
1136 // in a similar way as __cxa_begin_catch.
1138 __cxa_eh_globals *g = __cxa_get_globals();
1139 __cxa_exception *ep;
1141 if (NAMES::is_foreign_exception(ucbp)) {
1142 // coverity[alloc_fn] coverity[var_assign]
1143 ep = NAMES::get_foreign_intermediary(g->propagatingExceptions, ucbp);
1144 ep->propagationCount++; // Indicate one (or one additional) propagation
1146 ep = ucbp_to_ep(ucbp);
1149 if (ep->propagationCount == 1) {
1150 // Insert into chain
1151 ep->nextPropagatingException = g->propagatingExceptions;
1152 g->propagatingExceptions = ep;
1154 // coverity[leaked_storage]
1159 // Helper function for __cxa_end_cleanup
1161 extern "C" UCB * __ARM_cxa_end_cleanup(void)
1163 // Recover and return the currently propagating exception (from the
1164 // head of the propagatingExceptions chain).
1165 // propagationCount at this moment is a logical count of how many times the
1166 // item is in the chain so physically unchain it when this count is 1.
1167 // Foreign exceptions use an intermediary.
1169 __cxa_eh_globals *g = __cxa_get_globals();
1170 __cxa_exception *ep = g->propagatingExceptions;
1172 if (ep == NULL) terminate();
1174 UCB *ucbp = &ep->ucb;
1175 if (NAMES::is_foreign_exception(ucbp)) {
1176 // Get the foreign ucb
1177 ucbp = (UCB *)ep->exceptionType;
1178 if (ep->propagationCount == 1) {
1179 // Free the intermediate ucb (see description in __cxa_begin_catch)
1180 void *eop = (void *)(ep + 1);
1181 g->propagatingExceptions = ep->nextPropagatingException;
1182 __cxa_free_exception(eop);
1184 ep->propagationCount--;
1188 if (ep->propagationCount == 1) { // logically in chain once - so unchain
1189 g->propagatingExceptions = ep->nextPropagatingException;
1195 // __cxa_end_cleanup is called at the end of a cleanup fragment.
1196 // It must do the C++ housekeeping, then call _Unwind_Resume, but it must
1197 // damage no significant registers in the process.
1199 EXPORT_C __asm void __cxa_end_cleanup(void) {
1200 extern __ARM_cxa_end_cleanup;
1201 extern _Unwind_Resume WEAKASMDECL;
1204 preserve8; // This is preserve8 (ARM assembler heuristics are inadequate)
1211 bl __ARM_cxa_end_cleanup; // returns UCB address in r0
1218 bl _Unwind_Resume; // won't return
1220 stmfd r13!, {r1-r12}
1221 bl __ARM_cxa_end_cleanup; // returns UCB address in r0
1222 ldmia r13!, {r1-r12};
1223 b _Unwind_Resume; // won't return
1228 #endif /* arm_exceptions_cleanup_c */
1229 #ifdef arm_exceptions_catchsemantics_c
1231 /* Update date structures as if catching an object.
1232 * Call this from __cxa_begin_catch when actually catching an object,
1233 * and from external_exception_termination when called by a foreign runtime
1234 * after one of our objects was caught.
1237 void NAMES::eh_catch_semantics(UCB *ucbp)
1239 __cxa_eh_globals *g = __cxa_get_globals();
1240 __cxa_exception *ep;
1242 if (NAMES::is_foreign_exception(ucbp)) {
1243 // Foreign exception. Get the associated intermediary block or
1244 // make one if there isn't one already.
1245 // In the case of a rethrow, the foreign object may already be on
1246 // the handled exceptions chain (it will be first).
1247 // coverity[alloc_fn] coverity[var_assign]
1248 ep = NAMES::get_foreign_intermediary(g->caughtExceptions, ucbp);
1251 ep = ucbp_to_ep(ucbp);
1252 // Decrement the propagation count
1253 ep->propagationCount--;
1254 // Decrement the total uncaught C++ exceptions count
1255 g->uncaughtExceptions--;
1258 // Common code for our EO's, and foreign ones where we work on the intermediate EO
1260 // Increment the handler count for this exception object
1263 // Push the ep onto the "handled exceptions" chain if it is not already there.
1264 // (If catching a rethrow, it may already be there)
1266 if (ep->nextCaughtException == NULL) {
1267 ep->nextCaughtException = g->caughtExceptions;
1268 g->caughtExceptions = ep;
1270 // coverity[leaked_storage]
1274 #endif /* arm_exceptions_catchsemantics_c */
1275 #ifdef arm_exceptions_getexceptionptr_c
1277 EXPORT_C void *__cxa_get_exception_ptr(UCB *ucbp)
1279 return (void *)ucbp->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT]; // The matched object, if any
1283 #endif /* arm_exceptions_getexceptionptr_c */
1284 #ifdef arm_exceptions_begincatch_c
1286 void *__cxa_begin_catch(UCB *ucbp)
1288 void *match = (void *)ucbp->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT]; // The matched object, if any
1290 // Update the data structures
1292 NAMES::eh_catch_semantics(ucbp);
1294 // Tell the unwinder the exception propagation has finished,
1295 // and return the object pointer
1297 _Unwind_Complete(ucbp);
1302 #endif /* arm_exceptions_begincatch_c */
1303 #ifdef arm_exceptions_endcatch_c
1305 #pragma exceptions_unwind
1307 EXPORT_C void __cxa_end_catch(void)
1309 // Recover the exception object - it is the most recent caught exception object
1310 __cxa_eh_globals *g = __cxa_get_globals();
1311 __cxa_exception *ep = g->caughtExceptions;
1313 if (ep == NULL) terminate();
1315 // Rethrow in progress?
1317 bool object_being_rethrown = ep->propagationCount != 0;
1319 // Decrement the handler count for this exception object
1322 // Unstack the object if it is no longer being handled anywhere.
1323 // Destroy and free the object if it is no longer alive -
1324 // it is dead if its handler count becomes 0, unless it is
1325 // about to be rethrown.
1326 // If the dtor throws, allow its exception to propagate.
1327 // Do different things if it is a foreign exception object.
1329 if (ep->handlerCount == 0) {
1330 void *eop = (void *)(ep + 1);
1331 UCB *ucbp = &ep->ucb;
1332 bool foreign = NAMES::is_foreign_exception(ucbp);
1334 // Unstack it from the caught exceptions stack - it is guaranteed to be top item.
1335 g->caughtExceptions = ep->nextCaughtException;
1338 // Get the foreign ucb and free the intermediate ucb (see description in __cxa_begin_catch)
1339 ucbp = (UCB *)ep->exceptionType;
1340 __cxa_free_exception(eop);
1342 ep->nextCaughtException = NULL; // So __cxa_begin_catch knows it isn't in the chain
1345 // Now destroy the exception object if it's no longer needed
1346 if (!object_being_rethrown) {
1349 // Notify the foreign language, if it so requested
1350 if (ucbp->exception_cleanup != NULL)
1351 (ucbp->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, ucbp);
1355 // One of our objects: do C++-specific semantics
1357 if (ep->exceptionDestructor != NULL) {
1358 // Run the dtor. If it throws, free the memory anyway and
1359 // propagate the new exception.
1360 #ifdef ARM_EXCEPTIONS_ENABLED
1362 (ep->exceptionDestructor)(eop);
1364 // Free the memory and reraise
1365 __cxa_free_exception(eop);
1369 (ep->exceptionDestructor)(eop);
1372 // Dtor (if there was one) didn't throw. Free the memory.
1373 __cxa_free_exception(eop);
1375 } // !object_being_rethrown
1376 } // ep->handlerCount == 0
1380 #endif /* arm_exceptions_endcatch_c */
1381 #ifdef arm_exceptions_bad_typeid_c
1383 #pragma exceptions_unwind
1385 EXPORT_C void __cxa_bad_typeid(void)
1387 throw std::bad_typeid();
1391 #endif /* arm_exceptions_bad_typeid_c */
1392 #ifdef arm_exceptions_bad_cast_c
1394 #pragma exceptions_unwind
1396 EXPORT_C void __cxa_bad_cast(void)
1398 throw std::bad_cast();
1402 #endif /* arm_exceptions_bad_cast_c */