Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -261,10 +261,50 @@ AS_IF([test x"$enable_seluid24" = x"yes"], [ AC_DEFINE(OF_SELUID24, 1, [Whether to use 24 bit selector UIDs]) ]) + + AC_MSG_CHECKING(for exception type) + AC_TRY_COMPILE([ + extern void foo(); + ], [ + @try { + foo(); + } @finally { + foo(); + } + ], [ + AS_IF([$EGREP __gnu_objc_personality_v0 \ + conftest.$ac_objext >/dev/null], [ + exception_type="DWARF" + ]) + AS_IF([$EGREP __gnu_objc_personality_sj0 \ + conftest.$ac_objext >/dev/null], [ + exception_type="SjLj" + ]) + + case $exception_type in + DWARF) + AC_DEFINE(HAVE_DWARF_EXCEPTIONS, 1, + [Whether DWARF exceptions are used]) + ;; + SjLj) + AC_DEFINE(HAVE_SJLJ_EXCEPTIONS, 1, + [Whether SjLj exceptions are used]) + ;; + *) + AC_MSG_RESULT(unknown) + AC_MSG_ERROR([Exception type not detected!]) + ;; + esac + + AC_MSG_RESULT($exception_type) + ], [ + AC_MSG_RESULT(exceptions unavailable!) + AC_MSG_ERROR([Exceptions not accepted by compiler!]) + ]) ;; "Apple runtime") AC_DEFINE(OF_APPLE_RUNTIME, 1, [Whether we use the Apple ObjC runtime]) Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -113,11 +113,16 @@ uintptr_t typestable_base; uint8_t callsites_enc; const uint8_t *callsites, *actiontable; }; +#ifndef HAVE_SJLJ_EXCEPTIONS extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*); +#else +extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException( + struct _Unwind_Exception*); +#endif extern void* _Unwind_GetLanguageSpecificData(struct _Unwind_Context*); extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context*); extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context*); extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context*); @@ -166,10 +171,20 @@ extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*); extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t); extern void _Unwind_SetGR(struct _Unwind_Context*, int, uintptr_t); #endif + +#if defined(HAVE_DWARF_EXCEPTIONS) +# define PERSONALITY __gnu_objc_personality_v0 +# define RAISE_EXCEPTION _Unwind_RaiseException +#elif defined(HAVE_SJLJ_EXCEPTIONS) +# define PERSONALITY __gnu_objc_personality_sj0 +# define RAISE_EXCEPTION _Unwind_SjLj_RaiseException +#else +# error Unknown exception type! +#endif static objc_uncaught_exception_handler uncaught_exception_handler; static uint64_t read_uleb128(const uint8_t **ptr) @@ -337,16 +352,16 @@ static bool find_callsite(struct _Unwind_Context *ctx, struct lsda *lsda, uintptr_t *landingpad, const uint8_t **actionrecords) { uintptr_t ip = _Unwind_GetIP(ctx); - const uint8_t *ptr; + const uint8_t *ptr = lsda->callsites; *landingpad = 0; *actionrecords = NULL; - ptr = lsda->callsites; +#ifndef HAVE_SJLJ_EXCEPTIONS while (ptr < lsda->actiontable) { uintptr_t callsite_start, callsite_len, callsite_landingpad; uintptr_t callsite_action; callsite_start = lsda->region_start + @@ -371,10 +386,27 @@ return true; } } return false; +#else + uintptr_t callsite_landingpad, callsite_action; + + if ((uintptr_t)ip < 1) + return false; + + do { + callsite_landingpad = (uintptr_t)read_uleb128(&ptr); + callsite_action = (uintptr_t)read_uleb128(&ptr); + } while (--ip > 1); + + *landingpad = callsite_landingpad + 1; + if (callsite_action != 0) + *actionrecords = lsda->actiontable + callsite_action - 1; + + return true; +#endif } static bool class_matches(Class class, id object) { @@ -458,11 +490,11 @@ return 0; } #if defined(__arm__) || defined(__ARM__) _Unwind_Reason_Code -__gnu_objc_personality_v0(uint32_t state, struct _Unwind_Exception *ex, +PERSONALITY(uint32_t state, struct _Unwind_Exception *ex, struct _Unwind_Context *ctx) { int version = 1; uint64_t ex_class = ex->class; int actions; @@ -483,11 +515,11 @@ } _Unwind_SetGR(ctx, 12, (uintptr_t)ex); #else _Unwind_Reason_Code -__gnu_objc_personality_v0(int version, int actions, uint64_t ex_class, +PERSONALITY(int version, int actions, uint64_t ex_class, struct _Unwind_Exception *ex, struct _Unwind_Context *ctx) { #endif struct objc_exception *e = (struct objc_exception*)ex; bool foreign = (ex_class != objc_exception_class); @@ -594,11 +626,11 @@ memset(e, 0, sizeof(*e)); e->exception.class = objc_exception_class; e->exception.cleanup = cleanup; e->object = object; - if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK && + if (RAISE_EXCEPTION(&e->exception) == _URC_END_OF_STACK && uncaught_exception_handler != NULL) uncaught_exception_handler(object); abort(); }