os/kernelhwsrv/kernel/eka/compsupp/aehabi/cppsemantics.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* The C++ exceptions runtime support
     2  *
     3  * Copyright 2002-2003 ARM Limited.
     4  */
     5 /*
     6   Licence
     7 
     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
    15   licensors.
    16 
    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.
    21 */
    22 /*
    23  * RCS $Revision: 1.29.2.1 $
    24  * Checkin $Date: 2004/01/20 15:11:16 $
    25  * Revising $Author: achapman $
    26  */
    27 
    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.
    31  *
    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
    54  */
    55 
    56 #include <string.h>
    57 #include <typeinfo>
    58 #include <exception>
    59 #include <new>
    60 // Environment:
    61 #include "unwind_env.h"
    62 // Language-independent unwinder declarations:
    63 #include "unwinder.h"
    64 
    65 /* By default, none of these routines are unwindable: */
    66 #pragma noexceptions_unwind
    67 
    68 /* For brevity: */
    69 
    70 typedef _Unwind_Control_Block UCB;
    71 
    72 using std::terminate_handler;
    73 using std::unexpected_handler;
    74 using std::terminate;
    75 using std::unexpected;
    76 using std::type_info;
    77 
    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).
    81  */
    82 WEAKDECL NORETURNDECL void _Unwind_Resume(UCB *);
    83 WEAKDECL void _Unwind_Complete(UCB *);
    84 
    85 /* Diagnostics:
    86  * Define DEBUG to get extra interfaces which assist debugging this functionality.
    87  * Define PRINTED_DIAGNOSTICS for printed diagnostics.
    88  */
    89 #ifdef DEBUG
    90 #define PRINTED_DIAGNOSTICS
    91 #endif
    92 
    93 #ifdef PRINTED_DIAGNOSTICS
    94 extern "C" int printf(const char *, ...);
    95 #endif
    96 
    97 /* --------- "Exceptions_class" string for our implementation: --------- */
    98 
    99 #define EXCEPTIONS_CLASS_SIZE 8
   100 #define ARMCPP_EXCEPTIONS_CLASS "ARM\0C++\0"
   101 
   102 
   103 /* --------- Exception control object: --------- */
   104 
   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.
   108 
   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
   119 };
   120 
   121 
   122 /* --------- Control "globals": --------- */
   123 
   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.
   127 
   128 typedef void (*handler)(void);
   129 
   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
   139 };
   140 
   141 
   142 /* ---------- Entry points: ---------- */
   143 
   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.
   154  */
   155 
   156 typedef void *(*cppdtorptr)(void *);
   157 
   158 extern "C" {
   159 
   160   // Protocol routines called directly from application code
   161 
   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);
   170 
   171   // Protocol routines usually called only by the personality routine(s).
   172 
   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 **);
   177 
   178   // Auxilliary routines
   179 
   180   __cxa_eh_globals *__cxa_get_globals(void);
   181   void __cxa_bad_typeid(void);
   182   void __cxa_bad_cast(void);
   183 
   184   // Emergency memory buffer management routines
   185 
   186   void *__ARM_exceptions_buffer_init(void);
   187   void *__ARM_exceptions_buffer_allocate(void *, size_t);
   188   void *__ARM_exceptions_buffer_free(void *, void *);
   189 }
   190 
   191 
   192 // Support routines
   193 
   194 #define NAMES __ARM
   195 namespace NAMES {
   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 *);
   202 }
   203 
   204 // Macro: convert ucb pointer to __cxa_exception pointer
   205 
   206 #define ucbp_to_ep(UCB_P) ((__cxa_exception *)((char *)(UCB_P) - offsetof(__cxa_exception, ucb)))
   207 
   208 
   209 #ifdef arm_exceptions_globs_c
   210 
   211 /* --------- Allocating and retrieving "globals": --------- */
   212 
   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.
   216 
   217 // Default terminate handler:
   218 
   219 static void __default_terminate_handler(void) {
   220   abort();
   221 }
   222 
   223 // If std::unexpected() is in the image, include a default handler for it:
   224 namespace NAMES { WEAKDECL void default_unexpected_handler(void); }
   225 
   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);
   229 
   230 
   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
   233 // initialise it:
   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
   240 //    allocate.
   241 
   242 __cxa_eh_globals *__cxa_get_globals(void)
   243 {
   244   __cxa_eh_globals *this_thread_globals = (__cxa_eh_globals *)(EH_GLOBALS);
   245   if (this_thread_globals == NULL) {
   246 
   247     // First call
   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
   251 
   252     // Save the pointer in the specially-provided location
   253     EH_GLOBALS = this_thread_globals;
   254 
   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;
   265     else
   266       this_thread_globals->emergency_buffer = __ARM_exceptions_buffer_init();
   267   }
   268 
   269   return this_thread_globals;
   270 }
   271 
   272 
   273 #endif /* arm_exceptions_globs_c */
   274 #ifdef arm_exceptions_mem_c
   275 
   276 /* --------- Emergency memory: --------- */
   277 
   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.
   284 
   285 // A usage flag and enough space for a bad_alloc exception control object
   286 
   287 struct emergency_eco {
   288   __cxa_exception ep;
   289   std::bad_alloc b;
   290 };
   291 
   292 struct emergency_buffer {
   293   bool inuse;
   294   struct emergency_eco eco;
   295 };
   296 
   297 // Initialiser
   298 void* __ARM_exceptions_buffer_init(void)
   299 {
   300   emergency_buffer *buffer = (emergency_buffer *)malloc(sizeof(emergency_buffer));
   301   if (buffer == NULL) return NULL;
   302   buffer->inuse = false;
   303   return buffer;
   304 }
   305 
   306 // Allocator
   307 void *__ARM_exceptions_buffer_allocate(void *buffer, size_t size)
   308 {
   309   emergency_buffer *b = (emergency_buffer *)buffer;
   310   if (size > sizeof(emergency_eco) || b == NULL || b->inuse) return NULL;
   311   b->inuse = true;
   312   return &b->eco;
   313 }
   314 
   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)
   318 {
   319   emergency_buffer *b = (emergency_buffer *)buffer;
   320   if (b == NULL || addr != &b->eco) return NULL;
   321   b->inuse = false;
   322   return b;
   323 }
   324 
   325 
   326 #endif /* arm_exceptions_mem_c */
   327 #ifdef arm_exceptions_uncaught_c
   328 
   329 /* ---- uncaught_exception() ---- */
   330 
   331 /* The EDG (and I think our) interpretation is that if the implementation
   332  * ever called terminate(), uncaught_exception() should return true.
   333  */
   334 
   335 bool std::uncaught_exception(void)
   336 {
   337    __cxa_eh_globals *g = __cxa_get_globals();
   338    return g->implementation_ever_called_terminate || g->uncaughtExceptions;
   339 }
   340 
   341 
   342 #endif /* arm_exceptions_uncaught_c */
   343 #ifdef arm_exceptions_terminate_c
   344 
   345 /* ---- terminate() etc ---- */
   346 
   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
   352  * intercept throws.
   353  */
   354 
   355 void std::terminate(void)
   356 {
   357   __cxa_eh_globals *g = __cxa_get_globals();
   358 
   359   if (g->call_hook != NULL) {
   360     // Clear then call hook fn we were passed
   361     handler call_hook = g->call_hook;
   362     g->call_hook = NULL;
   363     call_hook();
   364   } else {
   365     // Call global hook fn
   366     g->terminateHandler();
   367   }
   368   // If hook fn returns:
   369   abort();
   370 }
   371 
   372 
   373 #endif /* arm_exceptions_terminate_c */
   374 #ifdef arm_exceptions_setterminate_c
   375 
   376 terminate_handler std::set_terminate(terminate_handler h) throw()
   377 {
   378   __cxa_eh_globals *g = __cxa_get_globals();
   379   terminate_handler old = g->terminateHandler;
   380   g->terminateHandler = h;
   381   return old;
   382 }
   383 
   384 
   385 #endif /* arm_exceptions_setterminate_c */
   386 #ifdef arm_exceptions_unexpected_c
   387 
   388 /* ---- unexpected() etc ---- */
   389 /* Comments as per terminate() */
   390 
   391 void NAMES::default_unexpected_handler(void) {
   392   terminate();
   393 }
   394 
   395 #pragma exceptions_unwind
   396 
   397 void std::unexpected(void)
   398 {
   399   __cxa_eh_globals *g = __cxa_get_globals();
   400 
   401   if (g->call_hook != NULL) {
   402     // Clear then call hook fn we were passed
   403     handler call_hook = g->call_hook;
   404     g->call_hook = NULL;
   405     call_hook();
   406   } else {
   407     // Call global hook fn
   408     g->unexpectedHandler();
   409   }
   410 
   411   // If hook fn returns:
   412   abort();
   413 }
   414 
   415 
   416 #endif /* arm_exceptions_unexpected_c */
   417 #ifdef arm_exceptions_setunexpected_c
   418 
   419 unexpected_handler std::set_unexpected(unexpected_handler h) throw()
   420 {
   421   __cxa_eh_globals *g = __cxa_get_globals();
   422   unexpected_handler old = g->unexpectedHandler;
   423   g->unexpectedHandler = h;
   424   return old;
   425 }
   426 
   427 
   428 #endif /* arm_exceptions_setunexpected_c */
   429 #ifdef arm_exceptions_support_c
   430 
   431 /* ---------- Helper functions: ---------- */
   432 
   433 /* Two routines to determine whether two exceptions objects share a layout.
   434  * This is determined by checking whether the UCB exception_class members
   435  * are identical.
   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.
   443  */
   444 
   445 #if 0
   446 
   447 // Straightforward versions
   448 
   449 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
   450 {
   451   return memcmp(ec1, ec2, EXCEPTIONS_CLASS_SIZE) == 0; // identical
   452 }
   453 
   454 // One of our exception objects, or not?
   455 
   456 bool NAMES::is_foreign_exception(UCB *ucbp)
   457 {
   458   return !NAMES::same_exceptions_class(&ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS);
   459 }
   460 
   461 #else
   462 
   463 // Faster versions
   464 
   465 bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
   466 {
   467   uint32_t *ip1 = (uint32_t *)ec1;
   468   uint32_t *ip2 = (uint32_t *)ec2;
   469   return ip1[0] == ip2[0] && ip1[1] == ip2[1];
   470 }
   471 
   472 // One of our exception objects, or not?
   473 
   474 bool NAMES::is_foreign_exception(UCB *ucbp)
   475 {
   476   // Need a word-aligned copy of the string
   477   static const union {
   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);
   481 }
   482 
   483 #endif
   484 
   485 
   486 #endif /* arm_exceptions_support_c */
   487 #ifdef arm_exceptions_callterm_c
   488 
   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.
   496  */
   497 
   498 void NAMES::call_terminate_handler(UCB *ucbp)
   499 {
   500   __cxa_eh_globals *g = __cxa_get_globals();
   501 
   502   if (ucbp == NULL) {
   503     // Call global hook
   504     g->call_hook = g->terminateHandler;
   505   } else {
   506     // Extract the hook to call
   507     if (NAMES::is_foreign_exception(ucbp)) {
   508       // Someone else's
   509       g->call_hook = g->terminateHandler;  // best we can do under the circumstances
   510     } else {
   511       // One of ours
   512       __cxa_exception *ep = ucbp_to_ep(ucbp);
   513       g->call_hook = ep->terminateHandler; // the one in force at the point of throw
   514     }
   515   }
   516 
   517   g->implementation_ever_called_terminate = true;
   518   terminate();
   519   // never returns
   520 }
   521 
   522 
   523 void __cxa_call_terminate(UCB *ucbp)
   524 {
   525   if (ucbp != NULL) // Record entry to (implicit) handler
   526     __cxa_begin_catch(ucbp);
   527 
   528   NAMES::call_terminate_handler(ucbp);
   529   // never returns
   530 }
   531 
   532 
   533 #endif /* arm_exceptions_callterm_c */
   534 #ifdef arm_exceptions_callunex_c
   535 
   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.
   542  */
   543 
   544 #pragma exceptions_unwind
   545 
   546 void __cxa_call_unexpected(UCB *ucbp)
   547 {
   548 
   549   // Extract data we will need from the barrier cache before
   550   // anyone has a chance to overwrite it
   551 
   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];
   556 
   557   // Also get the globals here and the eop
   558 
   559   __cxa_eh_globals *g = __cxa_get_globals();
   560   __cxa_exception *ep = ucbp_to_ep(ucbp);
   561 
   562 #ifdef ARM_EXCEPTIONS_ENABLED
   563   try {
   564 #endif
   565 
   566     // Record entry to (implicit) handler
   567 
   568     __cxa_begin_catch(ucbp);
   569 
   570     // Now extract the hook to call
   571 
   572     if (NAMES::is_foreign_exception(ucbp)) {
   573       // Someone else's
   574       g->call_hook = g->unexpectedHandler;  // best we can do under the circumstances
   575     } else {
   576       // One of ours
   577       g->call_hook = ep->unexpectedHandler; // the one in force at the point of throw
   578     }
   579     unexpected();  // never returns normally, but might throw something
   580 
   581 #ifdef ARM_EXCEPTIONS_ENABLED
   582   } catch (...) {
   583 
   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.
   594 
   595     // Get hold of what was thrown (which we just caught).
   596 
   597     __cxa_exception *epnew = g->caughtExceptions;
   598 
   599     // Call __cxa_end_catch on the original object, taking care with the catch chain
   600 
   601     if (epnew == ep) {
   602       // rethrow - easy & safe - object is at top of chain and handlercount > 1
   603       __cxa_end_catch();
   604     } else {
   605       // not rethrow - unchain the top (new) object, clean up the next one,
   606       // and put the top object back
   607 
   608       // unchain
   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)
   613       try {
   614 	__cxa_end_catch();
   615       } catch(...) {
   616 	terminate();
   617       }
   618       // Chain back in
   619       epnew->nextCaughtException = g->caughtExceptions;
   620       g->caughtExceptions = epnew;
   621     }
   622 
   623     // See whether what was thrown is permitted, and in passing
   624     // see if std::bad_exception is permitted
   625 
   626     bool bad_exception_permitted = false;
   627     uint32_t i;
   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");
   634 #endif
   635 	throw; // got a match - propagate it
   636       }
   637       if (&typeid(std::bad_exception) == fnspec)
   638 	bad_exception_permitted = true;
   639       rtti_offset_array_addr += stride;
   640     }
   641 
   642     // There was no match...
   643     if (bad_exception_permitted) throw std::bad_exception(); // transmute
   644 
   645     // Otherwise call epnew's terminate handler
   646     NAMES::call_terminate_handler(&epnew->ucb);
   647   }
   648 #endif
   649 }
   650 
   651 
   652 #endif /* arm_exceptions_callunex_c */
   653 #ifdef arm_exceptions_currenttype_c
   654 
   655 /* Yield the type of the currently handled exception, or null if none or the
   656  * object is foreign.
   657  */
   658 
   659 const type_info *__cxa_current_exception_type(void)
   660 {
   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;
   665 }
   666 
   667 
   668 #endif /* arm_exceptions_currenttype_c */
   669 #ifdef arm_exceptions_alloc_c
   670 
   671 /* Allocate store for controlling an exception propagation */
   672 
   673 void *__cxa_allocate_exception(size_t size)
   674 {
   675   __cxa_eh_globals *g = __cxa_get_globals();
   676 
   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
   680 
   681   size_t total_size = size + sizeof(__cxa_exception);
   682   __cxa_exception *ep = (__cxa_exception *)malloc(total_size);
   683   if (ep == NULL) {
   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);
   687   }
   688 
   689   UCB *ucbp = &ep->ucb;
   690 
   691   // Initialise the UCB
   692 
   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 */
   696 
   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)
   699 
   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
   706 
   707   // Return pointer to the EO
   708 
   709   return ep + 1;
   710 }
   711 
   712 
   713 #endif /* arm_exceptions_alloc_c */
   714 #ifdef arm_exceptions_free_c
   715 
   716 /* Free store allocated by __cxa_allocate_exception */
   717 
   718 void __cxa_free_exception(void *eop)
   719 {
   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;
   723   free(ep);
   724 }
   725 
   726 
   727 #endif /* arm_exceptions_free_c */
   728 #ifdef arm_exceptions_throw_c
   729 
   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.
   733  */
   734 
   735 static void external_exception_termination(_Unwind_Reason_Code c, UCB *ucbp)
   736 {
   737   NAMES::eh_catch_semantics(ucbp);
   738   __cxa_end_catch();
   739 }
   740 
   741 
   742 /* Initiate a throw */
   743 
   744 #pragma push
   745 #pragma exceptions_unwind
   746 
   747 void __cxa_throw(void *eop, const type_info *t, cppdtorptr d)
   748 {
   749   __cxa_exception *ep = (__cxa_exception *)((char *)eop - sizeof(__cxa_exception));
   750   UCB *ucbp = &ep->ucb;
   751 
   752   // Initialise the remaining LEO and UCB fields not done by __cxa_allocate_exception
   753 
   754   ucbp->exception_cleanup = external_exception_termination;
   755   ep->exceptionType = t;
   756   ep->exceptionDestructor = d;
   757   ep->propagationCount = 1;      // Propagating by 1 throw
   758 
   759   // Increment the uncaught C++ exceptions count
   760 
   761   __cxa_eh_globals *g = __cxa_get_globals();
   762   g->uncaughtExceptions++;
   763 
   764   // Tell debugger what's happening
   765 
   766   DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, t);
   767 
   768   // Initiate unwinding - if we get control back, call C++ routine terminate()
   769 
   770   _Unwind_RaiseException(ucbp);
   771 
   772 #ifdef PRINTED_DIAGNOSTICS
   773   printf("__cxa_throw: throw failed\n");
   774 #endif
   775 
   776   __cxa_call_terminate(ucbp);
   777 }
   778 
   779 #pragma pop
   780 
   781 /* ----- Type matching: ----- */
   782 
   783 /* This is located here so that (in ARM's implementation) it is only retained in
   784  * an image if the application itself throws.
   785  */
   786 
   787 /* Type matching functions.
   788  * C++ DR126 says the matching rules for fnspecs are intended to be the same as
   789  * those for catch:
   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.
   794  */
   795 
   796 /* Helper macros: */
   797 
   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))
   801 
   802 #define is_const(QUALS) (((QUALS) & abi::__pbase_type_info::__const_mask) != 0)
   803 
   804 #define any_qualifier_missing(TEST_QUALS, REF_QUALS) ((~(TEST_QUALS) & (REF_QUALS)) != 0)
   805 
   806 /* A routine is required for derived class to base class conversion.
   807  * This is obtained via a macro definition DERIVED_TO_BASE_CONVERSION
   808  * in unwind_env.h.
   809  */
   810 
   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)
   815  */
   816 bool __cxa_type_match(UCB *ucbp, const type_info *match_type, void **matched_objectpp)
   817 {
   818   if (NAMES::is_foreign_exception(ucbp))
   819     return false;
   820 
   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;
   827 
   828   for (;;) {
   829 
   830     // Match if identical
   831 
   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");
   836 #endif
   837       return true;
   838     }
   839 
   840     // Fail if one is a pointer and the other isn't
   841 
   842     const type_info *type_throw_type = &typeid(*throw_type);
   843     const type_info *type_match_type = &typeid(*match_type);
   844 
   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");
   850 #endif
   851       return false;
   852     }
   853 
   854     // Both are pointers or neither is
   855     if (type_throw_type == &typeid(abi::__pointer_type_info)) {
   856       // Both are pointers
   857 #ifdef PRINTED_DIAGNOSTICS
   858       printf("__cxa_type_match: throwing a ptr\n");
   859 #endif
   860       pointer_depth++;
   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");
   867 #endif
   868 	return false;
   869       }
   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");
   876 #endif
   877 	return false;
   878       }
   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;
   885       continue;
   886     }
   887 
   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*
   891 
   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");
   896 #endif
   897       return true;
   898     }
   899 
   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.
   903 
   904     void *matched_base_p;
   905 
   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",
   915 	       original_objectp);
   916 #endif
   917 	*matched_objectpp = pointer_depth == 0 ? matched_base_p : original_objectp;
   918 	return true;
   919       } else {
   920 #ifdef PRINTED_DIAGNOSTICS
   921 	printf("__cxa_type_match: failed (derived to base failed)\n");
   922 #endif
   923 	return false;
   924       }
   925     }
   926 
   927 #ifdef PRINTED_DIAGNOSTICS
   928     printf("__cxa_type_match: failed (types simply differ)\n");
   929 #endif
   930     return false;
   931   } /* for */
   932 }
   933 
   934 
   935 /* For debugging purposes: */
   936 #ifdef DEBUG
   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)
   941 {
   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.
   945    */
   946   __cxa_exception *e = ((__cxa_exception *)objptr) - 1;
   947   e->exceptionType = throw_type;
   948   return __cxa_type_match(&e->ucb, catch_type, matched_objectpp);
   949 }
   950 #endif
   951 
   952 
   953 #endif /* arm_exceptions_throw_c */
   954 #ifdef arm_exceptions_rethrow_c
   955 
   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.
   959  */
   960 
   961 extern "C" WEAKDECL _Unwind_Reason_Code _Unwind_RaiseException(UCB *ucbp);
   962 
   963 #pragma exceptions_unwind
   964 
   965 void __cxa_rethrow(void)
   966 {
   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;
   970   bool foreign;
   971 
   972   // Must call terminate here if no such exception
   973   if (ep == NULL) NAMES::call_terminate_handler(NULL);
   974 
   975   UCB *ucbp = &ep->ucb;
   976 
   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.
   980 
   981   ep->propagationCount++;
   982 
   983   // Now reraise, taking care with foreign exceptions
   984 
   985   foreign = NAMES::is_foreign_exception(ucbp);
   986   if (foreign) {
   987     // Indirect through the intermediate object to the foreign ucb
   988     ucbp = (UCB *)ep->exceptionType;
   989   } else {
   990     // Increment the uncaught C++ exceptions count
   991     g->uncaughtExceptions++;
   992   }
   993 
   994   // Tell debugger what's happening
   995 
   996   DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, foreign ? NULL : ep->exceptionType);
   997 
   998   // Initiate unwinding - if we get control back, call C++ routine terminate()
   999 
  1000   _Unwind_RaiseException(ucbp);
  1001 
  1002 #ifdef PRINTED_DIAGNOSTICS
  1003   printf("__cxa_rethrow: throw failed\n");
  1004 #endif
  1005 
  1006   __cxa_call_terminate(ucbp);
  1007 }
  1008 
  1009 #endif /* arm_exceptions_rethrow_c */
  1010 #ifdef arm_exceptions_foreign_c
  1011 
  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.
  1019  */
  1020 
  1021 __cxa_exception *NAMES::get_foreign_intermediary(__cxa_exception *head_ep, UCB *ucbp)
  1022 {
  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)
  1027       return head_ep;
  1028   }
  1029 
  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
  1038   return ep;
  1039 }
  1040 
  1041 
  1042 #endif /* arm_exceptions_foreign_c */
  1043 #ifdef arm_exceptions_cleanup_c
  1044 
  1045 bool __cxa_begin_cleanup(UCB *ucbp)
  1046 {
  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.
  1058 
  1059   __cxa_eh_globals *g = __cxa_get_globals();
  1060   __cxa_exception *ep;
  1061 
  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
  1065   } else {
  1066     ep = ucbp_to_ep(ucbp);
  1067   }
  1068 
  1069   if (ep->propagationCount == 1) {
  1070     // Insert into chain
  1071     ep->nextPropagatingException = g->propagatingExceptions;
  1072     g->propagatingExceptions = ep;
  1073   }
  1074 
  1075   return true;
  1076 }
  1077 
  1078 
  1079 // Helper function for __cxa_end_cleanup
  1080 
  1081 extern "C" UCB * __ARM_cxa_end_cleanup(void)
  1082 {
  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.
  1088 
  1089   __cxa_eh_globals *g = __cxa_get_globals();
  1090   __cxa_exception *ep = g->propagatingExceptions;
  1091 
  1092   if (ep == NULL) terminate();
  1093 
  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);
  1103     } else {
  1104       ep->propagationCount--;
  1105     }
  1106   } else {
  1107     // Not foreign
  1108     if (ep->propagationCount == 1) { // logically in chain once - so unchain
  1109       g->propagatingExceptions = ep->nextPropagatingException;
  1110     }
  1111   }
  1112   return ucbp;
  1113 }
  1114 
  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.
  1118 
  1119 __asm void __cxa_end_cleanup(void) {
  1120   extern __ARM_cxa_end_cleanup;
  1121   extern _Unwind_Resume WEAKASMDECL;
  1122 
  1123 #ifdef __thumb
  1124   preserve8;                   // This is preserve8 (ARM assembler heuristics are inadequate)
  1125   push {r1-r7};
  1126   mov r2, r8;
  1127   mov r3, r9;
  1128   mov r4, r10;
  1129   mov r5, r11;
  1130   push {r1-r5};
  1131   bl __ARM_cxa_end_cleanup;    // returns UCB address in r0
  1132   pop {r1-r5};
  1133   mov r8, r2;
  1134   mov r9, r3;
  1135   mov r10, r4;
  1136   mov r11, r5;
  1137   pop {r1-r7};
  1138   bl _Unwind_Resume;           // won't return
  1139 #else
  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
  1144 #endif
  1145 }
  1146 
  1147 
  1148 #endif /* arm_exceptions_cleanup_c */
  1149 #ifdef arm_exceptions_catchsemantics_c
  1150 
  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.
  1155  */
  1156 
  1157 void NAMES::eh_catch_semantics(UCB *ucbp)
  1158 {
  1159   __cxa_eh_globals *g = __cxa_get_globals();
  1160   __cxa_exception *ep;
  1161 
  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);
  1168   } else {
  1169     // Not foreign
  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--;
  1175   }
  1176 
  1177   // Common code for our EO's, and foreign ones where we work on the intermediate EO
  1178 
  1179   // Increment the handler count for this exception object
  1180   ep->handlerCount++;
  1181 
  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)
  1184 
  1185   if (ep->nextCaughtException == NULL) {
  1186     ep->nextCaughtException = g->caughtExceptions;
  1187     g->caughtExceptions = ep;
  1188   }
  1189 }
  1190 
  1191 
  1192 #endif /* arm_exceptions_catchsemantics_c */
  1193 #ifdef arm_exceptions_begincatch_c
  1194 
  1195 void *__cxa_begin_catch(UCB *ucbp)
  1196 {
  1197   void *match = (void *)ucbp->barrier_cache.bitpattern[0]; // The matched object, if any
  1198 
  1199   // Update the data structures
  1200 
  1201   NAMES::eh_catch_semantics(ucbp);
  1202 
  1203   // Tell the unwinder the exception propagation has finished,
  1204   // and return the object pointer
  1205 
  1206   _Unwind_Complete(ucbp);
  1207   return match;
  1208 }
  1209 
  1210 
  1211 #endif /* arm_exceptions_begincatch_c */
  1212 #ifdef arm_exceptions_endcatch_c
  1213 
  1214 #pragma exceptions_unwind
  1215 
  1216 void __cxa_end_catch(void)
  1217 {
  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;
  1221 
  1222   if (ep == NULL) terminate();
  1223 
  1224   // Rethrow in progress?
  1225 
  1226   bool object_being_rethrown = ep->propagationCount != 0;
  1227 
  1228   // Decrement the handler count for this exception object
  1229   ep->handlerCount--;
  1230 
  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.
  1237 
  1238   if (ep->handlerCount == 0) {
  1239     void *eop = (void *)(ep + 1);
  1240     UCB *ucbp = &ep->ucb;
  1241     bool foreign = NAMES::is_foreign_exception(ucbp);
  1242 
  1243     // Unstack it from the caught exceptions stack - it is guaranteed to be top item.
  1244     g->caughtExceptions = ep->nextCaughtException;
  1245 
  1246     if (foreign) {
  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);
  1250     } else {
  1251       ep->nextCaughtException = NULL;  // So __cxa_begin_catch knows it isn't in the chain
  1252     }
  1253 
  1254     // Now destroy the exception object if it's no longer needed
  1255     if (!object_being_rethrown) {
  1256       if (foreign) {
  1257 
  1258 	// Notify the foreign language, if it so requested
  1259 	if (ucbp->exception_cleanup != NULL)
  1260 	  (ucbp->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, ucbp);
  1261 
  1262       } else {
  1263 
  1264         // One of our objects: do C++-specific semantics
  1265 
  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
  1270 	  try {
  1271 	    (ep->exceptionDestructor)(eop);
  1272 	  } catch(...) {
  1273 	    // Free the memory and reraise
  1274 	    __cxa_free_exception(eop);
  1275 	    throw;
  1276 	  }
  1277 #else
  1278 	  (ep->exceptionDestructor)(eop);
  1279 #endif
  1280 	}
  1281 	// Dtor (if there was one) didn't throw. Free the memory.
  1282 	__cxa_free_exception(eop);
  1283       }  // !foreign
  1284     }  // !object_being_rethrown
  1285   }  // ep->handlerCount == 0
  1286 }
  1287 
  1288 
  1289 #endif /* arm_exceptions_endcatch_c */
  1290 #ifdef arm_exceptions_bad_typeid_c
  1291 
  1292 #pragma exceptions_unwind
  1293 
  1294 void __cxa_bad_typeid(void)
  1295 {
  1296   throw std::bad_typeid();
  1297 }
  1298 
  1299 
  1300 #endif /* arm_exceptions_bad_typeid_c */
  1301 #ifdef arm_exceptions_bad_cast_c
  1302 
  1303 #pragma exceptions_unwind
  1304 
  1305 void __cxa_bad_cast(void)
  1306 {
  1307   throw std::bad_cast();
  1308 }
  1309 
  1310 
  1311 #endif /* arm_exceptions_bad_cast_c */