diff --git a/CMakeLists.txt b/CMakeLists.txt index d55a8e29..95c2fa54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,12 +114,12 @@ set(libBlocksRuntime_COMPATIBILITY_HDRS set(libobjc_CXX_SRCS selector_table.cc ) -# Windows does not use DWARF EH -if (WIN32) +# Windows does not use DWARF EH, except when using the GNU ABI (MinGW) +if (WIN32 AND NOT MINGW) list(APPEND libobjc_CXX_SRCS eh_win32_msvc.cc) else () list(APPEND libobjc_C_SRCS eh_personality.c) -endif (WIN32) +endif (WIN32 AND NOT MINGW) find_package(tsl-robin-map) @@ -132,7 +132,7 @@ if (NOT tls-robin-map_FOUND) FetchContent_MakeAvailable(robinmap) endif() -if (WIN32) +if (WIN32 AND NOT MINGW) set(OLD_ABI_COMPAT_DEFAULT false) else() set(OLD_ABI_COMPAT_DEFAULT true) @@ -189,7 +189,7 @@ if(WIN32) endif() -if (MSVC) +if (WIN32 AND NOT MINGW) set(ASSEMBLER ${CMAKE_ASM_COMPILER} CACHE STRING "Assembler to use with Visual Studio (must be gcc / clang!)") message(STATUS "Using custom build commands to work around CMake bugs") message(STATUS "ASM compiler: ${ASSEMBLER}") @@ -210,7 +210,7 @@ endif() -if (WIN32) +if (WIN32 AND NOT MINGW) message(STATUS "Using MSVC-compatible exception model") else () separate_arguments(EH_PERSONALITY_FLAGS NATIVE_COMMAND ${CMAKE_CXX_FLAGS}) @@ -234,7 +234,7 @@ target_sources(objc PRIVATE ${libobjc_CXX_SRCS}) include(FindThreads) target_link_libraries(objc Threads::Threads) # Link against ntdll.dll for RtlRaiseException -if (WIN32) +if (WIN32 AND NOT MINGW) target_link_libraries(objc ntdll.dll) endif() diff --git a/common.S b/common.S index 4e797e24..182d967d 100644 --- a/common.S +++ b/common.S @@ -10,3 +10,9 @@ #define TYPE_DIRECTIVE(symbol, symboltype) #endif +#if defined(_MSC_VER) && defined(__i386__) +#define STRINGIFY(a) #a +#define EXPORT_SYMBOL(symbol) .ascii " " STRINGIFY(/EXPORT:_##symbol) +#else +#define EXPORT_SYMBOL(symbol) .ascii " /EXPORT:" #symbol +#endif diff --git a/eh_personality.c b/eh_personality.c index 1910f061..d638d977 100644 --- a/eh_personality.c +++ b/eh_personality.c @@ -550,9 +550,9 @@ static inline _Unwind_Reason_Code internal_objc_personality(int version, } } - _Unwind_SetIP(context, (unsigned long)action.landing_pad); + _Unwind_SetIP(context, (uintptr_t)action.landing_pad); _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), - (unsigned long)(isNew ? exceptionObject : object)); + (uintptr_t)(isNew ? exceptionObject : object)); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector); DEBUG_LOG("Installing context, selector %d\n", (int)selector); @@ -560,15 +560,19 @@ static inline _Unwind_Reason_Code internal_objc_personality(int version, return _URC_INSTALL_CONTEXT; } +OBJC_PUBLIC BEGIN_PERSONALITY_FUNCTION(__gnu_objc_personality_v0) return internal_objc_personality(version, actions, exceptionClass, exceptionObject, context, NO); } + +OBJC_PUBLIC BEGIN_PERSONALITY_FUNCTION(__gnustep_objc_personality_v0) return internal_objc_personality(version, actions, exceptionClass, exceptionObject, context, YES); } +OBJC_PUBLIC BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0) #ifndef NO_OBJCXX if (cxx_exception_class == 0) @@ -584,11 +588,11 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0) } // We now have two copies of the _Unwind_Exception object (which stores // state for the unwinder) in flight. Make sure that they're in sync. - COPY_EXCEPTION(ex->cxx_exception, exceptionObject) + COPY_EXCEPTION(ex->cxx_exception, exceptionObject); exceptionObject = ex->cxx_exception; exceptionClass = cxx_exception_class; int ret = CALL_PERSONALITY_FUNCTION(__gxx_personality_v0); - COPY_EXCEPTION(exceptionObject, ex->cxx_exception) + COPY_EXCEPTION(exceptionObject, ex->cxx_exception); if (ret == _URC_INSTALL_CONTEXT) { get_thread_data()->cxxCaughtException = YES; @@ -599,7 +603,7 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0) return CALL_PERSONALITY_FUNCTION(__gxx_personality_v0); } -id objc_begin_catch(struct _Unwind_Exception *exceptionObject) +OBJC_PUBLIC id objc_begin_catch(struct _Unwind_Exception *exceptionObject) { struct thread_data *td = get_thread_data(); DEBUG_LOG("Beginning catch %p\n", exceptionObject); @@ -671,7 +675,7 @@ id objc_begin_catch(struct _Unwind_Exception *exceptionObject) return (id)((char*)exceptionObject + sizeof(struct _Unwind_Exception)); } -void objc_end_catch(void) +OBJC_PUBLIC void objc_end_catch(void) { struct thread_data *td = get_thread_data_fast(); // If this is a boxed foreign exception then the boxing class is @@ -717,7 +721,7 @@ void objc_end_catch(void) } } -void objc_exception_rethrow(struct _Unwind_Exception *e) +OBJC_PUBLIC void objc_exception_rethrow(struct _Unwind_Exception *e) { struct thread_data *td = get_thread_data_fast(); // If this is an Objective-C exception, then diff --git a/objc/hooks.h b/objc/hooks.h index 21491b15..51b88b2d 100644 --- a/objc/hooks.h +++ b/objc/hooks.h @@ -47,7 +47,7 @@ OBJC_PUBLIC extern struct objc_slot *(*__objc_msg_forward3)(id, SEL) OBJC_DEPREC */ OBJC_PUBLIC extern IMP (*__objc_msg_forward2)(id, SEL); -#ifndef _WIN32 +#ifndef _MSC_VER /** * Hook defined for handling unhandled exceptions. If the unwind library * reaches the end of the stack without finding a handler then this hook is diff --git a/objc_msgSend.x86-32.S b/objc_msgSend.x86-32.S index b590e7fe..99b4f4eb 100644 --- a/objc_msgSend.x86-32.S +++ b/objc_msgSend.x86-32.S @@ -37,7 +37,7 @@ test %eax, %eax jz 5f # Nil slot - invoke some kind of forwarding mechanism mov SLOT_OFFSET(%eax), %ecx -#ifdef _WIN32 +#ifdef _MSC_VER call *CDECL(__guard_check_icall_fptr) #endif jmp *%ecx @@ -62,7 +62,7 @@ add $12, %esp # restore the stack -#ifdef _WIN32 +#ifdef _MSC_VER mov %eax, %ecx call *CDECL(__guard_check_icall_fptr) jmp *%ecx @@ -126,7 +126,7 @@ CDECL(objc_msgSend_stret): #ifdef _WIN32 .section .drectve,"yn" - .ascii " /EXPORT:_objc_msgSend" - .ascii " /EXPORT:_objc_msgSend_stret" - .ascii " /EXPORT:_objc_msgSend_fpret" + EXPORT_SYMBOL(objc_msgSend) + EXPORT_SYMBOL(objc_msgSend_stret) + EXPORT_SYMBOL(objc_msgSend_fpret) #endif diff --git a/objc_msgSend.x86-64.S b/objc_msgSend.x86-64.S index ab64836f..2d153140 100644 --- a/objc_msgSend.x86-64.S +++ b/objc_msgSend.x86-64.S @@ -193,7 +193,7 @@ 12: #endif // WITH_TRACING -#ifdef _WIN64 +#ifdef _MSC_VER mov %r10, %rax jmp *__guard_dispatch_icall_fptr(%rip) #else @@ -295,9 +295,11 @@ TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function) CDECL(objc_msgSend_stret): MSGSEND objc_msgSend_stret, %rdx, %r8 .section .drectve,"yn" -.ascii " /EXPORT:objc_msgSend" -.ascii " /EXPORT:objc_msgSend_fpret" -.ascii " /EXPORT:objc_msgSend_stret" +EXPORT_SYMBOL(objc_msgSend) + +EXPORT_SYMBOL(objc_msgSend_fpret) + +EXPORT_SYMBOL(objc_msgSend_stret) #else .globl CDECL(objc_msgSend) TYPE_DIRECTIVE(CDECL(objc_msgSend), @function) diff --git a/objcxx_eh.cc b/objcxx_eh.cc index 526ca70d..a8b75709 100644 --- a/objcxx_eh.cc +++ b/objcxx_eh.cc @@ -218,7 +218,7 @@ namespace gnustep /** * Superclass for the type info for Objective-C exceptions. */ - struct __objc_type_info : std::type_info + struct OBJC_PUBLIC __objc_type_info : std::type_info { /** * Constructor that sets the name. @@ -266,7 +266,7 @@ namespace gnustep /** * Singleton type info for the `id` type. */ - struct __objc_id_type_info : __objc_type_info + struct OBJC_PUBLIC __objc_id_type_info : __objc_type_info { /** * The `id` type is mangled to `@id`, which is not a valid mangling @@ -278,7 +278,7 @@ namespace gnustep void **obj, unsigned outer) const; }; - struct __objc_class_type_info : __objc_type_info + struct OBJC_PUBLIC __objc_class_type_info : __objc_type_info { virtual ~__objc_class_type_info(); virtual bool __do_catch(const type_info *thrownType, diff --git a/unwind-itanium.h b/unwind-itanium.h index 01f99304..b1694217 100644 --- a/unwind-itanium.h +++ b/unwind-itanium.h @@ -79,8 +79,12 @@ struct _Unwind_Exception { uint64_t exception_class; _Unwind_Exception_Cleanup_Fn exception_cleanup; +#ifdef __SEH__ + uintptr_t private_[6]; +#else uintptr_t private_1; uintptr_t private_2; +#endif } __attribute__((__aligned__)); extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); @@ -88,13 +92,13 @@ extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); extern void _Unwind_Resume (struct _Unwind_Exception *); extern void _Unwind_DeleteException (struct _Unwind_Exception *); -extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int); -extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long); -extern unsigned long _Unwind_GetIP (struct _Unwind_Context *); -extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *); -extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long); -extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*); -extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, uintptr_t); +extern uintptr_t _Unwind_GetIP (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetIPInfo (struct _Unwind_Context *, int *); +extern void _Unwind_SetIP (struct _Unwind_Context *, uintptr_t); +extern uintptr_t _Unwind_GetLanguageSpecificData (struct _Unwind_Context*); +extern uintptr_t _Unwind_GetRegionStart (struct _Unwind_Context *); #ifdef _GNU_SOURCE @@ -115,17 +119,17 @@ extern _Unwind_Reason_Code /* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why _Unwind_GetBSP() exists. */ -extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetBSP (struct _Unwind_Context *); /* Return the "canonical frame address" for the given context. This is used by NPTL... */ -extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetCFA (struct _Unwind_Context *); /* Return the base-address for data references. */ -extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetDataRelBase (struct _Unwind_Context *); /* Return the base-address for text references. */ -extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *); +extern uintptr_t _Unwind_GetTextRelBase (struct _Unwind_Context *); /* Call _Unwind_Trace_Fn once for each stack-frame, without doing any cleanup. The first frame for which the callback is invoked is the @@ -164,12 +168,21 @@ _Unwind_Reason_Code name(int version,\ #define CALL_PERSONALITY_FUNCTION(name) name(version, actions, exceptionClass, exceptionObject, context) +#ifdef __SEH__ +#define COPY_EXCEPTION(dst, src) \ + do { \ + memcpy((dst)->private_, (src)->private_, sizeof((src)->private_)); \ + } while(0) +#else #define COPY_EXCEPTION(dst, src) \ - (dst)->private_1 = (src)->private_1; \ - (dst)->private_2 = (src)->private_2; + do { \ + (dst)->private_1 = (src)->private_1; \ + (dst)->private_2 = (src)->private_2; \ + } while(0) +#endif #ifdef __cplusplus } #endif -#endif /* _UNWIND_H */ +#endif /* _UNWIND_H */ \ No newline at end of file