First public contribution.
1 /* The C++ exceptions runtime support
3 * Copyright 2002-2003 ARM Limited.
8 1. Subject to the provisions of clause 2, ARM hereby grants to LICENSEE a
9 perpetual, non-exclusive, nontransferable, royalty free, worldwide licence
10 to use this Example Implementation of Exception Handling solely for the
11 purpose of developing, having developed, manufacturing, having
12 manufactured, offering to sell, selling, supplying or otherwise
13 distributing products which comply with the Exception Handling ABI for the
14 ARM Architecture specification. All other rights are reserved to ARM or its
17 2. THIS EXAMPLE IMPLEMENTATION OF EXCEPTION HANDLING IS PROVIDED "AS IS"
18 WITH NO WARRANTIES EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED
19 TO ANY WARRANTY OF SATISFACTORY QUALITY, MERCHANTABILITY, NONINFRINGEMENT
20 OR FITNESS FOR A PARTICULAR PURPOSE.
23 * RCS $Revision: 1.29.2.1 $
24 * Checkin $Date: 2004/01/20 15:11:16 $
25 * Revising $Author: achapman $
28 /* This source file is compiled automatically by ARM's make system into
29 * multiple object files. The source regions constituting object file
30 * xxx.o are delimited by ifdef xxx_c / endif directives.
32 * The source regions currently marked are:
33 * arm_exceptions_globs_c
34 * arm_exceptions_mem_c
35 * arm_exceptions_uncaught_c
36 * arm_exceptions_terminate_c
37 * arm_exceptions_setterminate_c
38 * arm_exceptions_unexpected_c
39 * arm_exceptions_setunexpected_c
40 * arm_exceptions_support_c
41 * arm_exceptions_callterm_c
42 * arm_exceptions_callunex_c
43 * arm_exceptions_currenttype_c
44 * arm_exceptions_alloc_c
45 * arm_exceptions_free_c
46 * arm_exceptions_throw_c
47 * arm_exceptions_rethrow_c
48 * arm_exceptions_foreign_c
49 * arm_exceptions_cleanup_c
50 * arm_exceptions_begincatch_c
51 * arm_exceptions_endcatch_c
52 * arm_exceptions_bad_typeid_c
53 * arm_exceptions_bad_cast_c
61 #include "unwind_env.h"
62 // Language-independent unwinder declarations:
65 /* By default, none of these routines are unwindable: */
66 #pragma noexceptions_unwind
70 typedef _Unwind_Control_Block UCB;
72 using std::terminate_handler;
73 using std::unexpected_handler;
75 using std::unexpected;
78 /* Redeclare these interface routines as weak, so using them does not
79 * pull in the unwind library. We only want the unwind library if
80 * someone throws (or raises an exception from some other language).
82 WEAKDECL NORETURNDECL void _Unwind_Resume(UCB *);
83 WEAKDECL void _Unwind_Complete(UCB *);
86 * Define DEBUG to get extra interfaces which assist debugging this functionality.
87 * Define PRINTED_DIAGNOSTICS for printed diagnostics.
90 #define PRINTED_DIAGNOSTICS
93 #ifdef PRINTED_DIAGNOSTICS
94 extern "C" int printf(const char *, ...);
97 /* --------- "Exceptions_class" string for our implementation: --------- */
99 #define EXCEPTIONS_CLASS_SIZE 8
100 #define ARMCPP_EXCEPTIONS_CLASS "ARM\0C++\0"
103 /* --------- Exception control object: --------- */
105 // Type __cxa_exception is the combined C++ housekeeping (LEO) and UCB.
106 // It will be followed by the user exception object, hence must ensure
107 // the latter is aligned on an 8 byte boundary.
109 struct __cxa_exception {
110 const type_info *exceptionType; // RTTI object describing the type of the exception
111 void *(*exceptionDestructor)(void *); // Destructor for the exception object (may be NULL)
112 unexpected_handler unexpectedHandler; // Handler in force after evaluating throw expr
113 terminate_handler terminateHandler; // Handler in force after evaluating throw expr
114 __cxa_exception *nextCaughtException; // Chain of "currently caught" c++ exception objects
115 uint32_t handlerCount; // Count of how many handlers this EO is "caught" in
116 __cxa_exception *nextPropagatingException; // Chain of objects saved over cleanup
117 uint32_t propagationCount; // Count of live propagations (throws) of this EO
118 UCB ucb; // Forces alignment of next item to 8-byte boundary
122 /* --------- Control "globals": --------- */
124 // We do this by putting all the thread-specific "globals" into a single
125 // area of store, which we allocate space for dynamically.
126 // We don't define a constructor for this; see comments with __cxa_get_globals.
128 typedef void (*handler)(void);
130 struct __cxa_eh_globals {
131 uint32_t uncaughtExceptions; // counter
132 unexpected_handler unexpectedHandler; // per-thread handler
133 terminate_handler terminateHandler; // per-thread handler
134 bool implementation_ever_called_terminate; // true if it ever did
135 handler call_hook; // transient field to tell terminate/unexpected which hook to call
136 __cxa_exception *caughtExceptions; // chain of "caught" exceptions
137 __cxa_exception *propagatingExceptions; // chain of "propagating" (in cleanup) exceptions
138 void *emergency_buffer; // emergency buffer for when rest of heap full
142 /* ---------- Entry points: ---------- */
144 /* There is a little type-delicacy required here as __cxa_throw takes a
145 * function pointer. Setting aside the problem of not being able to form
146 * a pointer to a destructor in C++, if we simply say extern "C" here
147 * then the function pointer will also have C linkage and will be a
148 * pointer to a C function. This causes problems when __cxa_throw is
149 * defined (unless we repeat the extern "C" at the definition site) because
150 * the fnptr in the definition gets C++ linkage, hence that __cxa_throw has
151 * a different signature to the declared one, and so the function we wanted
152 * doesn't get defined at all.
153 * Maybe it should just take a void * but this seems more honest.
156 typedef void *(*cppdtorptr)(void *);
160 // Protocol routines called directly from application code
162 void *__cxa_allocate_exception(size_t size);
163 void __cxa_free_exception(void *);
164 WEAKDECL void __cxa_throw(void *, const type_info *, cppdtorptr);
165 void __cxa_rethrow(void);
166 void *__cxa_begin_catch(UCB *);
167 void __cxa_end_catch(void);
168 void __cxa_end_cleanup(void);
169 const type_info *__cxa_current_exception_type(void);
171 // Protocol routines usually called only by the personality routine(s).
173 void __cxa_call_terminate(UCB *);
174 void __cxa_call_unexpected(UCB *);
175 bool __cxa_begin_cleanup(UCB *);
176 bool __cxa_type_match(UCB *, const std::type_info *, void **);
178 // Auxilliary routines
180 __cxa_eh_globals *__cxa_get_globals(void);
181 void __cxa_bad_typeid(void);
182 void __cxa_bad_cast(void);
184 // Emergency memory buffer management routines
186 void *__ARM_exceptions_buffer_init(void);
187 void *__ARM_exceptions_buffer_allocate(void *, size_t);
188 void *__ARM_exceptions_buffer_free(void *, void *);
196 void default_unexpected_handler(void);
197 void call_terminate_handler(UCB *);
198 void eh_catch_semantics(UCB *);
199 bool is_foreign_exception(UCB *);
200 bool same_exceptions_class(const void *, const void *);
201 __cxa_exception *get_foreign_intermediary(__cxa_exception *, UCB *);
204 // Macro: convert ucb pointer to __cxa_exception pointer
206 #define ucbp_to_ep(UCB_P) ((__cxa_exception *)((char *)(UCB_P) - offsetof(__cxa_exception, ucb)))
209 #ifdef arm_exceptions_globs_c
211 /* --------- Allocating and retrieving "globals": --------- */
213 // The exception-handling globals should be allocated per-thread.
214 // This is done here assuming the existance of a zero-initialised void*
215 // pointer location obtainable by the macro EH_GLOBALS.
217 // Default terminate handler:
219 static void __default_terminate_handler(void) {
223 // If std::unexpected() is in the image, include a default handler for it:
224 namespace NAMES { WEAKDECL void default_unexpected_handler(void); }
226 // If this symbol is present, allocate an emergency buffer.
227 // As we aren't allowed static data, make it a function
228 extern "C" WEAKDECL void __ARM_exceptions_buffer_required(void);
231 // __cxa_eh_globals returns the per-thread memory. There are several complications,
232 // all of which relate to not touching the exceptions system while trying to
234 // 1) We can't obtain memory by calling new or nothrow new as both of these use
235 // exceptions internally, so we must use malloc
236 // 2) We choose not to initialise the memory via placement new and a constructor,
237 // since placement new is declared with an empty function exception specification,
238 // which causes more of the exceptions system to always be pulled in.
239 // 3) We can't call terminate, as terminate looks in the memory we are trying to
242 __cxa_eh_globals *__cxa_get_globals(void)
244 __cxa_eh_globals *this_thread_globals = (__cxa_eh_globals *)(EH_GLOBALS);
245 if (this_thread_globals == NULL) {
248 // Obtain some memory: this is thread-safe provided malloc is.
249 this_thread_globals = (__cxa_eh_globals *)malloc(sizeof(__cxa_eh_globals));
250 if (this_thread_globals == NULL) abort(); // NOT terminate(), which calls this fn
252 // Save the pointer in the specially-provided location
253 EH_GLOBALS = this_thread_globals;
255 // Finally initialise the memory by hand
256 this_thread_globals->uncaughtExceptions = 0;
257 this_thread_globals->unexpectedHandler = NAMES::default_unexpected_handler;
258 this_thread_globals->terminateHandler = __default_terminate_handler;
259 this_thread_globals->implementation_ever_called_terminate = false;
260 this_thread_globals->call_hook = NULL;
261 this_thread_globals->caughtExceptions = NULL;
262 this_thread_globals->propagatingExceptions = NULL;
263 if (&__ARM_exceptions_buffer_required == NULL)
264 this_thread_globals->emergency_buffer = NULL;
266 this_thread_globals->emergency_buffer = __ARM_exceptions_buffer_init();
269 return this_thread_globals;
273 #endif /* arm_exceptions_globs_c */
274 #ifdef arm_exceptions_mem_c
276 /* --------- Emergency memory: --------- */
278 // It is possible to reserve memory for throwing bad_alloc when the heap
279 // is otherwise full. The ARM implementation provides hooks to do this.
280 // The default implementation reserves just enough space for a bad_alloc
281 // object, so if memory is later exhausted bad_alloc can still be thrown.
282 // Note there is no guarantee or requirement that the exception being
283 // thrown is actually bad_alloc.
285 // A usage flag and enough space for a bad_alloc exception control object
287 struct emergency_eco {
292 struct emergency_buffer {
294 struct emergency_eco eco;
298 void* __ARM_exceptions_buffer_init(void)
300 emergency_buffer *buffer = (emergency_buffer *)malloc(sizeof(emergency_buffer));
301 if (buffer == NULL) return NULL;
302 buffer->inuse = false;
307 void *__ARM_exceptions_buffer_allocate(void *buffer, size_t size)
309 emergency_buffer *b = (emergency_buffer *)buffer;
310 if (size > sizeof(emergency_eco) || b == NULL || b->inuse) return NULL;
315 // Deallocator: Must return non-NULL if and only if it recognises
316 // and releases the supplied object
317 void *__ARM_exceptions_buffer_free(void *buffer, void *addr)
319 emergency_buffer *b = (emergency_buffer *)buffer;
320 if (b == NULL || addr != &b->eco) return NULL;
326 #endif /* arm_exceptions_mem_c */
327 #ifdef arm_exceptions_uncaught_c
329 /* ---- uncaught_exception() ---- */
331 /* The EDG (and I think our) interpretation is that if the implementation
332 * ever called terminate(), uncaught_exception() should return true.
335 bool std::uncaught_exception(void)
337 __cxa_eh_globals *g = __cxa_get_globals();
338 return g->implementation_ever_called_terminate || g->uncaughtExceptions;
342 #endif /* arm_exceptions_uncaught_c */
343 #ifdef arm_exceptions_terminate_c
345 /* ---- terminate() etc ---- */
347 /* The behaviour of terminate() must differ between calls by the
348 * implementation and calls by the application. This is achieved by having the
349 * implementation set call_hook immediately before the call to terminate().
350 * The hook called by terminate() should terminate the program without
351 * returning to the caller. There is no requirement for terminate() itself to
355 void std::terminate(void)
357 __cxa_eh_globals *g = __cxa_get_globals();
359 if (g->call_hook != NULL) {
360 // Clear then call hook fn we were passed
361 handler call_hook = g->call_hook;
365 // Call global hook fn
366 g->terminateHandler();
368 // If hook fn returns:
373 #endif /* arm_exceptions_terminate_c */
374 #ifdef arm_exceptions_setterminate_c
376 terminate_handler std::set_terminate(terminate_handler h) throw()
378 __cxa_eh_globals *g = __cxa_get_globals();
379 terminate_handler old = g->terminateHandler;
380 g->terminateHandler = h;
385 #endif /* arm_exceptions_setterminate_c */
386 #ifdef arm_exceptions_unexpected_c
388 /* ---- unexpected() etc ---- */
389 /* Comments as per terminate() */
391 void NAMES::default_unexpected_handler(void) {
395 #pragma exceptions_unwind
397 void std::unexpected(void)
399 __cxa_eh_globals *g = __cxa_get_globals();
401 if (g->call_hook != NULL) {
402 // Clear then call hook fn we were passed
403 handler call_hook = g->call_hook;
407 // Call global hook fn
408 g->unexpectedHandler();
411 // If hook fn returns:
416 #endif /* arm_exceptions_unexpected_c */
417 #ifdef arm_exceptions_setunexpected_c
419 unexpected_handler std::set_unexpected(unexpected_handler h) throw()
421 __cxa_eh_globals *g = __cxa_get_globals();
422 unexpected_handler old = g->unexpectedHandler;
423 g->unexpectedHandler = h;
428 #endif /* arm_exceptions_setunexpected_c */
429 #ifdef arm_exceptions_support_c
431 /* ---------- Helper functions: ---------- */
433 /* Two routines to determine whether two exceptions objects share a layout.
434 * This is determined by checking whether the UCB exception_class members
436 * In principle we could use memcmp to perform this check (the code is
437 * given below) but the check is quite frequent and so that is costly.
438 * Therefore for efficiency we make use of the fact that the UCB is
439 * word aligned, that the exception_class member is consequently
440 * word aligned within it, and that we know the size of the member.
441 * We take care elsewhere to only ever call the routines with pointers
442 * to word-aligned addresses.
447 // Straightforward versions
449 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
451 return memcmp(ec1, ec2, EXCEPTIONS_CLASS_SIZE) == 0; // identical
454 // One of our exception objects, or not?
456 bool NAMES::is_foreign_exception(UCB *ucbp)
458 return !NAMES::same_exceptions_class(&ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS);
465 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
467 uint32_t *ip1 = (uint32_t *)ec1;
468 uint32_t *ip2 = (uint32_t *)ec2;
469 return ip1[0] == ip2[0] && ip1[1] == ip2[1];
472 // One of our exception objects, or not?
474 bool NAMES::is_foreign_exception(UCB *ucbp)
476 // Need a word-aligned copy of the string
478 const char s[EXCEPTIONS_CLASS_SIZE+1]; int dummy;
479 } is_foreign_exception_static = {ARMCPP_EXCEPTIONS_CLASS};
480 return !NAMES::same_exceptions_class(&ucbp->exception_class, &is_foreign_exception_static.s);
486 #endif /* arm_exceptions_support_c */
487 #ifdef arm_exceptions_callterm_c
489 /* When the implementation wants to call terminate(), do the following:
490 * Mark the object as "caught" so it can be rethrown.
491 * Set the hook function for terminate() to call;
492 * Mark the fact that terminate() has been called by the implementation;
493 * We have to be careful - the implementation might encounter an error while
494 * unwinding a foreign exception, and also it is possible this might be
495 * called after failing to obtain a ucb.
498 void NAMES::call_terminate_handler(UCB *ucbp)
500 __cxa_eh_globals *g = __cxa_get_globals();
504 g->call_hook = g->terminateHandler;
506 // Extract the hook to call
507 if (NAMES::is_foreign_exception(ucbp)) {
509 g->call_hook = g->terminateHandler; // best we can do under the circumstances
512 __cxa_exception *ep = ucbp_to_ep(ucbp);
513 g->call_hook = ep->terminateHandler; // the one in force at the point of throw
517 g->implementation_ever_called_terminate = true;
523 void __cxa_call_terminate(UCB *ucbp)
525 if (ucbp != NULL) // Record entry to (implicit) handler
526 __cxa_begin_catch(ucbp);
528 NAMES::call_terminate_handler(ucbp);
533 #endif /* arm_exceptions_callterm_c */
534 #ifdef arm_exceptions_callunex_c
536 /* When the implementation wants to call unexpected(), do the following:
537 * Mark the object as "caught" so it can be rethrown.
538 * Set the hook function for unexpected() to call;
539 * Call unexpected and trap any throw to make sure it is acceptable.
540 * We have to be careful - the implementation might encounter an error while
541 * unwinding a foreign exception.
544 #pragma exceptions_unwind
546 void __cxa_call_unexpected(UCB *ucbp)
549 // Extract data we will need from the barrier cache before
550 // anyone has a chance to overwrite it
552 uint32_t rtti_count = ucbp->barrier_cache.bitpattern[1];
553 uint32_t base = ucbp->barrier_cache.bitpattern[2];
554 uint32_t stride = ucbp->barrier_cache.bitpattern[3];
555 uint32_t rtti_offset_array_addr = ucbp->barrier_cache.bitpattern[4];
557 // Also get the globals here and the eop
559 __cxa_eh_globals *g = __cxa_get_globals();
560 __cxa_exception *ep = ucbp_to_ep(ucbp);
562 #ifdef ARM_EXCEPTIONS_ENABLED
566 // Record entry to (implicit) handler
568 __cxa_begin_catch(ucbp);
570 // Now extract the hook to call
572 if (NAMES::is_foreign_exception(ucbp)) {
574 g->call_hook = g->unexpectedHandler; // best we can do under the circumstances
577 g->call_hook = ep->unexpectedHandler; // the one in force at the point of throw
579 unexpected(); // never returns normally, but might throw something
581 #ifdef ARM_EXCEPTIONS_ENABLED
584 // Unexpected() threw. This requires some delicacy.
585 // There are 2 possibilities:
586 // i) rethrow of the same object
587 // ii) throw of a new object
588 // Unexpected() is an implicit handler, and we manually called
589 // __cxa_begin_catch on the ingoing object. We need to call
590 // __cxa_end_catch on that object and, if the object is no longer
591 // being handled (possible in case ii), this will cause its destruction.
592 // The wrinkle is that in case ii the object is not on top of the catch
593 // stack because we just caught something else.
595 // Get hold of what was thrown (which we just caught).
597 __cxa_exception *epnew = g->caughtExceptions;
599 // Call __cxa_end_catch on the original object, taking care with the catch chain
602 // rethrow - easy & safe - object is at top of chain and handlercount > 1
605 // not rethrow - unchain the top (new) object, clean up the next one,
606 // and put the top object back
609 g->caughtExceptions = epnew->nextCaughtException;
610 // assert g->caughtExceptions == ep now
611 // Decrement its handlercount (this might call a dtor if the count goes to 0,
612 // and the dtor might throw - if it does, just give up)
619 epnew->nextCaughtException = g->caughtExceptions;
620 g->caughtExceptions = epnew;
623 // See whether what was thrown is permitted, and in passing
624 // see if std::bad_exception is permitted
626 bool bad_exception_permitted = false;
628 for (i = 0; i < rtti_count; i++) {
629 void *matched_object;
630 const type_info *fnspec = (const type_info *)(*(uint32_t *)rtti_offset_array_addr + base);
631 if (__cxa_type_match(&(epnew->ucb), fnspec, &matched_object)) {
632 #ifdef PRINTED_DIAGNOSTICS
633 printf("__cxa_call_unexpected: fnspec matched\n");
635 throw; // got a match - propagate it
637 if (&typeid(std::bad_exception) == fnspec)
638 bad_exception_permitted = true;
639 rtti_offset_array_addr += stride;
642 // There was no match...
643 if (bad_exception_permitted) throw std::bad_exception(); // transmute
645 // Otherwise call epnew's terminate handler
646 NAMES::call_terminate_handler(&epnew->ucb);
652 #endif /* arm_exceptions_callunex_c */
653 #ifdef arm_exceptions_currenttype_c
655 /* Yield the type of the currently handled exception, or null if none or the
659 const type_info *__cxa_current_exception_type(void)
661 __cxa_eh_globals *g = __cxa_get_globals();
662 __cxa_exception *ep = g->caughtExceptions;
663 if (ep == NULL || NAMES::is_foreign_exception(&ep->ucb)) return NULL;
664 return ep->exceptionType;
668 #endif /* arm_exceptions_currenttype_c */
669 #ifdef arm_exceptions_alloc_c
671 /* Allocate store for controlling an exception propagation */
673 void *__cxa_allocate_exception(size_t size)
675 __cxa_eh_globals *g = __cxa_get_globals();
677 // Allocate store for a __cxa_exception header and the EO.
678 // Allocated store should be thread-safe and persistent, and must do
679 // something sensible if the allocation fails
681 size_t total_size = size + sizeof(__cxa_exception);
682 __cxa_exception *ep = (__cxa_exception *)malloc(total_size);
684 // Try the emergency memory pool
685 ep = (__cxa_exception *)__ARM_exceptions_buffer_allocate(g->emergency_buffer, total_size);
686 if (ep == NULL) NAMES::call_terminate_handler(NULL);
689 UCB *ucbp = &ep->ucb;
691 // Initialise the UCB
693 memcpy(ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS, EXCEPTIONS_CLASS_SIZE);
694 ucbp->exception_cleanup = NULL; /* initialise properly before throwing */
695 ucbp->unwinder_cache.reserved1 = 0; /* required to do this */
697 // Initialise parts of the LEO, in case copy-construction of the EO results
698 // in a need to call terminate (via __cxa_call_terminate)
700 ep->handlerCount = 0; // Not in any handlers
701 ep->nextCaughtException = NULL; // Not in any handlers
702 ep->nextPropagatingException = NULL; // Not saved over cleanup
703 ep->propagationCount = 0; // Not propagating
704 ep->terminateHandler = g->terminateHandler; // Cache current terminate handler
705 ep->unexpectedHandler = g->unexpectedHandler; // Cache current unexpected handler
707 // Return pointer to the EO
713 #endif /* arm_exceptions_alloc_c */
714 #ifdef arm_exceptions_free_c
716 /* Free store allocated by __cxa_allocate_exception */
718 void __cxa_free_exception(void *eop)
720 __cxa_eh_globals *g = __cxa_get_globals();
721 char *ep = (char *)eop - sizeof(__cxa_exception);
722 if (__ARM_exceptions_buffer_free(g->emergency_buffer, ep)) return;
727 #endif /* arm_exceptions_free_c */
728 #ifdef arm_exceptions_throw_c
730 /* This routine is called when a foreign runtime catches one of our exception
731 * objects and then exits its catch by a means other than rethrow.
732 * We should clean it up as if we had caught it ourselves.
735 static void external_exception_termination(_Unwind_Reason_Code c, UCB *ucbp)
737 NAMES::eh_catch_semantics(ucbp);
742 /* Initiate a throw */
745 #pragma exceptions_unwind
747 void __cxa_throw(void *eop, const type_info *t, cppdtorptr d)
749 __cxa_exception *ep = (__cxa_exception *)((char *)eop - sizeof(__cxa_exception));
750 UCB *ucbp = &ep->ucb;
752 // Initialise the remaining LEO and UCB fields not done by __cxa_allocate_exception
754 ucbp->exception_cleanup = external_exception_termination;
755 ep->exceptionType = t;
756 ep->exceptionDestructor = d;
757 ep->propagationCount = 1; // Propagating by 1 throw
759 // Increment the uncaught C++ exceptions count
761 __cxa_eh_globals *g = __cxa_get_globals();
762 g->uncaughtExceptions++;
764 // Tell debugger what's happening
766 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, t);
768 // Initiate unwinding - if we get control back, call C++ routine terminate()
770 _Unwind_RaiseException(ucbp);
772 #ifdef PRINTED_DIAGNOSTICS
773 printf("__cxa_throw: throw failed\n");
776 __cxa_call_terminate(ucbp);
781 /* ----- Type matching: ----- */
783 /* This is located here so that (in ARM's implementation) it is only retained in
784 * an image if the application itself throws.
787 /* Type matching functions.
788 * C++ DR126 says the matching rules for fnspecs are intended to be the same as
790 * "A function is said to allow an exception of type E if its exception-specification
791 * contains a type T for which a handler of type T would be a match (15.3 except.handle)
792 * for an exception of type E."
793 * Thus we have a single type matching rule.
798 #define CV_quals_of_pointee(P) (((const abi::__pbase_type_info *)(P))->__flags & \
799 (abi::__pbase_type_info::__const_mask | \
800 abi::__pbase_type_info::__volatile_mask))
802 #define is_const(QUALS) (((QUALS) & abi::__pbase_type_info::__const_mask) != 0)
804 #define any_qualifier_missing(TEST_QUALS, REF_QUALS) ((~(TEST_QUALS) & (REF_QUALS)) != 0)
806 /* A routine is required for derived class to base class conversion.
807 * This is obtained via a macro definition DERIVED_TO_BASE_CONVERSION
811 /* External entry point:
812 * Type check the c++ rtti object for compatibility against the type of
813 * the object containing the ucb. Return a pointer to the matched object
814 * (possibly a non-leftmost baseclass of the exception object)
816 bool __cxa_type_match(UCB *ucbp, const type_info *match_type, void **matched_objectpp)
818 if (NAMES::is_foreign_exception(ucbp))
821 __cxa_exception *ep = ucbp_to_ep(ucbp);
822 const type_info *throw_type = ep->exceptionType;
823 bool previous_qualifiers_include_const = true; // for pointer qualification conversion
824 unsigned int pointer_depth = 0;
825 void *original_objectp = ep + 1;
826 void *current_objectp = original_objectp;
830 // Match if identical
832 if (throw_type == match_type) {
833 *matched_objectpp = original_objectp;
834 #ifdef PRINTED_DIAGNOSTICS
835 printf("__cxa_type_match: success (exact match after any ptrs)\n");
840 // Fail if one is a pointer and the other isn't
842 const type_info *type_throw_type = &typeid(*throw_type);
843 const type_info *type_match_type = &typeid(*match_type);
845 if ((type_throw_type == &typeid(abi::__pointer_type_info) ||
846 type_match_type == &typeid(abi::__pointer_type_info)) &&
847 type_throw_type != type_match_type) {
848 #ifdef PRINTED_DIAGNOSTICS
849 printf("__cxa_type_match: failed (mixed ptr/non-ptr)\n");
854 // Both are pointers or neither is
855 if (type_throw_type == &typeid(abi::__pointer_type_info)) {
857 #ifdef PRINTED_DIAGNOSTICS
858 printf("__cxa_type_match: throwing a ptr\n");
861 // Check match_type is at least as CV-qualified as throw_type
862 unsigned int match_quals = CV_quals_of_pointee(match_type);
863 unsigned int throw_quals = CV_quals_of_pointee(throw_type);
864 if (any_qualifier_missing(match_quals, throw_quals)) {
865 #ifdef PRINTED_DIAGNOSTICS
866 printf("__cxa_type_match: failed (missing qualifiers)\n");
870 // If the match type has additional qualifiers not found in the
871 // throw type, any previous qualifiers must have included const
872 if (any_qualifier_missing(throw_quals, match_quals) &&
873 !previous_qualifiers_include_const) {
874 #ifdef PRINTED_DIAGNOSTICS
875 printf("__cxa_type_match: failed (not all qualifiers have const)\n");
879 if (!is_const(match_quals))
880 previous_qualifiers_include_const = false;
881 throw_type = ((const abi::__pbase_type_info *)throw_type)->__pointee;
882 match_type = ((const abi::__pbase_type_info *)match_type)->__pointee;
883 if (current_objectp != NULL)
884 current_objectp = *(void **)current_objectp;
888 // Neither is a pointer now but qualification conversion has been done.
889 // See if pointer conversion on the original was possible.
890 // T* will match void*
892 if (pointer_depth == 1 && match_type == &typeid(void)) {
893 *matched_objectpp = original_objectp;
894 #ifdef PRINTED_DIAGNOSTICS
895 printf("__cxa_type_match: success(conversion to void *)\n");
900 // Else if we have 2 class types, a derived class is matched by a
901 // non-ambiguous public base class (perhaps not a leftmost one).
902 // __si_class_type_info and __vmi_class_type_info are classes with bases.
904 void *matched_base_p;
906 if (pointer_depth < 2 &&
907 (type_throw_type == &typeid(abi::__si_class_type_info) ||
908 type_throw_type == &typeid(abi::__vmi_class_type_info))) {
909 if (DERIVED_TO_BASE_CONVERSION(current_objectp, &matched_base_p,
910 throw_type, match_type)) {
911 #ifdef PRINTED_DIAGNOSTICS
912 printf("__cxa_type_match: success (matched base 0x%x of 0x%x%s, thrown object 0x%x)\n",
913 matched_base_p, current_objectp,
914 pointer_depth == 0 ? "" : " via ptr",
917 *matched_objectpp = pointer_depth == 0 ? matched_base_p : original_objectp;
920 #ifdef PRINTED_DIAGNOSTICS
921 printf("__cxa_type_match: failed (derived to base failed)\n");
927 #ifdef PRINTED_DIAGNOSTICS
928 printf("__cxa_type_match: failed (types simply differ)\n");
935 /* For debugging purposes: */
937 extern "C" bool debug__cxa_type_match(void *objptr,
938 const type_info *throw_type,
939 const type_info *catch_type,
940 void **matched_objectpp)
942 /* Create enough of an exception object that the type-matcher can run, then
943 * check the type. Objptr is expected to be the result of a call to
944 * __cxa_allocate_exception, which has then been copy-constructed.
946 __cxa_exception *e = ((__cxa_exception *)objptr) - 1;
947 e->exceptionType = throw_type;
948 return __cxa_type_match(&e->ucb, catch_type, matched_objectpp);
953 #endif /* arm_exceptions_throw_c */
954 #ifdef arm_exceptions_rethrow_c
956 /* Redeclare _Unwind_RaiseException as weak (if WEAKDECL is defined
957 * appropriately) so the use from __cxa_rethrow does not on its own
958 * force the unwind library to be loaded.
961 extern "C" WEAKDECL _Unwind_Reason_Code _Unwind_RaiseException(UCB *ucbp);
963 #pragma exceptions_unwind
965 void __cxa_rethrow(void)
967 // Recover the exception object - it is the most recent caught exception object
968 __cxa_eh_globals *g = __cxa_get_globals();
969 __cxa_exception *ep = g->caughtExceptions;
972 // Must call terminate here if no such exception
973 if (ep == NULL) NAMES::call_terminate_handler(NULL);
975 UCB *ucbp = &ep->ucb;
977 // Mark the object as being propagated by throw, preventing multiple
978 // propagation and also permitting __cxa_end_catch to do the right
979 // thing when it is called from the handler's cleanup.
981 ep->propagationCount++;
983 // Now reraise, taking care with foreign exceptions
985 foreign = NAMES::is_foreign_exception(ucbp);
987 // Indirect through the intermediate object to the foreign ucb
988 ucbp = (UCB *)ep->exceptionType;
990 // Increment the uncaught C++ exceptions count
991 g->uncaughtExceptions++;
994 // Tell debugger what's happening
996 DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, foreign ? NULL : ep->exceptionType);
998 // Initiate unwinding - if we get control back, call C++ routine terminate()
1000 _Unwind_RaiseException(ucbp);
1002 #ifdef PRINTED_DIAGNOSTICS
1003 printf("__cxa_rethrow: throw failed\n");
1006 __cxa_call_terminate(ucbp);
1009 #endif /* arm_exceptions_rethrow_c */
1010 #ifdef arm_exceptions_foreign_c
1012 /* During catch and cleanup, foreign exception objects are dealt with using
1013 * an intermediate __cxa_exception block in the appropriate exceptions
1014 * chain. This block has the same exception_class as the real foreign
1015 * ucb, and points to the real ucb via the intermediate block's exceptionType
1016 * field. This helper function checks whether it has been passed such an
1017 * intermediate block and sets one up if not. Only call it when the UCB
1018 * is known to belong to a foreign exception.
1021 __cxa_exception *NAMES::get_foreign_intermediary(__cxa_exception *head_ep, UCB *ucbp)
1023 if (head_ep != NULL) {
1024 UCB *head_ucbp = &head_ep->ucb;
1025 if (NAMES::same_exceptions_class(&head_ucbp->exception_class, &ucbp->exception_class) &&
1026 (UCB *)head_ep->exceptionType == ucbp)
1030 // Create an intermediate block. Only initialise as much as necessary
1031 __cxa_exception *ep = ((__cxa_exception *)__cxa_allocate_exception(0)) - 1;
1032 UCB *new_ucbp = &ep->ucb;
1033 memcpy(new_ucbp->exception_class, ucbp->exception_class, EXCEPTIONS_CLASS_SIZE);
1034 ep->propagationCount = 0; // Not propagating
1035 ep->handlerCount = 0; // Not handled
1036 ep->nextCaughtException = NULL; // Not in chain
1037 ep->exceptionType = (const type_info *)ucbp; // The foreign UCB
1042 #endif /* arm_exceptions_foreign_c */
1043 #ifdef arm_exceptions_cleanup_c
1045 bool __cxa_begin_cleanup(UCB *ucbp)
1047 // Indicate that a cleanup is about to start.
1048 // Save the exception pointer over the cleanup for recovery later, using a chain.
1049 // If we allowed the exception to be rethrown in a cleanup, then
1050 // the object might appear multiple times at the head of this chain,
1051 // and the propagationCount could be used to track this - at this point,
1052 // the object is logically in the chain propagationCount-1 times, and
1053 // physically 0 or 1 times. Thus if propagationCount == 1 we should insert
1054 // it physically. A similar rule is used for physical removal in
1055 //__cxa_end_cleanup.
1056 // Foreign exceptions are handled via an intermediate __cxa_exception object
1057 // in a similar way as __cxa_begin_catch.
1059 __cxa_eh_globals *g = __cxa_get_globals();
1060 __cxa_exception *ep;
1062 if (NAMES::is_foreign_exception(ucbp)) {
1063 ep = NAMES::get_foreign_intermediary(g->propagatingExceptions, ucbp);
1064 ep->propagationCount++; // Indicate one (or one additional) propagation
1066 ep = ucbp_to_ep(ucbp);
1069 if (ep->propagationCount == 1) {
1070 // Insert into chain
1071 ep->nextPropagatingException = g->propagatingExceptions;
1072 g->propagatingExceptions = ep;
1079 // Helper function for __cxa_end_cleanup
1081 extern "C" UCB * __ARM_cxa_end_cleanup(void)
1083 // Recover and return the currently propagating exception (from the
1084 // head of the propagatingExceptions chain).
1085 // propagationCount at this moment is a logical count of how many times the
1086 // item is in the chain so physically unchain it when this count is 1.
1087 // Foreign exceptions use an intermediary.
1089 __cxa_eh_globals *g = __cxa_get_globals();
1090 __cxa_exception *ep = g->propagatingExceptions;
1092 if (ep == NULL) terminate();
1094 UCB *ucbp = &ep->ucb;
1095 if (NAMES::is_foreign_exception(ucbp)) {
1096 // Get the foreign ucb
1097 ucbp = (UCB *)ep->exceptionType;
1098 if (ep->propagationCount == 1) {
1099 // Free the intermediate ucb (see description in __cxa_begin_catch)
1100 void *eop = (void *)(ep + 1);
1101 g->propagatingExceptions = ep->nextPropagatingException;
1102 __cxa_free_exception(eop);
1104 ep->propagationCount--;
1108 if (ep->propagationCount == 1) { // logically in chain once - so unchain
1109 g->propagatingExceptions = ep->nextPropagatingException;
1115 // __cxa_end_cleanup is called at the end of a cleanup fragment.
1116 // It must do the C++ housekeeping, then call _Unwind_Resume, but it must
1117 // damage no significant registers in the process.
1119 __asm void __cxa_end_cleanup(void) {
1120 extern __ARM_cxa_end_cleanup;
1121 extern _Unwind_Resume WEAKASMDECL;
1124 preserve8; // This is preserve8 (ARM assembler heuristics are inadequate)
1131 bl __ARM_cxa_end_cleanup; // returns UCB address in r0
1138 bl _Unwind_Resume; // won't return
1140 stmfd r13!, {r1-r12}
1141 bl __ARM_cxa_end_cleanup; // returns UCB address in r0
1142 ldmia r13!, {r1-r12};
1143 b _Unwind_Resume; // won't return
1148 #endif /* arm_exceptions_cleanup_c */
1149 #ifdef arm_exceptions_catchsemantics_c
1151 /* Update date structures as if catching an object.
1152 * Call this from __cxa_begin_catch when actually catching an object,
1153 * and from external_exception_termination when called by a foreign runtime
1154 * after one of our objects was caught.
1157 void NAMES::eh_catch_semantics(UCB *ucbp)
1159 __cxa_eh_globals *g = __cxa_get_globals();
1160 __cxa_exception *ep;
1162 if (NAMES::is_foreign_exception(ucbp)) {
1163 // Foreign exception. Get the associated intermediary block or
1164 // make one if there isn't one already.
1165 // In the case of a rethrow, the foreign object may already be on
1166 // the handled exceptions chain (it will be first).
1167 ep = NAMES::get_foreign_intermediary(g->caughtExceptions, ucbp);
1170 ep = ucbp_to_ep(ucbp);
1171 // Decrement the propagation count
1172 ep->propagationCount--;
1173 // Decrement the total uncaught C++ exceptions count
1174 g->uncaughtExceptions--;
1177 // Common code for our EO's, and foreign ones where we work on the intermediate EO
1179 // Increment the handler count for this exception object
1182 // Push the ep onto the "handled exceptions" chain if it is not already there.
1183 // (If catching a rethrow, it may already be there)
1185 if (ep->nextCaughtException == NULL) {
1186 ep->nextCaughtException = g->caughtExceptions;
1187 g->caughtExceptions = ep;
1192 #endif /* arm_exceptions_catchsemantics_c */
1193 #ifdef arm_exceptions_begincatch_c
1195 void *__cxa_begin_catch(UCB *ucbp)
1197 void *match = (void *)ucbp->barrier_cache.bitpattern[0]; // The matched object, if any
1199 // Update the data structures
1201 NAMES::eh_catch_semantics(ucbp);
1203 // Tell the unwinder the exception propagation has finished,
1204 // and return the object pointer
1206 _Unwind_Complete(ucbp);
1211 #endif /* arm_exceptions_begincatch_c */
1212 #ifdef arm_exceptions_endcatch_c
1214 #pragma exceptions_unwind
1216 void __cxa_end_catch(void)
1218 // Recover the exception object - it is the most recent caught exception object
1219 __cxa_eh_globals *g = __cxa_get_globals();
1220 __cxa_exception *ep = g->caughtExceptions;
1222 if (ep == NULL) terminate();
1224 // Rethrow in progress?
1226 bool object_being_rethrown = ep->propagationCount != 0;
1228 // Decrement the handler count for this exception object
1231 // Unstack the object if it is no longer being handled anywhere.
1232 // Destroy and free the object if it is no longer alive -
1233 // it is dead if its handler count becomes 0, unless it is
1234 // about to be rethrown.
1235 // If the dtor throws, allow its exception to propagate.
1236 // Do different things if it is a foreign exception object.
1238 if (ep->handlerCount == 0) {
1239 void *eop = (void *)(ep + 1);
1240 UCB *ucbp = &ep->ucb;
1241 bool foreign = NAMES::is_foreign_exception(ucbp);
1243 // Unstack it from the caught exceptions stack - it is guaranteed to be top item.
1244 g->caughtExceptions = ep->nextCaughtException;
1247 // Get the foreign ucb and free the intermediate ucb (see description in __cxa_begin_catch)
1248 ucbp = (UCB *)ep->exceptionType;
1249 __cxa_free_exception(eop);
1251 ep->nextCaughtException = NULL; // So __cxa_begin_catch knows it isn't in the chain
1254 // Now destroy the exception object if it's no longer needed
1255 if (!object_being_rethrown) {
1258 // Notify the foreign language, if it so requested
1259 if (ucbp->exception_cleanup != NULL)
1260 (ucbp->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, ucbp);
1264 // One of our objects: do C++-specific semantics
1266 if (ep->exceptionDestructor != NULL) {
1267 // Run the dtor. If it throws, free the memory anyway and
1268 // propagate the new exception.
1269 #ifdef ARM_EXCEPTIONS_ENABLED
1271 (ep->exceptionDestructor)(eop);
1273 // Free the memory and reraise
1274 __cxa_free_exception(eop);
1278 (ep->exceptionDestructor)(eop);
1281 // Dtor (if there was one) didn't throw. Free the memory.
1282 __cxa_free_exception(eop);
1284 } // !object_being_rethrown
1285 } // ep->handlerCount == 0
1289 #endif /* arm_exceptions_endcatch_c */
1290 #ifdef arm_exceptions_bad_typeid_c
1292 #pragma exceptions_unwind
1294 void __cxa_bad_typeid(void)
1296 throw std::bad_typeid();
1300 #endif /* arm_exceptions_bad_typeid_c */
1301 #ifdef arm_exceptions_bad_cast_c
1303 #pragma exceptions_unwind
1305 void __cxa_bad_cast(void)
1307 throw std::bad_cast();
1311 #endif /* arm_exceptions_bad_cast_c */