|
|
|
|
@ -1,16 +1,24 @@
|
|
|
|
|
typedef struct objc_object* id;
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include "dwarf_eh.h"
|
|
|
|
|
#include "objcxx_eh.h"
|
|
|
|
|
#include <cxxabi.h>
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
|
|
#include "objc/runtime.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace __cxxabiv1
|
|
|
|
|
{
|
|
|
|
|
struct __class_type_info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using __cxxabiv1::__class_type_info;
|
|
|
|
|
extern "C" void
|
|
|
|
|
__cxa_throw(void *thrown_exception, std::type_info *tinfo,
|
|
|
|
|
void (*dest)(void *));
|
|
|
|
|
|
|
|
|
|
using namespace __cxxabiv1;
|
|
|
|
|
|
|
|
|
|
// Define some C++ ABI types here, rather than including them. This prevents
|
|
|
|
|
// conflicts with the libstdc++ headers, which expose only a subset of the
|
|
|
|
|
@ -56,6 +64,9 @@ namespace std
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
static std::atomic<ptrdiff_t> exception_object_offset;
|
|
|
|
|
static std::atomic<ptrdiff_t> exception_type_offset;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static BOOL isKindOfClass(Class thrown, Class type)
|
|
|
|
|
{
|
|
|
|
|
@ -71,29 +82,6 @@ static BOOL isKindOfClass(Class thrown, Class type)
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* C++ Exception structure. From the Itanium ABI spec
|
|
|
|
|
*/
|
|
|
|
|
struct __cxa_exception
|
|
|
|
|
{
|
|
|
|
|
std::type_info *exceptionType;
|
|
|
|
|
void (*exceptionDestructor) (void *);
|
|
|
|
|
unexpected_handler unexpectedHandler;
|
|
|
|
|
terminate_handler terminateHandler;
|
|
|
|
|
__cxa_exception *nextException;
|
|
|
|
|
int handlerCount;
|
|
|
|
|
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
|
|
|
|
|
_Unwind_Exception *nextCleanup;
|
|
|
|
|
int cleanupCount;
|
|
|
|
|
#endif
|
|
|
|
|
int handlerSwitchValue;
|
|
|
|
|
const char *actionRecord;
|
|
|
|
|
const char *languageSpecificData;
|
|
|
|
|
void *catchTemp;
|
|
|
|
|
void *adjustedPtr;
|
|
|
|
|
_Unwind_Exception unwindHeader;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -134,7 +122,7 @@ bool gnustep::libobjc::__objc_class_type_info::__do_catch(const type_info *throw
|
|
|
|
|
void **obj,
|
|
|
|
|
unsigned outer) const
|
|
|
|
|
{
|
|
|
|
|
id thrown = (id)obj;
|
|
|
|
|
id thrown = nullptr;
|
|
|
|
|
bool found = false;
|
|
|
|
|
// Id throw matches any ObjC catch. This may be a silly idea!
|
|
|
|
|
if (dynamic_cast<const __objc_id_type_info*>(thrownType)
|
|
|
|
|
@ -192,42 +180,60 @@ extern "C"
|
|
|
|
|
*/
|
|
|
|
|
gnustep::libobjc::__objc_id_type_info __objc_id_type_info;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Exception cleanup function for C++ exceptions that wrap Objective-C
|
|
|
|
|
* exceptions.
|
|
|
|
|
*/
|
|
|
|
|
static void exception_cleanup(_Unwind_Reason_Code reason,
|
|
|
|
|
struct _Unwind_Exception *ex)
|
|
|
|
|
struct _Unwind_Exception *objc_init_cxx_exception(id obj)
|
|
|
|
|
{
|
|
|
|
|
__cxa_exception *cxxex = (__cxa_exception*) ((char*)ex - offsetof(struct __cxa_exception, unwindHeader));
|
|
|
|
|
if (cxxex->exceptionType != &__objc_id_type_info)
|
|
|
|
|
void *cxxexception = nullptr;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
delete cxxex->exceptionType;
|
|
|
|
|
id *exception_object = static_cast<id*>(__cxa_allocate_exception(sizeof(id)));
|
|
|
|
|
*exception_object = obj;
|
|
|
|
|
__cxa_throw(exception_object, &__objc_id_type_info, nullptr);
|
|
|
|
|
}
|
|
|
|
|
__cxa_free_exception((void*)ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct _Unwind_Exception *objc_init_cxx_exception(void *thrown_exception)
|
|
|
|
|
{
|
|
|
|
|
__cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
|
|
|
|
|
|
|
|
|
|
std::type_info *tinfo = &__objc_id_type_info;
|
|
|
|
|
|
|
|
|
|
ex->exceptionType = tinfo;
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
cxxexception = __cxa_current_primary_exception();
|
|
|
|
|
}
|
|
|
|
|
assert(cxxexception);
|
|
|
|
|
uint64_t *ehcls = reinterpret_cast<uint64_t*>(cxxexception);
|
|
|
|
|
ehcls--;
|
|
|
|
|
int count = 1;
|
|
|
|
|
while (*ehcls != cxx_exception_class)
|
|
|
|
|
{
|
|
|
|
|
ehcls--;
|
|
|
|
|
count++;
|
|
|
|
|
assert((count < 8) && "Exception structure appears to be corrupt");
|
|
|
|
|
}
|
|
|
|
|
ptrdiff_t displacement = reinterpret_cast<const char*>(cxxexception) - reinterpret_cast<const char*>(ehcls);
|
|
|
|
|
assert((exception_object_offset == 0) || (exception_object_offset == displacement));
|
|
|
|
|
|
|
|
|
|
ex->exceptionDestructor = 0;
|
|
|
|
|
exception_object_offset = displacement;
|
|
|
|
|
|
|
|
|
|
ex->unwindHeader.exception_class = EXCEPTION_CLASS('G','N','U','C','C','+','+','\0');
|
|
|
|
|
ex->unwindHeader.exception_cleanup = exception_cleanup;
|
|
|
|
|
std::type_info **ehtype = reinterpret_cast<std::type_info**>(ehcls);
|
|
|
|
|
ehtype--;
|
|
|
|
|
count = 1;
|
|
|
|
|
while (*ehtype != &__objc_id_type_info)
|
|
|
|
|
{
|
|
|
|
|
ehtype--;
|
|
|
|
|
count++;
|
|
|
|
|
assert((count < 32) && "Exception structure appears to be corrupt");
|
|
|
|
|
}
|
|
|
|
|
displacement = reinterpret_cast<const char*>(ehtype) - reinterpret_cast<const char*>(ehcls);
|
|
|
|
|
assert((exception_type_offset == 0) || (exception_type_offset == displacement));
|
|
|
|
|
|
|
|
|
|
return &ex->unwindHeader;
|
|
|
|
|
exception_type_offset = displacement;
|
|
|
|
|
return reinterpret_cast<_Unwind_Exception*>(ehcls);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* objc_object_for_cxx_exception(void *thrown_exception, int *isValid)
|
|
|
|
|
{
|
|
|
|
|
__cxa_exception *ex = (__cxa_exception*) ((char*)thrown_exception -
|
|
|
|
|
offsetof(struct __cxa_exception, unwindHeader));
|
|
|
|
|
const std::type_info *thrownType = ex->exceptionType;
|
|
|
|
|
ptrdiff_t type_offset = exception_type_offset;
|
|
|
|
|
if (type_offset == 0)
|
|
|
|
|
{
|
|
|
|
|
*isValid = 0;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
const std::type_info *thrownType =
|
|
|
|
|
*reinterpret_cast<const std::type_info**>(reinterpret_cast<char*>(thrown_exception) + type_offset);
|
|
|
|
|
if (!dynamic_cast<const gnustep::libobjc::__objc_id_type_info*>(thrownType) &&
|
|
|
|
|
!dynamic_cast<const gnustep::libobjc::__objc_class_type_info*>(thrownType))
|
|
|
|
|
{
|
|
|
|
|
@ -235,7 +241,7 @@ void* objc_object_for_cxx_exception(void *thrown_exception, int *isValid)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
*isValid = 1;
|
|
|
|
|
return *(id*)(ex+1);
|
|
|
|
|
return *reinterpret_cast<id*>(reinterpret_cast<char*>(thrown_exception) + exception_object_offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|