x86: Fix MSVC runtime checks interop (#612) MSVC can add runtime code that checks if a stack frame is mismanaged, however our custom assembly deliberately accesses and modifies the parent stack frame. Fortunately we can disable that specific check for the function call so do that. Co-authored-by: Matthew Waters <matthew@centricular.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
diff --git a/src/x86/ffi.c b/src/x86/ffi.c
index b4d0d39..26dbc05 100644
--- a/src/x86/ffi.c
+++ b/src/x86/ffi.c
@@ -256,6 +256,13 @@ static const struct abi_params abi_params[FFI_LAST_ABI] = {
extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN;
+/* We perform some black magic here to use some of the parent's stack frame in
+ * ffi_call_i386() that breaks with the MSVC compiler with the /RTCs or /GZ
+ * flags. Disable the 'Stack frame run time error checking' for this function
+ * so we don't hit weird exceptions in debug builds. */
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", off)
+#endif
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
@@ -391,6 +398,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_call_i386 (frame, stack);
}
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", restore)
+#endif
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
diff --git a/src/x86/ffiw64.c b/src/x86/ffiw64.c
index 6c28d59..6870d07 100644
--- a/src/x86/ffiw64.c
+++ b/src/x86/ffiw64.c
@@ -108,6 +108,13 @@ EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
return FFI_OK;
}
+/* We perform some black magic here to use some of the parent's stack frame in
+ * ffi_call_win64() that breaks with the MSVC compiler with the /RTCs or /GZ
+ * flags. Disable the 'Stack frame run time error checking' for this function
+ * so we don't hit weird exceptions in debug builds. */
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", off)
+#endif
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
@@ -172,6 +179,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_call_win64 (stack, frame, closure);
}
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", restore)
+#endif
void
EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)