-
Notifications
You must be signed in to change notification settings - Fork 119
/
objcxx_eh_mingw.cc
134 lines (111 loc) · 3.45 KB
/
objcxx_eh_mingw.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <atomic>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "dwarf_eh.h"
#include "objcxx_eh_private.h"
#include "objcxx_eh.h"
#include "objc/runtime.h"
#include "objc/objc-arc.h"
#include "objc/objc-exception.h"
#include "objc/hooks.h"
namespace __cxxabiv1
{
struct __cxa_refcounted_exception
{
int referenceCount;
};
}
using namespace __cxxabiv1;
extern "C" __cxa_refcounted_exception* __cxa_init_primary_exception(void *obj, std::type_info *tinfo, void (*dest) (void *));
static void eh_cleanup(void *exception)
{
DEBUG_LOG("eh_cleanup: Releasing 0x%x\n", *(id*)exception);
objc_release(*(id*)exception);
}
/**
* Flag indicating that we've already inspected a C++ exception and found all
* of the offsets.
*/
std::atomic<bool> done_setup;
/**
* The size of the `_Unwind_Exception` (including padding) in a
* `__cxa_exception`.
*/
std::atomic<size_t> exception_struct_size;
extern "C"
OBJC_PUBLIC
void objc_exception_throw(id object)
{
// Don't bother with a mutex here. It doesn't matter if two threads set
// these values at the same time.
if (!done_setup)
{
DEBUG_LOG("objc_exception_throw: Doing initial setup\n");
MagicValueHolder *magicExc = (MagicValueHolder *)__cxa_allocate_exception(sizeof(MagicValueHolder));
MagicValueHolder x;
*magicExc = x;
__cxa_refcounted_exception *header =
__cxa_init_primary_exception(magicExc, & __objc_id_type_info, NULL);
exception_struct_size = find_forwards(header, MagicValueHolder::magic);
__cxa_free_exception(magicExc);
DEBUG_LOG("objc_exception_throw: exception_struct_size: 0x%x\n", unsigned(exception_struct_size));
done_setup = true;
}
id *exc = (id *)__cxa_allocate_exception(sizeof(id));
*exc = object;
objc_retain(object);
DEBUG_LOG("objc_exception_throw: Throwing 0x%x\n", *exc);
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
__cxa_refcounted_exception *header =
__cxa_init_primary_exception(exc, & __objc_id_type_info, eh_cleanup);
header->referenceCount = 1;
_Unwind_Exception *unwindHeader = pointer_add<_Unwind_Exception>(header, exception_struct_size - sizeof(_Unwind_Exception));
_Unwind_Reason_Code err = _Unwind_RaiseException (unwindHeader);
if (_URC_END_OF_STACK == err && 0 != _objc_unexpected_exception)
{
DEBUG_LOG("Invoking _objc_unexpected_exception\n");
_objc_unexpected_exception(object);
}
DEBUG_LOG("Throw returned %d\n",(int) err);
abort();
}
OBJC_PUBLIC extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler)
{
return __atomic_exchange_n(&_objc_unexpected_exception, handler, __ATOMIC_SEQ_CST);
}
extern "C" void* __cxa_begin_catch(void *object);
extern "C"
OBJC_PUBLIC
void* objc_begin_catch(void* object)
{
return __cxa_begin_catch(object);
}
extern "C" void __cxa_end_catch();
extern "C"
OBJC_PUBLIC
void objc_end_catch()
{
__cxa_end_catch();
}
extern "C" void __cxa_rethrow();
extern "C"
OBJC_PUBLIC
void objc_exception_rethrow()
{
__cxa_rethrow();
}
extern "C" EXCEPTION_DISPOSITION __gxx_personality_seh0(PEXCEPTION_RECORD ms_exc,
void *this_frame,
PCONTEXT ms_orig_context,
PDISPATCHER_CONTEXT ms_disp);
extern "C"
OBJC_PUBLIC
EXCEPTION_DISPOSITION __gnu_objc_personality_seh0(PEXCEPTION_RECORD ms_exc,
void *this_frame,
PCONTEXT ms_orig_context,
PDISPATCHER_CONTEXT ms_disp)
{
return __gxx_personality_seh0(ms_exc, this_frame, ms_orig_context, ms_disp);
}