2010-07-01 07:17:53 +00:00
|
|
|
#if defined(__has_include)
|
|
|
|
#if __has_include(<objc/hooks.h>)
|
2010-06-30 13:08:22 +00:00
|
|
|
#import "Foundation/NSObject.h"
|
2011-03-13 12:14:40 +00:00
|
|
|
#import "GNUstepBase/CXXException.h"
|
2010-06-30 13:08:22 +00:00
|
|
|
#include <objc/runtime.h>
|
|
|
|
#include <objc/hooks.h>
|
|
|
|
|
|
|
|
/** From the CodeSourcery ABI Spec, with C++ pointers turned to void*, and
|
|
|
|
* other parts abridged. */
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
_URC_FOREIGN_EXCEPTION_CAUGHT = 1
|
2010-06-30 13:08:22 +00:00
|
|
|
} _Unwind_Reason_Code;
|
|
|
|
|
|
|
|
struct _Unwind_Exception;
|
|
|
|
|
|
|
|
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
|
|
|
|
struct _Unwind_Exception *);
|
|
|
|
struct _Unwind_Exception
|
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
uint64_t exception_class;
|
|
|
|
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
|
|
|
unsigned long private_1;
|
|
|
|
unsigned long private_2;
|
2010-06-30 13:08:22 +00:00
|
|
|
} __attribute__((__aligned__));
|
|
|
|
|
|
|
|
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
|
|
|
|
|
|
|
|
|
|
|
|
struct __cxa_exception
|
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
void *exceptionType;
|
|
|
|
void (*exceptionDestructor) (void *);
|
|
|
|
void (*unexpectedHandler) (void *);
|
|
|
|
void (*terminateHandler) (void *);
|
|
|
|
void *nextException;
|
2010-06-30 13:08:22 +00:00
|
|
|
|
2010-07-01 07:17:53 +00:00
|
|
|
int handlerCount;
|
|
|
|
int handlerSwitchValue;
|
|
|
|
const char * actionRecord;
|
|
|
|
const char * languageSpecificData;
|
|
|
|
void * catchTemp;
|
|
|
|
void * adjustedPtr;
|
|
|
|
struct _Unwind_Exception unwindHeader;
|
2010-06-30 13:08:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
@implementation CXXException
|
|
|
|
static Class CXXExceptionClass;
|
|
|
|
// TODO: Add an API for registering other classes for other exception types
|
|
|
|
static Class boxClass(int64_t foo)
|
|
|
|
{
|
2011-03-16 14:38:42 +00:00
|
|
|
// Big endian platforms
|
2011-02-19 15:34:21 +00:00
|
|
|
if (foo == *(int64_t*)(void*)"GNUCC++\0")
|
2010-07-01 07:17:53 +00:00
|
|
|
{
|
|
|
|
return CXXExceptionClass;
|
|
|
|
}
|
2011-03-16 14:38:42 +00:00
|
|
|
// Little endian platforms
|
|
|
|
if (foo == *(int64_t*)(void*)"\0++CCUNG")
|
|
|
|
{
|
|
|
|
return CXXExceptionClass;
|
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
return Nil;
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
+ (void) load
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
CXXExceptionClass = self;
|
|
|
|
_objc_class_for_boxing_foreign_exception = boxClass;
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
+ (id) exceptionWithForeignException: (struct _Unwind_Exception*)ex
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
CXXException *box = [self new];
|
|
|
|
box->ex = ex;
|
|
|
|
return [box autorelease];
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
- (void*) thrownValue
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
return ex + 1;
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
- (void*) cxx_type_info
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
char *ptr = (char*)ex;
|
|
|
|
ptr -= __builtin_offsetof(struct __cxa_exception, unwindHeader);
|
2011-02-19 15:34:21 +00:00
|
|
|
return ((struct __cxa_exception*)(void*)ptr)->exceptionType;
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
- (void) rethrow
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
struct _Unwind_Exception *re = ex;
|
|
|
|
// We aren't allowed to hold onto the exception if it's been rethrown.
|
|
|
|
ex = 0;
|
|
|
|
_Unwind_Resume_or_Rethrow(re);
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
2010-07-01 07:17:53 +00:00
|
|
|
- (void) dealloc
|
2010-06-30 13:08:22 +00:00
|
|
|
{
|
2010-07-01 07:17:53 +00:00
|
|
|
if (0 != ex && 0 != ex->exception_cleanup)
|
|
|
|
{
|
|
|
|
ex->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, ex);
|
|
|
|
}
|
|
|
|
[super dealloc];
|
2010-06-30 13:08:22 +00:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
#endif
|
2010-07-01 07:17:53 +00:00
|
|
|
#endif
|