kernel/eka/compsupp/rvct2_1/aehabi/cppsemantics.cpp
changeset 266 0008ccd16016
parent 259 57b9594f5772
child 272 70a6efdb753f
child 281 13fbfa31d2ba
--- a/kernel/eka/compsupp/rvct2_1/aehabi/cppsemantics.cpp	Thu Sep 02 21:54:16 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1311 +0,0 @@
-/* The C++ exceptions runtime support
- *
- * Copyright 2002-2003 ARM Limited.
- */
-/*
-  Licence
-
-  1. Subject to the provisions of clause 2, ARM hereby grants to LICENSEE a
-  perpetual, non-exclusive, nontransferable, royalty free, worldwide licence
-  to use this Example Implementation of Exception Handling solely for the
-  purpose of developing, having developed, manufacturing, having
-  manufactured, offering to sell, selling, supplying or otherwise
-  distributing products which comply with the Exception Handling ABI for the
-  ARM Architecture specification. All other rights are reserved to ARM or its
-  licensors.
-
-  2. THIS EXAMPLE IMPLEMENTATION OF EXCEPTION HANDLING  IS PROVIDED "AS IS"
-  WITH NO WARRANTIES EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED
-  TO ANY WARRANTY OF SATISFACTORY QUALITY, MERCHANTABILITY, NONINFRINGEMENT
-  OR FITNESS FOR A PARTICULAR PURPOSE.
-*/
-/*
- * RCS $Revision: 1.29.2.1 $
- * Checkin $Date: 2004/01/20 15:11:16 $
- * Revising $Author: achapman $
- */
-
-/* This source file is compiled automatically by ARM's make system into
- * multiple object files. The source regions constituting object file
- * xxx.o are delimited by ifdef xxx_c / endif directives.
- *
- * The source regions currently marked are:
- * arm_exceptions_globs_c
- * arm_exceptions_mem_c
- * arm_exceptions_uncaught_c
- * arm_exceptions_terminate_c
- * arm_exceptions_setterminate_c
- * arm_exceptions_unexpected_c
- * arm_exceptions_setunexpected_c
- * arm_exceptions_support_c
- * arm_exceptions_callterm_c
- * arm_exceptions_callunex_c
- * arm_exceptions_currenttype_c
- * arm_exceptions_alloc_c
- * arm_exceptions_free_c
- * arm_exceptions_throw_c
- * arm_exceptions_rethrow_c
- * arm_exceptions_foreign_c
- * arm_exceptions_cleanup_c
- * arm_exceptions_begincatch_c
- * arm_exceptions_endcatch_c
- * arm_exceptions_bad_typeid_c
- * arm_exceptions_bad_cast_c
- */
-
-#include <string.h>
-#include <typeinfo>
-#include <exception>
-#include <new>
-// Environment:
-#include "unwind_env.h"
-// Language-independent unwinder declarations:
-#include "unwinder.h"
-
-/* By default, none of these routines are unwindable: */
-#pragma noexceptions_unwind
-
-/* For brevity: */
-
-typedef _Unwind_Control_Block UCB;
-
-using std::terminate_handler;
-using std::unexpected_handler;
-using std::terminate;
-using std::unexpected;
-using std::type_info;
-
-/* Redeclare these interface routines as weak, so using them does not
- * pull in the unwind library. We only want the unwind library if
- * someone throws (or raises an exception from some other language).
- */
-WEAKDECL NORETURNDECL void _Unwind_Resume(UCB *);
-WEAKDECL void _Unwind_Complete(UCB *);
-
-/* Diagnostics:
- * Define DEBUG to get extra interfaces which assist debugging this functionality.
- * Define PRINTED_DIAGNOSTICS for printed diagnostics.
- */
-#ifdef DEBUG
-#define PRINTED_DIAGNOSTICS
-#endif
-
-#ifdef PRINTED_DIAGNOSTICS
-extern "C" int printf(const char *, ...);
-#endif
-
-/* --------- "Exceptions_class" string for our implementation: --------- */
-
-#define EXCEPTIONS_CLASS_SIZE 8
-#define ARMCPP_EXCEPTIONS_CLASS "ARM\0C++\0"
-
-
-/* --------- Exception control object: --------- */
-
-// Type __cxa_exception is the combined C++ housekeeping (LEO) and UCB.
-// It will be followed by the user exception object, hence must ensure
-// the latter is aligned on an 8 byte boundary.
-
-struct __cxa_exception {
-  const type_info *exceptionType;       // RTTI object describing the type of the exception
-  void *(*exceptionDestructor)(void *); // Destructor for the exception object (may be NULL)
-  unexpected_handler unexpectedHandler; // Handler in force after evaluating throw expr
-  terminate_handler terminateHandler;   // Handler in force after evaluating throw expr
-  __cxa_exception *nextCaughtException; // Chain of "currently caught" c++ exception objects
-  uint32_t handlerCount;                // Count of how many handlers this EO is "caught" in
-  __cxa_exception *nextPropagatingException; // Chain of objects saved over cleanup
-  uint32_t propagationCount;            // Count of live propagations (throws) of this EO
-  UCB ucb;                              // Forces alignment of next item to 8-byte boundary
-};
-
-
-/* --------- Control "globals": --------- */
-
-// We do this by putting all the thread-specific "globals" into a single
-// area of store, which we allocate space for dynamically.
-// We don't define a constructor for this; see comments with __cxa_get_globals.
-
-typedef void (*handler)(void);
-
-struct __cxa_eh_globals {
-  uint32_t uncaughtExceptions;               // counter
-  unexpected_handler unexpectedHandler;      // per-thread handler
-  terminate_handler terminateHandler;        // per-thread handler
-  bool implementation_ever_called_terminate; // true if it ever did
-  handler call_hook;     // transient field to tell terminate/unexpected which hook to call
-  __cxa_exception *caughtExceptions;         // chain of "caught" exceptions
-  __cxa_exception *propagatingExceptions;    // chain of "propagating" (in cleanup) exceptions
-  void *emergency_buffer;                    // emergency buffer for when rest of heap full
-};
-
-
-/* ---------- Entry points: ---------- */
-
-/* There is a little type-delicacy required here as __cxa_throw takes a
- * function pointer. Setting aside the problem of not being able to form
- * a pointer to a destructor in C++, if we simply say extern "C" here
- * then the function pointer will also have C linkage and will be a
- * pointer to a C function. This causes problems when __cxa_throw is
- * defined (unless we repeat the extern "C" at the definition site) because
- * the fnptr in the definition gets C++ linkage, hence that __cxa_throw has
- * a different signature to the declared one, and so the function we wanted
- * doesn't get defined at all.
- * Maybe it should just take a void * but this seems more honest.
- */
-
-typedef void *(*cppdtorptr)(void *);
-
-extern "C" {
-
-  // Protocol routines called directly from application code
-
-  void *__cxa_allocate_exception(size_t size);
-  void __cxa_free_exception(void *);
-  WEAKDECL void __cxa_throw(void *, const type_info *, cppdtorptr);
-  void __cxa_rethrow(void);
-  void *__cxa_begin_catch(UCB *);
-  void __cxa_end_catch(void);
-  void __cxa_end_cleanup(void);
-  const type_info *__cxa_current_exception_type(void);
-
-  // Protocol routines usually called only by the personality routine(s).
-
-  void __cxa_call_terminate(UCB *);
-  void __cxa_call_unexpected(UCB *);
-  bool __cxa_begin_cleanup(UCB *);
-  bool __cxa_type_match(UCB *, const std::type_info *, void **);
-
-  // Auxilliary routines
-
-  __cxa_eh_globals *__cxa_get_globals(void);
-  void __cxa_bad_typeid(void);
-  void __cxa_bad_cast(void);
-
-  // Emergency memory buffer management routines
-
-  void *__ARM_exceptions_buffer_init(void);
-  void *__ARM_exceptions_buffer_allocate(void *, size_t);
-  void *__ARM_exceptions_buffer_free(void *, void *);
-}
-
-
-// Support routines
-
-#define NAMES __ARM
-namespace NAMES {
-  void default_unexpected_handler(void);
-  void call_terminate_handler(UCB *);
-  void eh_catch_semantics(UCB *);
-  bool is_foreign_exception(UCB *);
-  bool same_exceptions_class(const void *, const void *);
-  __cxa_exception *get_foreign_intermediary(__cxa_exception *, UCB *);
-}
-
-// Macro: convert ucb pointer to __cxa_exception pointer
-
-#define ucbp_to_ep(UCB_P) ((__cxa_exception *)((char *)(UCB_P) - offsetof(__cxa_exception, ucb)))
-
-
-#ifdef arm_exceptions_globs_c
-
-/* --------- Allocating and retrieving "globals": --------- */
-
-// The exception-handling globals should be allocated per-thread.
-// This is done here assuming the existance of a zero-initialised void*
-// pointer location obtainable by the macro EH_GLOBALS.
-
-// Default terminate handler:
-
-static void __default_terminate_handler(void) {
-  abort();
-}
-
-// If std::unexpected() is in the image, include a default handler for it:
-namespace NAMES { WEAKDECL void default_unexpected_handler(void); }
-
-// If this symbol is present, allocate an emergency buffer.
-// As we aren't allowed static data, make it a function
-extern "C" WEAKDECL void __ARM_exceptions_buffer_required(void);
-
-
-// __cxa_eh_globals returns the per-thread memory. There are several complications,
-// all of which relate to not touching the exceptions system while trying to
-// initialise it:
-// 1) We can't obtain memory by calling new or nothrow new as both of these use
-//    exceptions internally, so we must use malloc
-// 2) We choose not to initialise the memory via placement new and a constructor,
-//    since placement new is declared with an empty function exception specification,
-//    which causes more of the exceptions system to always be pulled in.
-// 3) We can't call terminate, as terminate looks in the memory we are trying to
-//    allocate.
-
-__cxa_eh_globals *__cxa_get_globals(void)
-{
-  __cxa_eh_globals *this_thread_globals = (__cxa_eh_globals *)(EH_GLOBALS);
-  if (this_thread_globals == NULL) {
-
-    // First call
-    // Obtain some memory: this is thread-safe provided malloc is.
-    this_thread_globals = (__cxa_eh_globals *)malloc(sizeof(__cxa_eh_globals));
-    if (this_thread_globals == NULL) abort(); // NOT terminate(), which calls this fn
-
-    // Save the pointer in the specially-provided location
-    EH_GLOBALS = this_thread_globals;
-
-    // Finally initialise the memory by hand
-    this_thread_globals->uncaughtExceptions = 0;
-    this_thread_globals->unexpectedHandler = NAMES::default_unexpected_handler;
-    this_thread_globals->terminateHandler = __default_terminate_handler;
-    this_thread_globals->implementation_ever_called_terminate = false;
-    this_thread_globals->call_hook = NULL;
-    this_thread_globals->caughtExceptions = NULL;
-    this_thread_globals->propagatingExceptions = NULL;
-    if (&__ARM_exceptions_buffer_required == NULL)
-      this_thread_globals->emergency_buffer = NULL;
-    else
-      this_thread_globals->emergency_buffer = __ARM_exceptions_buffer_init();
-  }
-
-  return this_thread_globals;
-}
-
-
-#endif /* arm_exceptions_globs_c */
-#ifdef arm_exceptions_mem_c
-
-/* --------- Emergency memory: --------- */
-
-// It is possible to reserve memory for throwing bad_alloc when the heap
-// is otherwise full. The ARM implementation provides hooks to do this.
-// The default implementation reserves just enough space for a bad_alloc
-// object, so if memory is later exhausted bad_alloc can still be thrown.
-// Note there is no guarantee or requirement that the exception being
-// thrown is actually bad_alloc.
-
-// A usage flag and enough space for a bad_alloc exception control object
-
-struct emergency_eco {
-  __cxa_exception ep;
-  std::bad_alloc b;
-};
-
-struct emergency_buffer {
-  bool inuse;
-  struct emergency_eco eco;
-};
-
-// Initialiser
-void* __ARM_exceptions_buffer_init(void)
-{
-  emergency_buffer *buffer = (emergency_buffer *)malloc(sizeof(emergency_buffer));
-  if (buffer == NULL) return NULL;
-  buffer->inuse = false;
-  return buffer;
-}
-
-// Allocator
-void *__ARM_exceptions_buffer_allocate(void *buffer, size_t size)
-{
-  emergency_buffer *b = (emergency_buffer *)buffer;
-  if (size > sizeof(emergency_eco) || b == NULL || b->inuse) return NULL;
-  b->inuse = true;
-  return &b->eco;
-}
-
-// Deallocator: Must return non-NULL if and only if it recognises
-// and releases the supplied object
-void *__ARM_exceptions_buffer_free(void *buffer, void *addr)
-{
-  emergency_buffer *b = (emergency_buffer *)buffer;
-  if (b == NULL || addr != &b->eco) return NULL;
-  b->inuse = false;
-  return b;
-}
-
-
-#endif /* arm_exceptions_mem_c */
-#ifdef arm_exceptions_uncaught_c
-
-/* ---- uncaught_exception() ---- */
-
-/* The EDG (and I think our) interpretation is that if the implementation
- * ever called terminate(), uncaught_exception() should return true.
- */
-
-bool std::uncaught_exception(void)
-{
-   __cxa_eh_globals *g = __cxa_get_globals();
-   return g->implementation_ever_called_terminate || g->uncaughtExceptions;
-}
-
-
-#endif /* arm_exceptions_uncaught_c */
-#ifdef arm_exceptions_terminate_c
-
-/* ---- terminate() etc ---- */
-
-/* The behaviour of terminate() must differ between calls by the
- * implementation and calls by the application. This is achieved by having the
- * implementation set call_hook immediately before the call to terminate().
- * The hook called by terminate() should terminate the program without
- * returning to the caller. There is no requirement for terminate() itself to
- * intercept throws.
- */
-
-void std::terminate(void)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-
-  if (g->call_hook != NULL) {
-    // Clear then call hook fn we were passed
-    handler call_hook = g->call_hook;
-    g->call_hook = NULL;
-    call_hook();
-  } else {
-    // Call global hook fn
-    g->terminateHandler();
-  }
-  // If hook fn returns:
-  abort();
-}
-
-
-#endif /* arm_exceptions_terminate_c */
-#ifdef arm_exceptions_setterminate_c
-
-terminate_handler std::set_terminate(terminate_handler h) throw()
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-  terminate_handler old = g->terminateHandler;
-  g->terminateHandler = h;
-  return old;
-}
-
-
-#endif /* arm_exceptions_setterminate_c */
-#ifdef arm_exceptions_unexpected_c
-
-/* ---- unexpected() etc ---- */
-/* Comments as per terminate() */
-
-void NAMES::default_unexpected_handler(void) {
-  terminate();
-}
-
-#pragma exceptions_unwind
-
-void std::unexpected(void)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-
-  if (g->call_hook != NULL) {
-    // Clear then call hook fn we were passed
-    handler call_hook = g->call_hook;
-    g->call_hook = NULL;
-    call_hook();
-  } else {
-    // Call global hook fn
-    g->unexpectedHandler();
-  }
-
-  // If hook fn returns:
-  abort();
-}
-
-
-#endif /* arm_exceptions_unexpected_c */
-#ifdef arm_exceptions_setunexpected_c
-
-unexpected_handler std::set_unexpected(unexpected_handler h) throw()
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-  unexpected_handler old = g->unexpectedHandler;
-  g->unexpectedHandler = h;
-  return old;
-}
-
-
-#endif /* arm_exceptions_setunexpected_c */
-#ifdef arm_exceptions_support_c
-
-/* ---------- Helper functions: ---------- */
-
-/* Two routines to determine whether two exceptions objects share a layout.
- * This is determined by checking whether the UCB exception_class members
- * are identical.
- * In principle we could use memcmp to perform this check (the code is
- * given below) but the check is quite frequent and so that is costly.
- * Therefore for efficiency we make use of the fact that the UCB is
- * word aligned, that the exception_class member is consequently
- * word aligned within it, and that we know the size of the member.
- * We take care elsewhere to only ever call the routines with pointers
- * to word-aligned addresses.
- */
-
-#if 0
-
-// Straightforward versions
-
-bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
-{
-  return memcmp(ec1, ec2, EXCEPTIONS_CLASS_SIZE) == 0; // identical
-}
-
-// One of our exception objects, or not?
-
-bool NAMES::is_foreign_exception(UCB *ucbp)
-{
-  return !NAMES::same_exceptions_class(&ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS);
-}
-
-#else
-
-// Faster versions
-
-bool NAMES::same_exceptions_class(const void *ec1, const void *ec2)
-{
-  uint32_t *ip1 = (uint32_t *)ec1;
-  uint32_t *ip2 = (uint32_t *)ec2;
-  return ip1[0] == ip2[0] && ip1[1] == ip2[1];
-}
-
-// One of our exception objects, or not?
-
-bool NAMES::is_foreign_exception(UCB *ucbp)
-{
-  // Need a word-aligned copy of the string
-  static const union {
-    const char s[EXCEPTIONS_CLASS_SIZE+1]; int dummy;
-  } is_foreign_exception_static = {ARMCPP_EXCEPTIONS_CLASS};
-  return !NAMES::same_exceptions_class(&ucbp->exception_class, &is_foreign_exception_static.s);
-}
-
-#endif
-
-
-#endif /* arm_exceptions_support_c */
-#ifdef arm_exceptions_callterm_c
-
-/* When the implementation wants to call terminate(), do the following:
- * Mark the object as "caught" so it can be rethrown.
- * Set the hook function for terminate() to call;
- * Mark the fact that terminate() has been called by the implementation;
- * We have to be careful - the implementation might encounter an error while
- * unwinding a foreign exception, and also it is possible this might be
- * called after failing to obtain a ucb.
- */
-
-void NAMES::call_terminate_handler(UCB *ucbp)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-
-  if (ucbp == NULL) {
-    // Call global hook
-    g->call_hook = g->terminateHandler;
-  } else {
-    // Extract the hook to call
-    if (NAMES::is_foreign_exception(ucbp)) {
-      // Someone else's
-      g->call_hook = g->terminateHandler;  // best we can do under the circumstances
-    } else {
-      // One of ours
-      __cxa_exception *ep = ucbp_to_ep(ucbp);
-      g->call_hook = ep->terminateHandler; // the one in force at the point of throw
-    }
-  }
-
-  g->implementation_ever_called_terminate = true;
-  terminate();
-  // never returns
-}
-
-
-void __cxa_call_terminate(UCB *ucbp)
-{
-  if (ucbp != NULL) // Record entry to (implicit) handler
-    __cxa_begin_catch(ucbp);
-
-  NAMES::call_terminate_handler(ucbp);
-  // never returns
-}
-
-
-#endif /* arm_exceptions_callterm_c */
-#ifdef arm_exceptions_callunex_c
-
-/* When the implementation wants to call unexpected(), do the following:
- * Mark the object as "caught" so it can be rethrown.
- * Set the hook function for unexpected() to call;
- * Call unexpected and trap any throw to make sure it is acceptable.
- * We have to be careful - the implementation might encounter an error while
- * unwinding a foreign exception.
- */
-
-#pragma exceptions_unwind
-
-void __cxa_call_unexpected(UCB *ucbp)
-{
-
-  // Extract data we will need from the barrier cache before
-  // anyone has a chance to overwrite it
-
-  uint32_t rtti_count = ucbp->barrier_cache.bitpattern[1];
-  uint32_t base = ucbp->barrier_cache.bitpattern[2];
-  uint32_t stride = ucbp->barrier_cache.bitpattern[3];
-  uint32_t rtti_offset_array_addr = ucbp->barrier_cache.bitpattern[4];
-
-  // Also get the globals here and the eop
-
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep = ucbp_to_ep(ucbp);
-
-#ifdef ARM_EXCEPTIONS_ENABLED
-  try {
-#endif
-
-    // Record entry to (implicit) handler
-
-    __cxa_begin_catch(ucbp);
-
-    // Now extract the hook to call
-
-    if (NAMES::is_foreign_exception(ucbp)) {
-      // Someone else's
-      g->call_hook = g->unexpectedHandler;  // best we can do under the circumstances
-    } else {
-      // One of ours
-      g->call_hook = ep->unexpectedHandler; // the one in force at the point of throw
-    }
-    unexpected();  // never returns normally, but might throw something
-
-#ifdef ARM_EXCEPTIONS_ENABLED
-  } catch (...) {
-
-    // Unexpected() threw. This requires some delicacy.
-    // There are 2 possibilities:
-    // i) rethrow of the same object
-    // ii) throw of a new object
-    // Unexpected() is an implicit handler, and we manually called
-    // __cxa_begin_catch on the ingoing object. We need to call
-    // __cxa_end_catch on that object and, if the object is no longer
-    // being handled (possible in case ii), this will cause its destruction.
-    // The wrinkle is that in case ii the object is not on top of the catch
-    // stack because we just caught something else.
-
-    // Get hold of what was thrown (which we just caught).
-
-    __cxa_exception *epnew = g->caughtExceptions;
-
-    // Call __cxa_end_catch on the original object, taking care with the catch chain
-
-    if (epnew == ep) {
-      // rethrow - easy & safe - object is at top of chain and handlercount > 1
-      __cxa_end_catch();
-    } else {
-      // not rethrow - unchain the top (new) object, clean up the next one,
-      // and put the top object back
-
-      // unchain
-      g->caughtExceptions = epnew->nextCaughtException;
-      // assert g->caughtExceptions == ep now
-      // Decrement its handlercount (this might call a dtor if the count goes to 0,
-      // and the dtor might throw - if it does, just give up)
-      try {
-	__cxa_end_catch();
-      } catch(...) {
-	terminate();
-      }
-      // Chain back in
-      epnew->nextCaughtException = g->caughtExceptions;
-      g->caughtExceptions = epnew;
-    }
-
-    // See whether what was thrown is permitted, and in passing
-    // see if std::bad_exception is permitted
-
-    bool bad_exception_permitted = false;
-    uint32_t i;
-    for (i = 0; i < rtti_count; i++) {
-      void *matched_object;
-      const type_info *fnspec = (const type_info *)(*(uint32_t *)rtti_offset_array_addr + base);
-      if (__cxa_type_match(&(epnew->ucb), fnspec, &matched_object)) {
-#ifdef PRINTED_DIAGNOSTICS
-	printf("__cxa_call_unexpected: fnspec matched\n");
-#endif
-	throw; // got a match - propagate it
-      }
-      if (&typeid(std::bad_exception) == fnspec)
-	bad_exception_permitted = true;
-      rtti_offset_array_addr += stride;
-    }
-
-    // There was no match...
-    if (bad_exception_permitted) throw std::bad_exception(); // transmute
-
-    // Otherwise call epnew's terminate handler
-    NAMES::call_terminate_handler(&epnew->ucb);
-  }
-#endif
-}
-
-
-#endif /* arm_exceptions_callunex_c */
-#ifdef arm_exceptions_currenttype_c
-
-/* Yield the type of the currently handled exception, or null if none or the
- * object is foreign.
- */
-
-const type_info *__cxa_current_exception_type(void)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep = g->caughtExceptions;
-  if (ep == NULL || NAMES::is_foreign_exception(&ep->ucb)) return NULL;
-  return ep->exceptionType;
-}
-
-
-#endif /* arm_exceptions_currenttype_c */
-#ifdef arm_exceptions_alloc_c
-
-/* Allocate store for controlling an exception propagation */
-
-void *__cxa_allocate_exception(size_t size)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-
-  // Allocate store for a __cxa_exception header and the EO.
-  // Allocated store should be thread-safe and persistent, and must do
-  // something sensible if the allocation fails
-
-  size_t total_size = size + sizeof(__cxa_exception);
-  __cxa_exception *ep = (__cxa_exception *)malloc(total_size);
-  if (ep == NULL) {
-    // Try the emergency memory pool
-    ep = (__cxa_exception *)__ARM_exceptions_buffer_allocate(g->emergency_buffer, total_size);
-    if (ep == NULL) NAMES::call_terminate_handler(NULL);
-  }
-
-  UCB *ucbp = &ep->ucb;
-
-  // Initialise the UCB
-
-  memcpy(ucbp->exception_class, ARMCPP_EXCEPTIONS_CLASS, EXCEPTIONS_CLASS_SIZE);
-  ucbp->exception_cleanup = NULL; /* initialise properly before throwing */
-  ucbp->unwinder_cache.reserved1 = 0; /* required to do this */
-
-  // Initialise parts of the LEO, in case copy-construction of the EO results
-  // in a need to call terminate (via __cxa_call_terminate)
-
-  ep->handlerCount = 0;                         // Not in any handlers
-  ep->nextCaughtException = NULL;               // Not in any handlers
-  ep->nextPropagatingException = NULL;          // Not saved over cleanup
-  ep->propagationCount = 0;                     // Not propagating
-  ep->terminateHandler = g->terminateHandler;   // Cache current terminate handler
-  ep->unexpectedHandler = g->unexpectedHandler; // Cache current unexpected handler
-
-  // Return pointer to the EO
-
-  return ep + 1;
-}
-
-
-#endif /* arm_exceptions_alloc_c */
-#ifdef arm_exceptions_free_c
-
-/* Free store allocated by __cxa_allocate_exception */
-
-void __cxa_free_exception(void *eop)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-  char *ep = (char *)eop - sizeof(__cxa_exception);
-  if (__ARM_exceptions_buffer_free(g->emergency_buffer, ep)) return;
-  free(ep);
-}
-
-
-#endif /* arm_exceptions_free_c */
-#ifdef arm_exceptions_throw_c
-
-/* This routine is called when a foreign runtime catches one of our exception
- * objects and then exits its catch by a means other than rethrow.
- * We should clean it up as if we had caught it ourselves.
- */
-
-static void external_exception_termination(_Unwind_Reason_Code c, UCB *ucbp)
-{
-  NAMES::eh_catch_semantics(ucbp);
-  __cxa_end_catch();
-}
-
-
-/* Initiate a throw */
-
-#pragma push
-#pragma exceptions_unwind
-
-void __cxa_throw(void *eop, const type_info *t, cppdtorptr d)
-{
-  __cxa_exception *ep = (__cxa_exception *)((char *)eop - sizeof(__cxa_exception));
-  UCB *ucbp = &ep->ucb;
-
-  // Initialise the remaining LEO and UCB fields not done by __cxa_allocate_exception
-
-  ucbp->exception_cleanup = external_exception_termination;
-  ep->exceptionType = t;
-  ep->exceptionDestructor = d;
-  ep->propagationCount = 1;      // Propagating by 1 throw
-
-  // Increment the uncaught C++ exceptions count
-
-  __cxa_eh_globals *g = __cxa_get_globals();
-  g->uncaughtExceptions++;
-
-  // Tell debugger what's happening
-
-  DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, t);
-
-  // Initiate unwinding - if we get control back, call C++ routine terminate()
-
-  _Unwind_RaiseException(ucbp);
-
-#ifdef PRINTED_DIAGNOSTICS
-  printf("__cxa_throw: throw failed\n");
-#endif
-
-  __cxa_call_terminate(ucbp);
-}
-
-#pragma pop
-
-/* ----- Type matching: ----- */
-
-/* This is located here so that (in ARM's implementation) it is only retained in
- * an image if the application itself throws.
- */
-
-/* Type matching functions.
- * C++ DR126 says the matching rules for fnspecs are intended to be the same as
- * those for catch:
- * "A function is said to allow an exception of type E if its exception-specification
- * contains a type T for which a handler of type T would be a match (15.3 except.handle)
- * for an exception of type E."
- * Thus we have a single type matching rule.
- */
-
-/* Helper macros: */
-
-#define CV_quals_of_pointee(P) (((const abi::__pbase_type_info *)(P))->__flags & \
-		                (abi::__pbase_type_info::__const_mask | \
-		                 abi::__pbase_type_info::__volatile_mask))
-
-#define is_const(QUALS) (((QUALS) & abi::__pbase_type_info::__const_mask) != 0)
-
-#define any_qualifier_missing(TEST_QUALS, REF_QUALS) ((~(TEST_QUALS) & (REF_QUALS)) != 0)
-
-/* A routine is required for derived class to base class conversion.
- * This is obtained via a macro definition DERIVED_TO_BASE_CONVERSION
- * in unwind_env.h.
- */
-
-/* External entry point:
- * Type check the c++ rtti object for compatibility against the type of
- * the object containing the ucb. Return a pointer to the matched object
- * (possibly a non-leftmost baseclass of the exception object)
- */
-bool __cxa_type_match(UCB *ucbp, const type_info *match_type, void **matched_objectpp)
-{
-  if (NAMES::is_foreign_exception(ucbp))
-    return false;
-
-  __cxa_exception *ep = ucbp_to_ep(ucbp);
-  const type_info *throw_type = ep->exceptionType;
-  bool previous_qualifiers_include_const = true; // for pointer qualification conversion
-  unsigned int pointer_depth = 0;
-  void *original_objectp = ep + 1;
-  void *current_objectp = original_objectp;
-
-  for (;;) {
-
-    // Match if identical
-
-    if (throw_type == match_type) {
-      *matched_objectpp = original_objectp;
-#ifdef PRINTED_DIAGNOSTICS
-      printf("__cxa_type_match: success (exact match after any ptrs)\n");
-#endif
-      return true;
-    }
-
-    // Fail if one is a pointer and the other isn't
-
-    const type_info *type_throw_type = &typeid(*throw_type);
-    const type_info *type_match_type = &typeid(*match_type);
-
-    if ((type_throw_type == &typeid(abi::__pointer_type_info) ||
-	 type_match_type == &typeid(abi::__pointer_type_info)) &&
-	type_throw_type != type_match_type) {
-#ifdef PRINTED_DIAGNOSTICS
-      printf("__cxa_type_match: failed (mixed ptr/non-ptr)\n");
-#endif
-      return false;
-    }
-
-    // Both are pointers or neither is
-    if (type_throw_type == &typeid(abi::__pointer_type_info)) {
-      // Both are pointers
-#ifdef PRINTED_DIAGNOSTICS
-      printf("__cxa_type_match: throwing a ptr\n");
-#endif
-      pointer_depth++;
-      // Check match_type is at least as CV-qualified as throw_type
-      unsigned int match_quals = CV_quals_of_pointee(match_type);
-      unsigned int throw_quals = CV_quals_of_pointee(throw_type);
-      if (any_qualifier_missing(match_quals, throw_quals)) {
-#ifdef PRINTED_DIAGNOSTICS
-	printf("__cxa_type_match: failed (missing qualifiers)\n");
-#endif
-	return false;
-      }
-      // If the match type has additional qualifiers not found in the
-      // throw type, any previous qualifiers must have included const
-      if (any_qualifier_missing(throw_quals, match_quals) &&
-	  !previous_qualifiers_include_const) {
-#ifdef PRINTED_DIAGNOSTICS
-	printf("__cxa_type_match: failed (not all qualifiers have const)\n");
-#endif
-	return false;
-      }
-      if (!is_const(match_quals))
-	previous_qualifiers_include_const = false;
-      throw_type = ((const abi::__pbase_type_info *)throw_type)->__pointee;
-      match_type = ((const abi::__pbase_type_info *)match_type)->__pointee;
-      if (current_objectp != NULL)
-        current_objectp = *(void **)current_objectp;
-      continue;
-    }
-
-    // Neither is a pointer now but qualification conversion has been done.
-    // See if pointer conversion on the original was possible.
-    // T* will match void*
-
-    if (pointer_depth == 1 && match_type == &typeid(void)) {
-      *matched_objectpp = original_objectp;
-#ifdef PRINTED_DIAGNOSTICS
-      printf("__cxa_type_match: success(conversion to void *)\n");
-#endif
-      return true;
-    }
-
-    // Else if we have 2 class types, a derived class is matched by a
-    // non-ambiguous public base class (perhaps not a leftmost one).
-    // __si_class_type_info and __vmi_class_type_info are classes with bases.
-
-    void *matched_base_p;
-
-    if (pointer_depth < 2 &&
-	(type_throw_type == &typeid(abi::__si_class_type_info) ||
-	 type_throw_type == &typeid(abi::__vmi_class_type_info))) {
-      if (DERIVED_TO_BASE_CONVERSION(current_objectp, &matched_base_p,
-				     throw_type, match_type)) {
-#ifdef PRINTED_DIAGNOSTICS
-	printf("__cxa_type_match: success (matched base 0x%x of 0x%x%s, thrown object 0x%x)\n",
-	       matched_base_p, current_objectp,
-	       pointer_depth == 0 ? "" : " via ptr",
-	       original_objectp);
-#endif
-	*matched_objectpp = pointer_depth == 0 ? matched_base_p : original_objectp;
-	return true;
-      } else {
-#ifdef PRINTED_DIAGNOSTICS
-	printf("__cxa_type_match: failed (derived to base failed)\n");
-#endif
-	return false;
-      }
-    }
-
-#ifdef PRINTED_DIAGNOSTICS
-    printf("__cxa_type_match: failed (types simply differ)\n");
-#endif
-    return false;
-  } /* for */
-}
-
-
-/* For debugging purposes: */
-#ifdef DEBUG
-extern "C" bool debug__cxa_type_match(void *objptr,
-				      const type_info *throw_type,
-				      const type_info *catch_type,
-				      void **matched_objectpp)
-{
-  /* Create enough of an exception object that the type-matcher can run, then
-   * check the type. Objptr is expected to be the result of a call to
-   * __cxa_allocate_exception, which has then been copy-constructed.
-   */
-  __cxa_exception *e = ((__cxa_exception *)objptr) - 1;
-  e->exceptionType = throw_type;
-  return __cxa_type_match(&e->ucb, catch_type, matched_objectpp);
-}
-#endif
-
-
-#endif /* arm_exceptions_throw_c */
-#ifdef arm_exceptions_rethrow_c
-
-/* Redeclare _Unwind_RaiseException as weak (if WEAKDECL is defined
- * appropriately) so the use from __cxa_rethrow does not on its own
- * force the unwind library to be loaded.
- */
-
-extern "C" WEAKDECL _Unwind_Reason_Code _Unwind_RaiseException(UCB *ucbp);
-
-#pragma exceptions_unwind
-
-void __cxa_rethrow(void)
-{
-  // Recover the exception object - it is the most recent caught exception object
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep = g->caughtExceptions;
-  bool foreign;
-
-  // Must call terminate here if no such exception
-  if (ep == NULL) NAMES::call_terminate_handler(NULL);
-
-  UCB *ucbp = &ep->ucb;
-
-  // Mark the object as being propagated by throw, preventing multiple
-  // propagation and also permitting __cxa_end_catch to do the right
-  // thing when it is called from the handler's cleanup.
-
-  ep->propagationCount++;
-
-  // Now reraise, taking care with foreign exceptions
-
-  foreign = NAMES::is_foreign_exception(ucbp);
-  if (foreign) {
-    // Indirect through the intermediate object to the foreign ucb
-    ucbp = (UCB *)ep->exceptionType;
-  } else {
-    // Increment the uncaught C++ exceptions count
-    g->uncaughtExceptions++;
-  }
-
-  // Tell debugger what's happening
-
-  DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_STARTING, foreign ? NULL : ep->exceptionType);
-
-  // Initiate unwinding - if we get control back, call C++ routine terminate()
-
-  _Unwind_RaiseException(ucbp);
-
-#ifdef PRINTED_DIAGNOSTICS
-  printf("__cxa_rethrow: throw failed\n");
-#endif
-
-  __cxa_call_terminate(ucbp);
-}
-
-#endif /* arm_exceptions_rethrow_c */
-#ifdef arm_exceptions_foreign_c
-
-/* During catch and cleanup, foreign exception objects are dealt with using
- * an intermediate __cxa_exception block in the appropriate exceptions
- * chain. This block has the same exception_class as the real foreign
- * ucb, and points to the real ucb via the intermediate block's exceptionType
- * field. This helper function checks whether it has been passed such an
- * intermediate block and sets one up if not. Only call it when the UCB
- * is known to belong to a foreign exception.
- */
-
-__cxa_exception *NAMES::get_foreign_intermediary(__cxa_exception *head_ep, UCB *ucbp)
-{
-  if (head_ep != NULL) {
-    UCB *head_ucbp = &head_ep->ucb;
-    if (NAMES::same_exceptions_class(&head_ucbp->exception_class, &ucbp->exception_class) &&
-	(UCB *)head_ep->exceptionType == ucbp)
-      return head_ep;
-  }
-
-  // Create an intermediate block. Only initialise as much as necessary
-  __cxa_exception *ep = ((__cxa_exception *)__cxa_allocate_exception(0)) - 1;
-  UCB *new_ucbp = &ep->ucb;
-  memcpy(new_ucbp->exception_class, ucbp->exception_class, EXCEPTIONS_CLASS_SIZE);
-  ep->propagationCount = 0;                     // Not propagating
-  ep->handlerCount = 0;                         // Not handled
-  ep->nextCaughtException = NULL;               // Not in chain
-  ep->exceptionType = (const type_info *)ucbp;  // The foreign UCB
-  return ep;
-}
-
-
-#endif /* arm_exceptions_foreign_c */
-#ifdef arm_exceptions_cleanup_c
-
-bool __cxa_begin_cleanup(UCB *ucbp)
-{
-  // Indicate that a cleanup is about to start.
-  // Save the exception pointer over the cleanup for recovery later, using a chain.
-  // If we allowed the exception to be rethrown in a cleanup, then
-  // the object might appear multiple times at the head of this chain,
-  // and the propagationCount could be used to track this - at this point,
-  // the object is logically in the chain propagationCount-1 times, and
-  // physically 0 or 1 times. Thus if propagationCount == 1 we should insert
-  // it physically. A similar rule is used for physical removal in
-  //__cxa_end_cleanup.
-  // Foreign exceptions are handled via an intermediate __cxa_exception object
-  // in a similar way as __cxa_begin_catch.
-
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep;
-
-  if (NAMES::is_foreign_exception(ucbp)) {
-    ep = NAMES::get_foreign_intermediary(g->propagatingExceptions, ucbp);
-    ep->propagationCount++;  // Indicate one (or one additional) propagation
-  } else {
-    ep = ucbp_to_ep(ucbp);
-  }
-
-  if (ep->propagationCount == 1) {
-    // Insert into chain
-    ep->nextPropagatingException = g->propagatingExceptions;
-    g->propagatingExceptions = ep;
-  }
-
-  return true;
-}
-
-
-// Helper function for __cxa_end_cleanup
-
-extern "C" UCB * __ARM_cxa_end_cleanup(void)
-{
-  // Recover and return the currently propagating exception (from the
-  // head of the propagatingExceptions chain).
-  // propagationCount at this moment is a logical count of how many times the
-  // item is in the chain so physically unchain it when this count is 1.
-  // Foreign exceptions use an intermediary.
-
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep = g->propagatingExceptions;
-
-  if (ep == NULL) terminate();
-
-  UCB *ucbp = &ep->ucb;
-  if (NAMES::is_foreign_exception(ucbp)) {
-    // Get the foreign ucb
-    ucbp = (UCB *)ep->exceptionType;
-    if (ep->propagationCount == 1) {
-      // Free the intermediate ucb (see description in __cxa_begin_catch)
-      void *eop = (void *)(ep + 1);
-      g->propagatingExceptions = ep->nextPropagatingException;
-      __cxa_free_exception(eop);
-    } else {
-      ep->propagationCount--;
-    }
-  } else {
-    // Not foreign
-    if (ep->propagationCount == 1) { // logically in chain once - so unchain
-      g->propagatingExceptions = ep->nextPropagatingException;
-    }
-  }
-  return ucbp;
-}
-
-// __cxa_end_cleanup is called at the end of a cleanup fragment.
-// It must do the C++ housekeeping, then call _Unwind_Resume, but it must
-// damage no significant registers in the process.
-
-__asm void __cxa_end_cleanup(void) {
-  extern __ARM_cxa_end_cleanup;
-  extern _Unwind_Resume WEAKASMDECL;
-
-#ifdef __thumb
-  preserve8;                   // This is preserve8 (ARM assembler heuristics are inadequate)
-  push {r1-r7};
-  mov r2, r8;
-  mov r3, r9;
-  mov r4, r10;
-  mov r5, r11;
-  push {r1-r5};
-  bl __ARM_cxa_end_cleanup;    // returns UCB address in r0
-  pop {r1-r5};
-  mov r8, r2;
-  mov r9, r3;
-  mov r10, r4;
-  mov r11, r5;
-  pop {r1-r7};
-  bl _Unwind_Resume;           // won't return
-#else
-  stmfd r13!, {r1-r12}
-  bl __ARM_cxa_end_cleanup;    // returns UCB address in r0
-  ldmia r13!, {r1-r12};
-  b _Unwind_Resume;            // won't return
-#endif
-}
-
-
-#endif /* arm_exceptions_cleanup_c */
-#ifdef arm_exceptions_catchsemantics_c
-
-/* Update date structures as if catching an object.
- * Call this from __cxa_begin_catch when actually catching an object,
- * and from external_exception_termination when called by a foreign runtime
- * after one of our objects was caught.
- */
-
-void NAMES::eh_catch_semantics(UCB *ucbp)
-{
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep;
-
-  if (NAMES::is_foreign_exception(ucbp)) {
-    // Foreign exception. Get the associated intermediary block or
-    // make one if there isn't one already.
-    // In the case of a rethrow, the foreign object may already be on
-    // the handled exceptions chain (it will be first).
-    ep = NAMES::get_foreign_intermediary(g->caughtExceptions, ucbp);
-  } else {
-    // Not foreign
-    ep = ucbp_to_ep(ucbp);
-    // Decrement the propagation count
-    ep->propagationCount--;
-    // Decrement the total uncaught C++ exceptions count
-    g->uncaughtExceptions--;
-  }
-
-  // Common code for our EO's, and foreign ones where we work on the intermediate EO
-
-  // Increment the handler count for this exception object
-  ep->handlerCount++;
-
-  // Push the ep onto the "handled exceptions" chain if it is not already there.
-  // (If catching a rethrow, it may already be there)
-
-  if (ep->nextCaughtException == NULL) {
-    ep->nextCaughtException = g->caughtExceptions;
-    g->caughtExceptions = ep;
-  }
-}
-
-
-#endif /* arm_exceptions_catchsemantics_c */
-#ifdef arm_exceptions_begincatch_c
-
-void *__cxa_begin_catch(UCB *ucbp)
-{
-  void *match = (void *)ucbp->barrier_cache.bitpattern[0]; // The matched object, if any
-
-  // Update the data structures
-
-  NAMES::eh_catch_semantics(ucbp);
-
-  // Tell the unwinder the exception propagation has finished,
-  // and return the object pointer
-
-  _Unwind_Complete(ucbp);
-  return match;
-}
-
-
-#endif /* arm_exceptions_begincatch_c */
-#ifdef arm_exceptions_endcatch_c
-
-#pragma exceptions_unwind
-
-void __cxa_end_catch(void)
-{
-  // Recover the exception object - it is the most recent caught exception object
-  __cxa_eh_globals *g = __cxa_get_globals();
-  __cxa_exception *ep = g->caughtExceptions;
-
-  if (ep == NULL) terminate();
-
-  // Rethrow in progress?
-
-  bool object_being_rethrown = ep->propagationCount != 0;
-
-  // Decrement the handler count for this exception object
-  ep->handlerCount--;
-
-  // Unstack the object if it is no longer being handled anywhere.
-  // Destroy and free the object if it is no longer alive -
-  // it is dead if its handler count becomes 0, unless it is
-  // about to be rethrown.
-  // If the dtor throws, allow its exception to propagate.
-  // Do different things if it is a foreign exception object.
-
-  if (ep->handlerCount == 0) {
-    void *eop = (void *)(ep + 1);
-    UCB *ucbp = &ep->ucb;
-    bool foreign = NAMES::is_foreign_exception(ucbp);
-
-    // Unstack it from the caught exceptions stack - it is guaranteed to be top item.
-    g->caughtExceptions = ep->nextCaughtException;
-
-    if (foreign) {
-      // Get the foreign ucb and free the intermediate ucb (see description in __cxa_begin_catch)
-      ucbp = (UCB *)ep->exceptionType;
-      __cxa_free_exception(eop);
-    } else {
-      ep->nextCaughtException = NULL;  // So __cxa_begin_catch knows it isn't in the chain
-    }
-
-    // Now destroy the exception object if it's no longer needed
-    if (!object_being_rethrown) {
-      if (foreign) {
-
-	// Notify the foreign language, if it so requested
-	if (ucbp->exception_cleanup != NULL)
-	  (ucbp->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, ucbp);
-
-      } else {
-
-        // One of our objects: do C++-specific semantics
-
-	if (ep->exceptionDestructor != NULL) {
-	  // Run the dtor. If it throws, free the memory anyway and
-	  // propagate the new exception.
-#ifdef ARM_EXCEPTIONS_ENABLED
-	  try {
-	    (ep->exceptionDestructor)(eop);
-	  } catch(...) {
-	    // Free the memory and reraise
-	    __cxa_free_exception(eop);
-	    throw;
-	  }
-#else
-	  (ep->exceptionDestructor)(eop);
-#endif
-	}
-	// Dtor (if there was one) didn't throw. Free the memory.
-	__cxa_free_exception(eop);
-      }  // !foreign
-    }  // !object_being_rethrown
-  }  // ep->handlerCount == 0
-}
-
-
-#endif /* arm_exceptions_endcatch_c */
-#ifdef arm_exceptions_bad_typeid_c
-
-#pragma exceptions_unwind
-
-void __cxa_bad_typeid(void)
-{
-  throw std::bad_typeid();
-}
-
-
-#endif /* arm_exceptions_bad_typeid_c */
-#ifdef arm_exceptions_bad_cast_c
-
-#pragma exceptions_unwind
-
-void __cxa_bad_cast(void)
-{
-  throw std::bad_cast();
-}
-
-
-#endif /* arm_exceptions_bad_cast_c */