Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support compiling on msys2/ucrt64 (no exception handling) #254

Merged
merged 1 commit into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down Expand Up @@ -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}")
Expand All @@ -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})
Expand All @@ -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()

Expand Down
6 changes: 6 additions & 0 deletions common.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
18 changes: 11 additions & 7 deletions eh_personality.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,25 +550,29 @@ 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);
get_thread_data()->cxxCaughtException = NO;
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)
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion objc/hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions objc_msgSend.x86-32.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does MSYS not support CFG?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this recently landed: https://sourceforge.net/p/mingw-w64/mailman/message/37712869/, I’ll have a closer look later today/tomorrow

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mingw does support CFG, I've reverted this change.

call *CDECL(__guard_check_icall_fptr)
#endif
jmp *%ecx
Expand All @@ -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
Expand Down Expand Up @@ -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
10 changes: 6 additions & 4 deletions objc_msgSend.x86-64.S
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@

12:
#endif // WITH_TRACING
#ifdef _WIN64
#ifdef _MSC_VER
mov %r10, %rax
jmp *__guard_dispatch_icall_fptr(%rip)
#else
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions objcxx_eh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
41 changes: 27 additions & 14 deletions unwind-itanium.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,26 @@ 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 *);
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

Expand All @@ -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
Expand Down Expand Up @@ -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 */