Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -59,6 +59,6 @@ FRAMEWORK_LIBS = ${LIBS} # For 68000, GCC emits calls to helper functions that expect a4 to be set. # Remove this once the library is using -fbaserel. AMIGA_LIB_CFLAGS += -mcpu=68020 -AMIGA_LIB_LDFLAGS += -mcpu=68020 +AMIGA_LIB_LDFLAGS += -mcpu=68020 -nostdlib -lnix Index: src/runtime/ObjFW_RT.h ================================================================== --- src/runtime/ObjFW_RT.h +++ src/runtime/ObjFW_RT.h @@ -325,10 +325,14 @@ extern void objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong); extern void objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong); extern void objc_enumerationMutation(id _Nonnull obj); +# ifndef OBJC_NO_PERSONALITY_DECLARATION +extern int __gnu_objc_personality_v0(int version, int actions, + uint64_t ex_class, void *_Nonnull ex, void *_Nonnull ctx); +# endif #ifdef __cplusplus } #endif #endif Index: src/runtime/ObjFW_RT.sfd ================================================================== --- src/runtime/ObjFW_RT.sfd +++ src/runtime/ObjFW_RT.sfd @@ -22,10 +22,11 @@ id glue_objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)(a0,a1,d0,d1) void glue_objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy)(a0,a1,d0,a2,d1,d2) void glue_objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) void glue_objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) void glue_objc_enumerationMutation(id _Nonnull obj)(a0) +int glue___gnu_objc_personality_v0(int version, int actions, uint64_t *_Nonnull ex_class, void *_Nonnull ex, void *_Nonnull ctx)(d0,d1,d2,a0,a1) * Functions declared in ObjFW_RT.h SEL _Nonnull sel_registerName(const char *_Nonnull name)(a0) const char *_Nonnull sel_getName(SEL _Nonnull sel)(a0) bool sel_isEqual(SEL _Nonnull sel1, SEL _Nonnull sel2)(a0,a1) Class _Nonnull objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extra_bytes)(a0,a1,d0) Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -138,5 +138,13 @@ void glue_objc_enumerationMutation(id obj OBJC_M68K_REG("a0")) { objc_enumerationMutation(obj); } + +int +glue___gnu_objc_personality_v0(int version OBJC_M68K_REG("d0"), + int actions OBJC_M68K_REG("d1"), uint64_t *ex_class OBJC_M68K_REG("d2"), + void *ex OBJC_M68K_REG("a0"), void *ctx OBJC_M68K_REG("a1")) +{ + return __gnu_objc_personality_v0(version, actions, *ex_class, ex, ctx); +} Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -41,28 +41,29 @@ return -1; } struct ObjFWRTBase { struct Library library; - BPTR seg_list; + void *seg_list; bool initialized; }; + +extern uintptr_t __CTOR_LIST__[], __DTOR_LIST__[]; +extern const void *_EH_FRAME_BEGINS__; +extern void *_EH_FRAME_OBJECTS__; struct ExecBase *SysBase; #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif -struct WBStartup *_WBenchMsg; struct objc_libc *libc; FILE *stdout; FILE *stderr; -extern uintptr_t __CTOR_LIST__[]; -extern uintptr_t __DTOR_LIST__[]; static struct Library * lib_init(struct ExecBase *exec_base OBJC_M68K_REG("a6"), - BPTR seg_list OBJC_M68K_REG("a0"), + void *seg_list OBJC_M68K_REG("a0"), struct ObjFWRTBase *base OBJC_M68K_REG("d0")) { SysBase = exec_base; base->seg_list = seg_list; @@ -79,14 +80,14 @@ base->library.lib_Flags &= ~LIBF_DELEXP; return &base->library; } -static BPTR +static void * expunge(struct ObjFWRTBase *base) { - BPTR seg_list; + void *seg_list; if (base->library.lib_OpenCnt > 0) { base->library.lib_Flags |= LIBF_DELEXP; return 0; } @@ -98,38 +99,36 @@ base->library.lib_NegSize + base->library.lib_PosSize); return seg_list; } -static BPTR +static void * OBJC_M68K_FUNC(lib_expunge, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) return expunge(base); } -static BPTR +static void * OBJC_M68K_FUNC(lib_close, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) + if (base->initialized && + (size_t)_EH_FRAME_BEGINS__ == (size_t)_EH_FRAME_OBJECTS__) + for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) + libc->__deregister_frame_info((&_EH_FRAME_BEGINS__)[i]); + if (--base->library.lib_OpenCnt == 0 && (base->library.lib_Flags & LIBF_DELEXP)) return expunge(base); - if (base->initialized) { - for (uintptr_t *iter = &__DTOR_LIST__[1]; *iter != 0; iter++) { - void (*dtor)(void) = (void (*)(void))*iter++; - dtor(); - } - } - return 0; } -static BPTR +static void * lib_null(void) { return 0; } @@ -141,10 +140,15 @@ libc = libc_; stdout = libc->stdout_; stderr = libc->stderr_; + + if ((size_t)_EH_FRAME_BEGINS__ == (size_t)_EH_FRAME_OBJECTS__) + for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) + libc->__register_frame_info((&_EH_FRAME_BEGINS__)[i], + (&_EH_FRAME_OBJECTS__)[i]); iter0 = &__CTOR_LIST__[1]; for (iter = iter0; *iter != 0; iter++); while (iter > iter0) { @@ -207,10 +211,76 @@ void abort(void) { libc->abort(); } + +int +_Unwind_RaiseException(void *ex) +{ + return libc->_Unwind_RaiseException(ex); +} + +void +_Unwind_DeleteException(void *ex) +{ + libc->_Unwind_DeleteException(ex); +} + +void * +_Unwind_GetLanguageSpecificData(void *ctx) +{ + return libc->_Unwind_GetLanguageSpecificData(ctx); +} + +uintptr_t +_Unwind_GetRegionStart(void *ctx) +{ + return libc->_Unwind_GetRegionStart(ctx); +} + +uintptr_t +_Unwind_GetDataRelBase(void *ctx) +{ + return libc->_Unwind_GetDataRelBase(ctx); +} + +uintptr_t +_Unwind_GetTextRelBase(void *ctx) +{ + return libc->_Unwind_GetTextRelBase(ctx); +} + +uintptr_t +_Unwind_GetIP(void *ctx) +{ + return libc->_Unwind_GetIP(ctx); +} + +uintptr_t +_Unwind_GetGR(void *ctx, int gr) +{ + return libc->_Unwind_GetGR(ctx, gr); +} + +void +_Unwind_SetIP(void *ctx, uintptr_t ip) +{ + libc->_Unwind_SetIP(ctx, ip); +} + +void +_Unwind_SetGR(void *ctx, int gr, uintptr_t value) +{ + libc->_Unwind_SetGR(ctx, gr, value); +} + +void +_Unwind_Resume(void *ex) +{ + libc->_Unwind_Resume(ex); +} #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" static CONST_APTR function_table[] = { (CONST_APTR)lib_open, @@ -226,11 +296,11 @@ ULONG data_size; CONST_APTR *function_table; ULONG *data_table; struct Library *(*init_func)( struct ExecBase *exec_base OBJC_M68K_REG("a6"), - BPTR seg_list OBJC_M68K_REG("a0"), + void *seg_list OBJC_M68K_REG("a0"), struct ObjFWRTBase *base OBJC_M68K_REG("d0")); } init_table = { sizeof(struct ObjFWRTBase), function_table, NULL, Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -14,10 +14,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#define OBJC_NO_PERSONALITY_DECLARATION #include #include #include Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -23,10 +23,24 @@ #include #include #include +extern int _Unwind_RaiseException(void *); +extern void _Unwind_DeleteException(void *); +extern void *_Unwind_GetLanguageSpecificData(void *); +extern uintptr_t _Unwind_GetRegionStart(void *); +extern uintptr_t _Unwind_GetDataRelBase(void *); +extern uintptr_t _Unwind_GetTextRelBase(void *); +extern uintptr_t _Unwind_GetIP(void *); +extern uintptr_t _Unwind_GetGR(void *, int); +extern void _Unwind_SetIP(void *, uintptr_t); +extern void _Unwind_SetGR(void *, int, uintptr_t); +extern void _Unwind_Resume(void *); +extern void __register_frame_info(const void *, void *); +extern void __deregister_frame_info(const void *); + struct Library *ObjFWRTBase; static void __attribute__((__constructor__)) init(void) { @@ -48,10 +62,24 @@ .free = free, .vfprintf = vfprintf, .fputs = fputs, .exit = exit, .abort = abort, + ._Unwind_RaiseException = _Unwind_RaiseException, + ._Unwind_DeleteException = _Unwind_DeleteException, + ._Unwind_GetLanguageSpecificData = + _Unwind_GetLanguageSpecificData, + ._Unwind_GetRegionStart = _Unwind_GetRegionStart, + ._Unwind_GetDataRelBase = _Unwind_GetDataRelBase, + ._Unwind_GetTextRelBase = _Unwind_GetTextRelBase, + ._Unwind_GetIP = _Unwind_GetIP, + ._Unwind_GetGR = _Unwind_GetGR, + ._Unwind_SetIP = _Unwind_SetIP, + ._Unwind_SetGR = _Unwind_SetGR, + ._Unwind_Resume = _Unwind_Resume, + .__register_frame_info = __register_frame_info, + .__deregister_frame_info = __deregister_frame_info, .stdout_ = stdout, .stderr_ = stderr }; objc_init(&libc); @@ -130,11 +158,22 @@ } void objc_exception_throw(id object) { - glue_objc_exception_throw(object); + /* + * This does not use the glue code to hack around a compiler bug. + * + * When using the generated inline stubs, the compiler does not emit + * any frame information, making the unwind fail. As unwind always + * starts from objc_exception_throw(), this means exceptions would + * never work. If, however, we're using a function pointer instead of + * the inline stub, the compiler does generate a frame and everything + * works fine. + */ + uintptr_t throw = (((uintptr_t)ObjFWRTBase) - 0x60); + ((void (*)(id OBJC_M68K_REG("a0")))throw)(object); OF_UNREACHABLE } int @@ -179,5 +218,13 @@ void objc_enumerationMutation(id obj) { glue_objc_enumerationMutation(obj); } + +int +__gnu_objc_personality_v0(int version, int actions, uint64_t ex_class, + void *ex, void *ctx) +{ + return glue___gnu_objc_personality_v0(version, actions, &ex_class, + ex, ctx); +} Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -143,10 +143,23 @@ void (*free)(void *); int (*vfprintf)(FILE *, const char *, va_list); int (*fputs)(const char *, FILE *); void (*exit)(int); void (*abort)(void); + int (*_Unwind_RaiseException)(void *_Nonnull); + void (*_Unwind_DeleteException)(void *_Nonnull); + void *(*_Unwind_GetLanguageSpecificData)(void *_Nonnull); + uintptr_t (*_Unwind_GetRegionStart)(void *_Nonnull); + uintptr_t (*_Unwind_GetDataRelBase)(void *_Nonnull); + uintptr_t (*_Unwind_GetTextRelBase)(void *_Nonnull); + uintptr_t (*_Unwind_GetIP)(void *_Nonnull); + uintptr_t (*_Unwind_GetGR)(void *_Nonnull, int); + void (*_Unwind_SetIP)(void *_Nonnull, uintptr_t); + void (*_Unwind_SetGR)(void *_Nonnull, int, uintptr_t); + void (*_Unwind_Resume)(void *); + void (*__register_frame_info)(const void *, void *); + void (*__deregister_frame_info)(const void *); FILE *stdout_; FILE *stderr_; } *objc_libc; #endif @@ -193,10 +206,15 @@ extern void glue_objc_setPropertyStruct(void *_Nonnull dest OBJC_M68K_REG("a0"), const void *_Nonnull src OBJC_M68K_REG("a1"), ptrdiff_t size OBJC_M68K_REG("d0"), bool atomic OBJC_M68K_REG("d1"), bool strong OBJC_M68K_REG("d2")); extern void glue_objc_enumerationMutation(id _Nonnull obj OBJC_M68K_REG("a0")); +extern int glue___gnu_objc_personality_v0(int version OBJC_M68K_REG("d0"), + int actions OBJC_M68K_REG("d1"), + uint64_t *_Nonnull ex_class OBJC_M68K_REG("d2"), + void *_Nonnull ex OBJC_M68K_REG("a0"), + void *_Nonnull ctx OBJC_M68K_REG("a1")); #endif extern void objc_register_all_categories(struct objc_abi_symtab *_Nonnull); extern struct objc_category *_Nullable *_Nullable objc_categories_for_class(Class _Nonnull);