Skip to content

Commit 38ebb38

Browse files
committed
MinGW: Use _Unwind_RaiseException to throw exceptions
1 parent f983cdb commit 38ebb38

File tree

3 files changed

+63
-62
lines changed

3 files changed

+63
-62
lines changed

CMakeLists.txt

+1-3
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,7 @@ set(libobjc_CXX_SRCS
124124
# Windows does not use DWARF EH, except when using the GNU ABI (MinGW)
125125
if (WIN32 AND NOT MINGW)
126126
list(APPEND libobjc_CXX_SRCS eh_win32_msvc.cc)
127-
elseif (MINGW)
128-
list(APPEND libobjc_CXX_SRCS eh_win32_mingw.m)
129-
else ()
127+
elseif (NOT MINGW)
130128
list(APPEND libobjc_C_SRCS eh_personality.c)
131129
endif ()
132130

eh_win32_mingw.m

-59
This file was deleted.

objcxx_eh.cc

+62
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ typedef struct objc_object* id;
77
#include "visibility.h"
88
#include "objc/runtime.h"
99
#include "objc/objc-arc.h"
10+
#ifdef __MINGW32__
11+
#include "objc/objc-exception.h"
12+
#include "objc/hooks.h"
13+
#endif
1014

1115
#ifndef DEBUG_EXCEPTIONS
1216
#define DEBUG_LOG(...)
@@ -515,14 +519,72 @@ static void eh_cleanup(void *exception)
515519
objc_release(*(id*)exception);
516520
}
517521

522+
namespace __cxxabiv1
523+
{
524+
struct __cxa_refcounted_exception
525+
{
526+
int referenceCount;
527+
};
528+
}
529+
530+
extern "C" __cxa_refcounted_exception* __cxa_init_primary_exception(void *obj, std::type_info *tinfo, void (*dest) (void *));
531+
518532
extern "C"
519533
OBJC_PUBLIC
520534
void objc_exception_throw(id object)
521535
{
536+
#ifdef __GLIBCXX__
537+
// Don't bother with a mutex here. It doesn't matter if two threads set
538+
// these values at the same time.
539+
if (!done_setup)
540+
{
541+
DEBUG_LOG("objc_exception_throw: Doing initial setup\n");
542+
MagicValueHolder *magicExc = (MagicValueHolder *)__cxa_allocate_exception(sizeof(MagicValueHolder));
543+
MagicValueHolder x;
544+
*magicExc = x;
545+
546+
__cxa_refcounted_exception *header =
547+
__cxa_init_primary_exception(magicExc, & __objc_id_type_info, NULL);
548+
exception_struct_size = find_forwards(header, MagicValueHolder::magic);
549+
__cxa_free_exception(magicExc);
550+
551+
DEBUG_LOG("objc_exception_throw: exception_struct_size: 0x%x\n", unsigned(exception_struct_size));
552+
553+
done_setup = true;
554+
}
555+
#endif
556+
522557
id *exc = (id *)__cxa_allocate_exception(sizeof(id));
523558
*exc = object;
524559
objc_retain(object);
525560
DEBUG_LOG("objc_exception_throw: Throwing 0x%x\n", *exc);
561+
562+
#ifndef __GLIBCXX__
563+
// At the moment, only libstdc++ exposes __cxa_init_primary_exception.
526564
__cxa_throw(exc, & __objc_id_type_info, eh_cleanup);
565+
#else
566+
__cxa_eh_globals *globals = __cxa_get_globals ();
567+
globals->uncaughtExceptions += 1;
568+
__cxa_refcounted_exception *header =
569+
__cxa_init_primary_exception(exc, & __objc_id_type_info, eh_cleanup);
570+
header->referenceCount = 1;
571+
572+
_Unwind_Exception *unwindHeader = pointer_add<_Unwind_Exception>(header, exception_struct_size - sizeof(_Unwind_Exception));
573+
_Unwind_Reason_Code err = _Unwind_RaiseException (unwindHeader);
574+
575+
if (_URC_END_OF_STACK == err && 0 != _objc_unexpected_exception)
576+
{
577+
DEBUG_LOG("Invoking _objc_unexpected_exception\n");
578+
_objc_unexpected_exception(object);
579+
}
580+
DEBUG_LOG("Throw returned %d\n",(int) err);
581+
abort();
582+
#endif
527583
}
584+
585+
OBJC_PUBLIC extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler)
586+
{
587+
return __atomic_exchange_n(&_objc_unexpected_exception, handler, __ATOMIC_SEQ_CST);
588+
}
589+
528590
#endif

0 commit comments

Comments
 (0)