Пример #1
0
/*
The adjusted pointer is computed by the personality routine during phase 1
  and saved in the exception header (either __cxa_exception or
  __cxa_dependent_exception).

  Requires:  exception is native
*/
void*
__cxa_get_exception_ptr(void* unwind_exception) throw()
{
#if __ARM_EABI_UNWINDER__
    return cxa_exception_from_exception_unwind_exception
    (
     static_cast<_Unwind_Exception*>(unwind_exception)
     )->nextPropagatingException;
#else
    return cxa_exception_from_exception_unwind_exception
           (
               static_cast<_Unwind_Exception*>(unwind_exception)
           )->adjustedPtr;
#endif //__ARM_EABI_UNWINDER__
}
Пример #2
0
/*
The routine to be called before the cleanup.  This will save __cxa_exception in
__cxa_eh_globals, so that __cxa_end_cleanup() can recover later.
*/
bool
__cxa_begin_cleanup(void* unwind_arg) throw ()
{
    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
    __cxa_eh_globals* globals = __cxa_get_globals();
    __cxa_exception* exception_header =
        cxa_exception_from_exception_unwind_exception(unwind_exception);

    if (isOurExceptionClass(unwind_exception))
    {
        if (0 == exception_header->propagationCount)
        {
            exception_header->nextPropagatingException = globals->propagatingExceptions;
            globals->propagatingExceptions = exception_header;
        }
        ++exception_header->propagationCount;
    }
    else
    {
        // If the propagatingExceptions stack is not empty, since we can't
        // chain the foreign exception, terminate it.
        if (NULL != globals->propagatingExceptions)
            std::terminate();
        globals->propagatingExceptions = exception_header;
    }
    return true;
}
Пример #3
0
/*
The adjusted pointer is computed by the personality routine during phase 1
  and saved in the exception header (either __cxa_exception or
  __cxa_dependent_exception).

  Requires:  exception is native
*/
void*
__cxa_get_exception_ptr(void* unwind_exception) throw()
{
    return cxa_exception_from_exception_unwind_exception
           (
               static_cast<_Unwind_Exception*>(unwind_exception)
           )->adjustedPtr;
}
Пример #4
0
/*
    If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
    stored in exc is called.  Otherwise the exceptionDestructor stored in 
    exc is called, and then the memory for the exception is deallocated.

    This is never called for a __cxa_dependent_exception.
*/
static
void
exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
{
    __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
    if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
        std::__terminate(exception_header->terminateHandler);
    // Just in case there exists a dependent exception that is pointing to this,
    //    check the reference count and only destroy this if that count goes to zero.
    __cxa_decrement_exception_refcount(unwind_exception + 1);
}
Пример #5
0
/*
The adjusted pointer is computed by the personality routine during phase 1
  and saved in the exception header (either __cxa_exception or
  __cxa_dependent_exception).

  Requires:  exception is native
*/
void*
__cxa_get_exception_ptr(void* unwind_exception) throw()
{
#if LIBCXXABI_ARM_EHABI
    return reinterpret_cast<void*>(
        static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
#else
    return cxa_exception_from_exception_unwind_exception(
        static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr;
#endif
}
Пример #6
0
/*
This routine can catch foreign or native exceptions.  If native, the exception
can be a primary or dependent variety.  This routine may remain blissfully
ignorant of whether the native exception is primary or dependent.

If the exception is native:
* Increment's the exception's handler count.
* Push the exception on the stack of currently-caught exceptions if it is not 
  already there (from a rethrow).
* Decrements the uncaught_exception count.
* Returns the adjusted pointer to the exception object, which is stored in
  the __cxa_exception by the personality routine.

If the exception is foreign, this means it did not originate from one of throw
routines.  The foreign exception does not necessarily have a __cxa_exception
header.  However we can catch it here with a catch (...), or with a call
to terminate or unexpected during unwinding.
* Do not try to increment the exception's handler count, we don't know where
  it is.
* Push the exception on the stack of currently-caught exceptions only if the
  stack is empty.  The foreign exception has no way to link to the current
  top of stack.  If the stack is not empty, call terminate.  Even with an
  empty stack, this is hacked in by pushing a pointer to an imaginary
  __cxa_exception block in front of the foreign exception.  It would be better
  if the __cxa_eh_globals structure had a stack of _Unwind_Exception, but it
  doesn't.  It has a stack of __cxa_exception (which has a next* in it).
* Do not decrement the uncaught_exception count because we didn't increment it
  in __cxa_throw (or one of our rethrow functions).
* If we haven't terminated, assume the exception object is just past the 
  _Unwind_Exception and return a pointer to that.
*/
void*
__cxa_begin_catch(void* unwind_arg) throw()
{
    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
    bool native_exception = isOurExceptionClass(unwind_exception);
    __cxa_eh_globals* globals = __cxa_get_globals();
    // exception_header is a hackish offset from a foreign exception, but it
    //   works as long as we're careful not to try to access any __cxa_exception
    //   parts.
    __cxa_exception* exception_header =
            cxa_exception_from_exception_unwind_exception
            (
                static_cast<_Unwind_Exception*>(unwind_exception)
            );
    if (native_exception)
    {
        // Increment the handler count, removing the flag about being rethrown
        exception_header->handlerCount = exception_header->handlerCount < 0 ?
            -exception_header->handlerCount + 1 : exception_header->handlerCount + 1;
        //  place the exception on the top of the stack if it's not already
        //    there by a previous rethrow
        if (exception_header != globals->caughtExceptions)
        {
            exception_header->nextException = globals->caughtExceptions;
            globals->caughtExceptions = exception_header;
        }
        globals->uncaughtExceptions -= 1;   // Not atomically, since globals are thread-local
#if LIBCXXABI_ARM_EHABI
        return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
#else
        return exception_header->adjustedPtr;
#endif
    }
    // Else this is a foreign exception
    // If the caughtExceptions stack is not empty, terminate
    if (globals->caughtExceptions != 0)
        std::terminate();
    // Push the foreign exception on to the stack
    globals->caughtExceptions = exception_header;
    return unwind_exception + 1;
}