Kernel/VTerm - "Fix" wrapping issue in VTerm (why was old behavior there?)
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / exception_handling.cc
index 2303980..81d4605 100644 (file)
 /*
+ * Acess2 C++ Support Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exception_handling.cc
+ * - Exception handling code (defined by C++ ABI)
+ *
+ * References:
+ * - LLVM Exception handling
+ *  > http://llvm.org/docs/ExceptionHandling.html
+ * - Itanium C++ ABI
+ *  >http://mentorembedded.github.io/cxx-abi/abi-eh.html
+ * - HP's "aC++" Document, Ch 7 "Exception Handling Tables"
+ *  > http://mentorembedded.github.io/cxx-abi/exceptions.pdf
  */
 #include <typeinfo>
 #include <cstdint>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include "exception_handling_cxxabi.h"
 
-typedef void *(unexpected_handler)(void);
-typedef void *(terminate_handler)(void);
+#include <acess/sys.h>
 
-struct _Unwind_Context;
+#define DEBUG_ENABLED  1
 
-typedef enum {
-       _URC_NO_REASON = 0,
-       _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
-       _URC_FATAL_PHASE2_ERROR = 2,
-       _URC_FATAL_PHASE1_ERROR = 3,
-       _URC_NORMAL_STOP = 4,
-       _URC_END_OF_STACK = 5,
-       _URC_HANDLER_FOUND = 6,
-       _URC_INSTALL_CONTEXT = 7,
-       _URC_CONTINUE_UNWIND = 8
-} _Unwind_Reason_Code;
+#if DEBUG_ENABLED
+# define       DEBUG(v...)     ::_SysDebug(v)
+#else
+# define       DEBUG(v...)     do{}while(0)
+#endif
 
-typedef void   (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc);
+/*__thread*/ struct __cxa_eh_globals {
+       __cxa_exception *caughtExceptions;
+       unsigned  int   uncaughtExceptions;
+} eh_globals;
 
-struct _Unwind_Exception
-{
-       uint64_t        exception_class;
-       _Unwind_Exception_Cleanup_Fn    exception_cleanup;
-       uint64_t        private_1;
-       uint64_t        private_2;
-};
-
-struct __cxa_exception
-{
-       std::type_info* exceptionType;
-       void (*exceptionDestructor)(void *);
-       unexpected_handler      unexpectedHandler;
-       terminate_handler       terminateHandler;
-       __cxa_exception*        nextException;
-       
-       int     handlerCount;
-       
-       int     handlerSwitchValue;
-       const char*     actionRecord;
-       const char*     languageSpecificData;
-       void*   catchTemp;
-       void*   adjustedPtr;
-       
-       _Unwind_Exception       unwindHeader;
-};
+/*__thread*/ struct {
+       __cxa_exception info;
+       char    buf[32];
+} emergency_exception;
+/*__thread*/ bool      emergency_exception_used;
 
- int   uncaught_exception_count;
-__cxa_exception        *uncaught_exception_top;
+static bool TEST_AND_SET(bool& flag) {
+       bool ret = flag;
+       flag = true;
+       return ret;
+}
 
+// === CODE ===
+extern "C" __cxa_eh_globals *__cxa_get_globals(void)
+{
+       return &eh_globals;
+}
+extern "C" __cxa_eh_globals *__cxa_get_globals_fast(void)
+{
+       return &eh_globals;
+}
 extern "C" void __cxa_call_unexpected(void *)
 {
        // An unexpected exception was thrown from a function that lists its possible exceptions
+       _SysDebug("__cxa_call_unexpected - TODO");
        for(;;);
 }
 
-extern "C" void *__cxa_begin_catch(void *exceptionObject)
+extern "C" void *__cxa_allocate_exception(size_t thrown_size)
+{
+       DEBUG("__cxa_allocate_exception(%i)", thrown_size);
+       __cxa_exception *ret = static_cast<__cxa_exception*>( malloc( sizeof(__cxa_exception) + thrown_size ) );
+       if( !ret ) {
+               if( thrown_size <= sizeof(emergency_exception.buf) && TEST_AND_SET(emergency_exception_used) )
+               {
+                       ret = &emergency_exception.info;
+               }
+       }
+       if( !ret ) {
+               _SysDebug("__cxa_allocate_exception - No free space");
+               ::std::terminate();
+       }
+       DEBUG("__cxa_allocate_exception: return %p", ret+1);
+       return ret + 1;
+}
+
+extern "C" void __cxa_free_exception(void *thrown_exception)
+{
+       DEBUG("__cxa_free_exception(%p)", thrown_exception);
+       if(thrown_exception == &emergency_exception.buf) {
+               //assert(emergency_exception_used);
+               emergency_exception_used = false;
+       }
+       else {
+               __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
+               free(except);
+       }
+}
+
+extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void*))
 {
-       struct __cxa_exception  *except = static_cast<__cxa_exception*>( exceptionObject );
-       except --;
+       #if DEBUG_ENABLED
+       DEBUG("__cxa_throw(%p,%p,%p) '%s' by %p",
+               thrown_exception, tinfo, dest, tinfo->name(), __builtin_return_address(0)
+               );
+       {
+               const ::std::exception* e = reinterpret_cast<const ::std::exception*>(thrown_exception);
+               DEBUG("- e.what() = '%s'", e->what());
+       }
+       #endif
+
+       __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
+       
+       except->unexpectedHandler = 0;
+       except->terminateHandler = 0;
+       except->exceptionType = tinfo;
+       except->exceptionDestructor = dest;
+       memcpy(&except->unwindHeader.exception_class, EXCEPTION_CLASS_ACESS, 8);
+       __cxa_get_globals()->uncaughtExceptions ++;
+       
+       int rv = _Unwind_RaiseException( &except->unwindHeader );
+       
+       ::_SysDebug("__cxa_throw(%p,%s) :: UNCAUGHT %i", thrown_exception, tinfo->name(), rv);
+       ::std::terminate();
+}
+
+extern "C" void *__cxa_begin_catch(_Unwind_Exception *exceptionObject)
+{
+       __cxa_exception *except = reinterpret_cast<__cxa_exception*>( exceptionObject+1 )-1;
+       DEBUG("__cxa_begin_catch(%p) - except=%p", exceptionObject, except);
        
        except->handlerCount ++;
        
-       except->nextException = uncaught_exception_top;
-       uncaught_exception_top = except;
+       except->nextException = __cxa_get_globals()->caughtExceptions;
+       __cxa_get_globals()->caughtExceptions = except;
        
-       uncaught_exception_count --;
+       __cxa_get_globals_fast()->uncaughtExceptions --;
        
-       return except;
+       return except+1;
 }
 
 extern "C" void __cxa_end_catch()
 {
-       struct __cxa_exception  *except = uncaught_exception_top;
+       struct __cxa_exception  *except = __cxa_get_globals()->caughtExceptions;
+       DEBUG("__cxa_end_catch - %p", except);
        except->handlerCount --;
-       uncaught_exception_top = except->nextException;
+       __cxa_get_globals()->caughtExceptions = except->nextException;
        
        if( except->handlerCount == 0 ) {
-               //__cxa_free_exception(except+1);
+               __cxa_free_exception(except+1);
        }
 }
 
+

UCC git Repository :: git.ucc.asn.au