Skip to content

Commit 3218c92

Browse files
authored
[4] Add cocotron-compatible exception frame handling (#15)
1 parent 563425f commit 3218c92

File tree

1 file changed

+88
-9
lines changed

1 file changed

+88
-9
lines changed

libobjc2/eh_personality.c

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stdlib.h>
22
#include <stdio.h>
33
#include <string.h>
4+
#include <setjmp.h>
45
#include "dwarf_eh.h"
56
#include "objc/runtime.h"
67
#include "objc/hooks.h"
@@ -29,6 +30,17 @@ __attribute__((weak)) void *__cxa_begin_catch(void *e);
2930
__attribute__((weak)) void __cxa_end_catch(void);
3031
__attribute__((weak)) void __cxa_rethrow(void);
3132

33+
#if defined(__HELIUM__)
34+
typedef void NSUncaughtExceptionHandler(id exception);
35+
36+
typedef struct NSExceptionFrame {
37+
jmp_buf state;
38+
struct NSExceptionFrame *parent;
39+
id exception;
40+
} NSExceptionFrame;
41+
typedef struct NSExceptionFrame objc_exception_frame;
42+
43+
#endif
3244

3345
/**
3446
* Class of exceptions to distinguish between this and other exception types.
@@ -96,6 +108,10 @@ struct thread_data
96108
id lastThrownObject;
97109
BOOL cxxCaughtException;
98110
struct objc_exception *caughtExceptions;
111+
#if defined(__HELIUM__)
112+
NSExceptionFrame *exception_frame;
113+
NSUncaughtExceptionHandler *uncaught_exception_handler;
114+
#endif
99115
};
100116

101117
static __thread struct thread_data thread_data;
@@ -748,21 +764,84 @@ void objc_exception_rethrow(struct _Unwind_Exception *e)
748764
}
749765

750766
#if defined(__HELIUM__)
751-
// exception handling hooks needed for cocotron foundation
752-
// FIXME: make these do stuff
767+
// Emulate the cocotron runtime's exception handling
753768

754-
typedef struct NSExceptionFrame {
755-
/*jmp_buf*/ long state;
756-
struct NSExceptionFrame *parent;
757-
/*NSException*/ void *exception;
758-
} NSExceptionFrame;
769+
static NSUncaughtExceptionHandler *uncaughtExceptionHandler = NULL;
770+
771+
OBJC_PUBLIC NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void) {
772+
return uncaughtExceptionHandler;
773+
}
774+
775+
OBJC_PUBLIC void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *proc) {
776+
uncaughtExceptionHandler = proc;
777+
}
778+
779+
OBJC_PUBLIC NSExceptionFrame *NSThreadCurrentHandler(void) {
780+
struct thread_data *td = get_thread_data_fast();
781+
return td->exception_frame;
782+
}
783+
784+
OBJC_PUBLIC void NSThreadSetCurrentHandler(NSExceptionFrame *handler) {
785+
struct thread_data *td = get_thread_data_fast();
786+
td->exception_frame = handler;
787+
}
788+
789+
OBJC_PUBLIC NSUncaughtExceptionHandler *NSThreadUncaughtExceptionHandler(void) {
790+
struct thread_data *td = get_thread_data_fast();
791+
return td->uncaught_exception_handler;
792+
}
793+
794+
OBJC_PUBLIC void NSThreadSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *function) {
795+
struct thread_data *td = get_thread_data_fast();
796+
td->uncaught_exception_handler = function;
797+
}
759798

760799
OBJC_PUBLIC void __NSPushExceptionFrame(NSExceptionFrame *frame) {
761-
printf("NSPushExceptionFrame\n");
800+
frame->parent = NSThreadCurrentHandler();
801+
frame->exception = nil;
802+
NSThreadSetCurrentHandler(frame);
762803
}
763804

764805
OBJC_PUBLIC void __NSPopExceptionFrame(NSExceptionFrame *frame) {
765-
printf("NSPopExceptionFrame\n");
806+
NSThreadSetCurrentHandler(frame->parent);
807+
}
808+
809+
static void defaultHandler(id exception) {
810+
__builtin_trap();
811+
fprintf(stderr, "*** Uncaught exception\n");
812+
}
813+
814+
OBJC_PUBLIC int objc_exception_match(Class exceptionClass, id exception) {
815+
return isKindOfClass(object_getClass(exception), exceptionClass);
816+
}
817+
818+
OBJC_PUBLIC id _NSRaiseException(id exception) {
819+
NSExceptionFrame *top = NSThreadCurrentHandler();
820+
if(top == NULL) {
821+
NSUncaughtExceptionHandler *proc = NSGetUncaughtExceptionHandler();
822+
if(proc == NULL) {
823+
defaultHandler(exception);
824+
} else {
825+
proc(exception);
826+
}
827+
} else {
828+
NSThreadSetCurrentHandler(top->parent);
829+
top->exception = exception;
830+
longjmp(top->state, 1);
831+
}
832+
}
833+
834+
void objc_exception_try_enter(void *exceptionFrame) {
835+
__NSPushExceptionFrame((NSExceptionFrame *)exceptionFrame);
836+
}
837+
838+
void objc_exception_try_exit(void *exceptionFrame) {
839+
__NSPopExceptionFrame((NSExceptionFrame *)exceptionFrame);
840+
}
841+
842+
id objc_exception_extract(void *exceptionFrame) {
843+
NSExceptionFrame *frame = (NSExceptionFrame *)exceptionFrame;
844+
return (id)frame->exception;
766845
}
767846

768847
#endif

0 commit comments

Comments
 (0)