81d460524443a3b42a66a670513a438b02beba0b
[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 #define DEBUG_ENABLED   1
27
28 #if DEBUG_ENABLED
29 # define        DEBUG(v...)     ::_SysDebug(v)
30 #else
31 # define        DEBUG(v...)     do{}while(0)
32 #endif
33
34 /*__thread*/ struct __cxa_eh_globals {
35         __cxa_exception *caughtExceptions;
36         unsigned  int   uncaughtExceptions;
37 } eh_globals;
38
39 /*__thread*/ struct {
40         __cxa_exception info;
41         char    buf[32];
42 } emergency_exception;
43 /*__thread*/ bool       emergency_exception_used;
44
45 static bool TEST_AND_SET(bool& flag) {
46         bool ret = flag;
47         flag = true;
48         return ret;
49 }
50
51 // === CODE ===
52 extern "C" __cxa_eh_globals *__cxa_get_globals(void)
53 {
54         return &eh_globals;
55 }
56 extern "C" __cxa_eh_globals *__cxa_get_globals_fast(void)
57 {
58         return &eh_globals;
59 }
60 extern "C" void __cxa_call_unexpected(void *)
61 {
62         // An unexpected exception was thrown from a function that lists its possible exceptions
63         _SysDebug("__cxa_call_unexpected - TODO");
64         for(;;);
65 }
66
67 extern "C" void *__cxa_allocate_exception(size_t thrown_size)
68 {
69         DEBUG("__cxa_allocate_exception(%i)", thrown_size);
70         __cxa_exception *ret = static_cast<__cxa_exception*>( malloc( sizeof(__cxa_exception) + thrown_size ) );
71         if( !ret ) {
72                 if( thrown_size <= sizeof(emergency_exception.buf) && TEST_AND_SET(emergency_exception_used) )
73                 {
74                         ret = &emergency_exception.info;
75                 }
76         }
77         if( !ret ) {
78                 _SysDebug("__cxa_allocate_exception - No free space");
79                 ::std::terminate();
80         }
81         DEBUG("__cxa_allocate_exception: return %p", ret+1);
82         return ret + 1;
83 }
84
85 extern "C" void __cxa_free_exception(void *thrown_exception)
86 {
87         DEBUG("__cxa_free_exception(%p)", thrown_exception);
88         if(thrown_exception == &emergency_exception.buf) {
89                 //assert(emergency_exception_used);
90                 emergency_exception_used = false;
91         }
92         else {
93                 __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
94                 free(except);
95         }
96 }
97
98 extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void*))
99 {
100         #if DEBUG_ENABLED
101         DEBUG("__cxa_throw(%p,%p,%p) '%s' by %p",
102                 thrown_exception, tinfo, dest, tinfo->name(), __builtin_return_address(0)
103                 );
104         {
105                 const ::std::exception* e = reinterpret_cast<const ::std::exception*>(thrown_exception);
106                 DEBUG("- e.what() = '%s'", e->what());
107         }
108         #endif
109
110         __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
111         
112         except->unexpectedHandler = 0;
113         except->terminateHandler = 0;
114         except->exceptionType = tinfo;
115         except->exceptionDestructor = dest;
116         memcpy(&except->unwindHeader.exception_class, EXCEPTION_CLASS_ACESS, 8);
117         __cxa_get_globals()->uncaughtExceptions ++;
118         
119         int rv = _Unwind_RaiseException( &except->unwindHeader );
120         
121         ::_SysDebug("__cxa_throw(%p,%s) :: UNCAUGHT %i", thrown_exception, tinfo->name(), rv);
122         ::std::terminate();
123 }
124
125 extern "C" void *__cxa_begin_catch(_Unwind_Exception *exceptionObject)
126 {
127         __cxa_exception *except = reinterpret_cast<__cxa_exception*>( exceptionObject+1 )-1;
128         DEBUG("__cxa_begin_catch(%p) - except=%p", exceptionObject, except);
129         
130         except->handlerCount ++;
131         
132         except->nextException = __cxa_get_globals()->caughtExceptions;
133         __cxa_get_globals()->caughtExceptions = except;
134         
135         __cxa_get_globals_fast()->uncaughtExceptions --;
136         
137         return except+1;
138 }
139
140 extern "C" void __cxa_end_catch()
141 {
142         struct __cxa_exception  *except = __cxa_get_globals()->caughtExceptions;
143         DEBUG("__cxa_end_catch - %p", except);
144         except->handlerCount --;
145         __cxa_get_globals()->caughtExceptions = except->nextException;
146         
147         if( except->handlerCount == 0 ) {
148                 __cxa_free_exception(except+1);
149         }
150 }
151
152

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