|
1 | 1 | #include <stdlib.h>
|
2 | 2 | #include <stdio.h>
|
3 | 3 | #include <string.h>
|
| 4 | +#include <setjmp.h> |
4 | 5 | #include "dwarf_eh.h"
|
5 | 6 | #include "objc/runtime.h"
|
6 | 7 | #include "objc/hooks.h"
|
@@ -29,6 +30,17 @@ __attribute__((weak)) void *__cxa_begin_catch(void *e);
|
29 | 30 | __attribute__((weak)) void __cxa_end_catch(void);
|
30 | 31 | __attribute__((weak)) void __cxa_rethrow(void);
|
31 | 32 |
|
| 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 |
32 | 44 |
|
33 | 45 | /**
|
34 | 46 | * Class of exceptions to distinguish between this and other exception types.
|
@@ -96,6 +108,10 @@ struct thread_data
|
96 | 108 | id lastThrownObject;
|
97 | 109 | BOOL cxxCaughtException;
|
98 | 110 | struct objc_exception *caughtExceptions;
|
| 111 | +#if defined(__HELIUM__) |
| 112 | + NSExceptionFrame *exception_frame; |
| 113 | + NSUncaughtExceptionHandler *uncaught_exception_handler; |
| 114 | +#endif |
99 | 115 | };
|
100 | 116 |
|
101 | 117 | static __thread struct thread_data thread_data;
|
@@ -748,21 +764,84 @@ void objc_exception_rethrow(struct _Unwind_Exception *e)
|
748 | 764 | }
|
749 | 765 |
|
750 | 766 | #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 |
753 | 768 |
|
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 | +} |
759 | 798 |
|
760 | 799 | OBJC_PUBLIC void __NSPushExceptionFrame(NSExceptionFrame *frame) {
|
761 |
| - printf("NSPushExceptionFrame\n"); |
| 800 | + frame->parent = NSThreadCurrentHandler(); |
| 801 | + frame->exception = nil; |
| 802 | + NSThreadSetCurrentHandler(frame); |
762 | 803 | }
|
763 | 804 |
|
764 | 805 | 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; |
766 | 845 | }
|
767 | 846 |
|
768 | 847 | #endif
|
|
0 commit comments