Usermode/libc++ - Exception handling implemented (partially)
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / exception_handling.cc
1 /*
2  * Acess2 C++ Support Library
3  * - By John Hodge (thePowersGang)
4  *
5  * exception_handling.cc
6  * - Exception handling code (defined by C++ ABI)
7  *
8  * References:
9  * - LLVM Exception handling
10  *  > http://llvm.org/docs/ExceptionHandling.html
11  * - Itanium C++ ABI
12  *  >http://mentorembedded.github.io/cxx-abi/abi-eh.html
13  * - HP's "aC++" Document, Ch 7 "Exception Handling Tables"
14  *  > http://mentorembedded.github.io/cxx-abi/exceptions.pdf
15  */
16 #include <typeinfo>
17 #include <cstdint>
18 #include <cstddef>
19 #include <cstdlib>
20 #include <cstring>
21 #include <exception>
22 #include "exception_handling_cxxabi.h"
23
24 #include <acess/sys.h>
25
26 /*__thread*/ struct __cxa_eh_globals {
27         __cxa_exception *caughtExceptions;
28         unsigned  int   uncaughtExceptions;
29 } eh_globals;
30
31 /*__thread*/ struct {
32         __cxa_exception info;
33         char    buf[32];
34 } emergency_exception;
35 /*__thread*/ bool       emergency_exception_used;
36
37 static bool TEST_AND_SET(bool& flag) {
38         bool ret = flag;
39         flag = true;
40         return ret;
41 }
42
43 // === CODE ===
44 extern "C" __cxa_eh_globals *__cxa_get_globals(void)
45 {
46         return &eh_globals;
47 }
48 extern "C" __cxa_eh_globals *__cxa_get_globals_fast(void)
49 {
50         return &eh_globals;
51 }
52 extern "C" void __cxa_call_unexpected(void *)
53 {
54         // An unexpected exception was thrown from a function that lists its possible exceptions
55         _SysDebug("__cxa_call_unexpected - TODO");
56         for(;;);
57 }
58
59 extern "C" void *__cxa_allocate_exception(size_t thrown_size)
60 {
61         ::_SysDebug("__cxa_allocate_exception(%i)", thrown_size);
62         __cxa_exception *ret = static_cast<__cxa_exception*>( malloc( sizeof(__cxa_exception) + thrown_size ) );
63         if( !ret ) {
64                 if( thrown_size <= sizeof(emergency_exception.buf) && TEST_AND_SET(emergency_exception_used) )
65                 {
66                         ret = &emergency_exception.info;
67                 }
68         }
69         if( !ret ) {
70                 _SysDebug("__cxa_allocate_exception - No free space");
71                 ::std::terminate();
72         }
73         ::_SysDebug("__cxa_allocate_exception: return %p", ret+1);
74         return ret + 1;
75 }
76
77 extern "C" void __cxa_free_exception(void *thrown_exception)
78 {
79         ::_SysDebug("__cxa_free_exception(%p)", thrown_exception);
80         if(thrown_exception == &emergency_exception.buf) {
81                 //assert(emergency_exception_used);
82                 emergency_exception_used = false;
83         }
84         else {
85                 __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
86                 free(except);
87         }
88 }
89
90 extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void*))
91 {
92         ::_SysDebug("__cxa_throw(%p,%p,%p) '%s' by %p",
93                 thrown_exception, tinfo, dest, tinfo->name(), __builtin_return_address(0)
94                 );
95         {
96                 const ::std::exception* e = reinterpret_cast<const ::std::exception*>(thrown_exception);
97                 ::_SysDebug("- e.what() = '%s'", e->what());
98         }
99
100         __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
101         
102         except->unexpectedHandler = 0;
103         except->terminateHandler = 0;
104         except->exceptionType = tinfo;
105         except->exceptionDestructor = dest;
106         memcpy(&except->unwindHeader.exception_class, EXCEPTION_CLASS_ACESS, 8);
107         __cxa_get_globals()->uncaughtExceptions ++;
108         
109         int rv = _Unwind_RaiseException( &except->unwindHeader );
110         
111         ::_SysDebug("__cxa_throw(%p,%s) :: UNCAUGHT %i", thrown_exception, tinfo->name(), rv);
112         ::std::terminate();
113 }
114
115 extern "C" void *__cxa_begin_catch(_Unwind_Exception *exceptionObject)
116 {
117         __cxa_exception *except = reinterpret_cast<__cxa_exception*>( exceptionObject+1 )-1;
118         ::_SysDebug("__cxa_begin_catch(%p) - except=%p", exceptionObject, except);
119         
120         except->handlerCount ++;
121         
122         except->nextException = __cxa_get_globals()->caughtExceptions;
123         __cxa_get_globals()->caughtExceptions = except;
124         
125         __cxa_get_globals_fast()->uncaughtExceptions --;
126         
127         return except+1;
128 }
129
130 extern "C" void __cxa_end_catch()
131 {
132         struct __cxa_exception  *except = __cxa_get_globals()->caughtExceptions;
133         ::_SysDebug("__cxa_end_catch - %p", except);
134         except->handlerCount --;
135         __cxa_get_globals()->caughtExceptions = except->nextException;
136         
137         if( except->handlerCount == 0 ) {
138                 __cxa_free_exception(except+1);
139         }
140 }
141
142

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