summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/Excn.h34
-rw-r--r--rts/RtsMain.c121
-rw-r--r--rts/ghc.mk14
-rw-r--r--rts/win32/OSMem.c2
-rw-r--r--rts/win32/OSThreads.c2
-rw-r--r--rts/win32/Ticker.c1
-rw-r--r--rts/win32/seh_excn.c45
-rw-r--r--rts/win32/seh_excn.h92
-rw-r--r--rts/win32/veh_excn.c100
-rw-r--r--rts/win32/veh_excn.h73
-rw-r--r--testsuite/tests/rts/all.T18
-rw-r--r--testsuite/tests/rts/derefnull.stdout-x86_64-unknown-mingw321
-rw-r--r--testsuite/tests/rts/divbyzero.stdout-x86_64-unknown-mingw321
13 files changed, 277 insertions, 227 deletions
diff --git a/rts/Excn.h b/rts/Excn.h
new file mode 100644
index 0000000000..b393234021
--- /dev/null
+++ b/rts/Excn.h
@@ -0,0 +1,34 @@
+/* -----------------------------------------------------------------------------
+*
+* (c) The GHC Team 1998-2000
+*
+* Hides indirection for EH handlers for different platforms
+*
+* ---------------------------------------------------------------------------*/
+
+#ifndef EXCN_H
+#define EXCN_H
+
+#include "ghcconfig.h"
+
+// On windows Excn provides two macros
+// BEGIN_WINDOWS_VEH_HANDLER and END_WINDOWS_VEH_HANDLER, which
+// will catch such exceptions in the entire process and die by
+// printing a message and calling stg_exit(1).
+//
+// For other operating systems an empty macro is defined so
+// that no #ifdefs are needed around the usage of these macros.
+
+
+#if defined(mingw32_HOST_OS)
+#include "win32/veh_excn.h"
+
+#define BEGIN_WINDOWS_VEH_HANDLER __register_hs_exception_handler();
+#define END_WINDOWS_VEH_HANDLER __unregister_hs_exception_handler();
+#else
+#define BEGIN_WINDOWS_VEH_HANDLER
+#define END_WINDOWS_VEH_HANDLER
+#endif /* mingw32_HOST_OS */
+
+#endif /* EXCN_H */
+
diff --git a/rts/RtsMain.c b/rts/RtsMain.c
index 3cf4f54cec..667c9e4ae2 100644
--- a/rts/RtsMain.c
+++ b/rts/RtsMain.c
@@ -8,6 +8,7 @@
#define COMPILING_RTS_MAIN
+#include "Excn.h"
#include "PosixSource.h"
#include "Rts.h"
#include "RtsAPI.h"
@@ -15,105 +16,81 @@
#include "RtsUtils.h"
#include "Prelude.h"
#include "Task.h"
-#if defined(mingw32_HOST_OS)
-#include "win32/seh_excn.h"
-#endif
#ifdef DEBUG
# include "Printer.h" /* for printing */
#endif
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
+// Hack: we assume that we're building a batch-mode system unless
+// INTERPRETER is set
+
+#ifndef INTERPRETER /* Hack */
-/* Annoying global vars for passing parameters to real_main() below
- * This is to get around problem with Windows SEH, see hs_main(). */
-static int progargc;
-static char **progargv;
-static StgClosure *progmain_closure; /* This will be ZCMain_main_closure */
-static RtsConfig rtsconfig;
+// The rts entry point from a compiled program using a Haskell main
+// function. This gets called from a tiny main function generated by
+// GHC and linked into each compiled Haskell program that uses a
+// Haskell main function.
+//
+// We expect the caller to pass ZCMain_main_closure for
+// main_closure. The reason we cannot refer to this symbol directly
+// is because we're inside the rts and we do not know for sure that
+// we'll be using a Haskell main function.
+//
+// NOTE: This function is marked as _noreturn_ in Main.h
-/* Hack: we assume that we're building a batch-mode system unless
- * INTERPRETER is set
- */
-#ifndef INTERPRETER /* Hack */
-static void real_main(void) GNUC3_ATTRIBUTE(__noreturn__);
-static void real_main(void)
+int hs_main ( int argc, char *argv[], // program args
+ StgClosure *main_closure, // closure for Main.main
+ RtsConfig rts_config) // RTS configuration
+
{
+ BEGIN_WINDOWS_VEH_HANDLER
+
int exit_status;
SchedulerStatus status;
- hs_init_ghc(&progargc, &progargv, rtsconfig);
-
- /* kick off the computation by creating the main thread with a pointer
- to mainIO_closure representing the computation of the overall program;
- then enter the scheduler with this thread and off we go;
-
- the same for GranSim (we have only one instance of this code)
+ hs_init_ghc(&argc, &argv, rts_config);
- in a parallel setup, where we have many instances of this code
- running on different PEs, we should do this only for the main PE
- (IAmMainThread is set in startupHaskell)
- */
+ // kick off the computation by creating the main thread with a pointer
+ // to mainIO_closure representing the computation of the overall program;
+ // then enter the scheduler with this thread and off we go;
+ //
+ // the same for GranSim (we have only one instance of this code)
+ //
+ // in a parallel setup, where we have many instances of this code
+ // running on different PEs, we should do this only for the main PE
+ // (IAmMainThread is set in startupHaskell)
- /* ToDo: want to start with a larger stack size */
+ // ToDo: want to start with a larger stack size
{
Capability *cap = rts_lock();
- rts_evalLazyIO(&cap,progmain_closure, NULL);
+ rts_evalLazyIO(&cap, main_closure, NULL);
status = rts_getSchedStatus(cap);
rts_unlock(cap);
}
- /* check the status of the entire Haskell computation */
+ // check the status of the entire Haskell computation
switch (status) {
case Killed:
- errorBelch("main thread exited (uncaught exception)");
- exit_status = EXIT_KILLED;
- break;
+ errorBelch("main thread exited (uncaught exception)");
+ exit_status = EXIT_KILLED;
+ break;
case Interrupted:
- errorBelch("interrupted");
- exit_status = EXIT_INTERRUPTED;
- break;
+ errorBelch("interrupted");
+ exit_status = EXIT_INTERRUPTED;
+ break;
case HeapExhausted:
- exit_status = EXIT_HEAPOVERFLOW;
- break;
+ exit_status = EXIT_HEAPOVERFLOW;
+ break;
case Success:
- exit_status = EXIT_SUCCESS;
- break;
+ exit_status = EXIT_SUCCESS;
+ break;
default:
- barf("main thread completed with invalid status");
+ barf("main thread completed with invalid status");
}
- shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
-}
-/* The rts entry point from a compiled program using a Haskell main
- * function. This gets called from a tiny main function generated by
- * GHC and linked into each compiled Haskell program that uses a
- * Haskell main function.
- *
- * We expect the caller to pass ZCMain_main_closure for
- * main_closure. The reason we cannot refer to this symbol directly
- * is because we're inside the rts and we do not know for sure that
- * we'll be using a Haskell main function.
- */
-int hs_main (int argc, char *argv[], // program args
- StgClosure *main_closure, // closure for Main.main
- RtsConfig rts_config) // RTS configuration
-{
- /* We do this dance with argc and argv as otherwise the SEH exception
- stuff (the BEGIN/END CATCH below) on Windows gets confused */
- progargc = argc;
- progargv = argv;
- progmain_closure = main_closure;
- rtsconfig = rts_config;
+ END_WINDOWS_VEH_HANDLER
-#if defined(mingw32_HOST_OS) && defined(i386_HOST_ARCH)
- BEGIN_CATCH
-#endif
- real_main();
-#if defined(mingw32_HOST_OS) && defined(i386_HOST_ARCH)
- END_CATCH
-#endif
+ shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
+ // No code beyond this point. Dead code elimination will remove it
}
# endif /* BATCH_MODE */
diff --git a/rts/ghc.mk b/rts/ghc.mk
index c5dc06e0e3..7ba4320f90 100644
--- a/rts/ghc.mk
+++ b/rts/ghc.mk
@@ -177,6 +177,13 @@ endif
rts_dist_$1_CC_OPTS += -DRtsWay=\"rts_$1\"
+# If we're compiling on windows, enforce that we only support XP+
+# Adding this here means it doesn't have to be done in individual .c files
+# and also centralizes the versioning.
+ifeq "$$(TargetOS_CPP)" "mingw32"
+rts_dist_$1_CC_OPTS += -DWINVER=0x0501
+endif
+
ifneq "$$(UseSystemLibFFI)" "YES"
rts_dist_FFI_SO = rts/dist/build/lib$$(LIBFFI_NAME)$$(soext)
else
@@ -313,13 +320,6 @@ endif
#-----------------------------------------------------------------------------
# Flags for compiling specific files
-
-# If RtsMain.c is built with optimisation then the SEH exception stuff on
-# Windows gets confused.
-# This has to be in HC rather than CC opts, as otherwise there's a
-# -optc-O2 that comes after it.
-rts/RtsMain_HC_OPTS += -optc-O0
-
rts/RtsMessages_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
rts/RtsUtils_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
rts/Trace_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
diff --git a/rts/win32/OSMem.c b/rts/win32/OSMem.c
index d9700727a5..afa5113638 100644
--- a/rts/win32/OSMem.c
+++ b/rts/win32/OSMem.c
@@ -6,8 +6,6 @@
*
* ---------------------------------------------------------------------------*/
-#define _WIN32_WINNT 0x0501
-
#include "Rts.h"
#include "sm/OSMem.h"
#include "RtsUtils.h"
diff --git a/rts/win32/OSThreads.c b/rts/win32/OSThreads.c
index c3d3af64d2..0c256127e5 100644
--- a/rts/win32/OSThreads.c
+++ b/rts/win32/OSThreads.c
@@ -7,8 +7,6 @@
*
* --------------------------------------------------------------------------*/
-#define _WIN32_WINNT 0x0501
-
#include "Rts.h"
#include <windows.h>
#if defined(THREADED_RTS)
diff --git a/rts/win32/Ticker.c b/rts/win32/Ticker.c
index 89902e568d..dd04d84118 100644
--- a/rts/win32/Ticker.c
+++ b/rts/win32/Ticker.c
@@ -2,7 +2,6 @@
* RTS periodic timers.
*
*/
-#define _WIN32_WINNT 0x0501
#include "Rts.h"
#include "Ticker.h"
diff --git a/rts/win32/seh_excn.c b/rts/win32/seh_excn.c
deleted file mode 100644
index da5f64d812..0000000000
--- a/rts/win32/seh_excn.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "ghcconfig.h"
-#include "seh_excn.h"
-
-/*
- * Exception / signal handlers.
- */
-#if defined(mingw32_HOST_OS)
-#if defined(i386_HOST_ARCH)
-jmp_buf seh_unwind_to;
-unsigned long seh_excn_code; /* variable used to communicate what kind of exception we've caught;nice. */
-
-EXCEPTION_DISPOSITION
-catchDivZero(struct _EXCEPTION_RECORD* rec,
- void* arg1 __attribute__((unused)),
- struct _CONTEXT* ctxt __attribute__((unused)),
- void* arg2 __attribute__((unused)))
-{
- if ((rec->ExceptionFlags & EH_UNWINDING) != 0) {
- // When the system unwinds the SEH stack after having handled an excn,
- // return immediately.
- return ExceptionContinueSearch;
- }
- switch (rec->ExceptionCode) {
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- seh_excn_code = 0;
- longjmp(seh_unwind_to, rec->ExceptionCode);
- return ExceptionContinueExecution;
- case EXCEPTION_STACK_OVERFLOW:
- seh_excn_code = 1;
- longjmp(seh_unwind_to, rec->ExceptionCode);
- return ExceptionContinueExecution;
- case EXCEPTION_ACCESS_VIOLATION:
- seh_excn_code = 2;
- longjmp(seh_unwind_to, rec->ExceptionCode);
- return ExceptionContinueExecution;
- longjmp(seh_unwind_to, rec->ExceptionCode);
- return ExceptionContinueExecution;
- default: ;
- }
- return ExceptionContinueSearch;
-}
-#endif
-#endif
-
diff --git a/rts/win32/seh_excn.h b/rts/win32/seh_excn.h
deleted file mode 100644
index 8829e840b7..0000000000
--- a/rts/win32/seh_excn.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef WIN32_SEH_EXCN_H
-#define WIN32_SEH_EXCN_H
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(__MINGW32__)
-/* Stuff needed to install and use SEH exception handlers */
-#include <excpt.h>
-#include <setjmp.h>
-#include <windows.h>
-#elif defined(_MSC_VER)
-#include <windows.h>
-#else
-#include <signal.h>
-#endif
-
-/* Exception handling.
- *
- * On Win32, the default action for things like division by zero and
- * segfaults is to pop up an annoying little dialog box.
- *
- * This is a pain when we are SSHed into a Windows machine, or when we
- * want to debug a problem with gdb.
- *
- * seh_excn provides two macros, BEGIN_CATCH and END_CATCH, which
- * will catch such exceptions in the code they bracket and die by
- * printing a message and calling stg_exit(1).
- */
-#define ON_DIV_ZERO fprintf(stdout,"divide by zero\n"); fflush(stdout);stg_exit(1)
-#define ON_STACK_OVERFLOW fprintf(stdout,"C stack overflow in generated code\n"); fflush(stdout); stg_exit(1)
-#define ON_SIGSEGV fprintf(stdout,"Segmentation fault/access violation in generated code\n"); fflush(stdout); stg_exit(1)
-
-#if defined(__MINGW32__)
-extern jmp_buf seh_unwind_to;
-extern unsigned long seh_excn_code;
-/*
- * install an exception handler 'exHandler' which longjmp()s (via 'jumpBuf')
- * to the code 'onExnCaught' when successfully catching an exception.
- *
- * Macro based on Andrew Begel's SEH support code posted to the mingw-users
- * mailing list.
- */
-#define TRY_BEGIN(jumpBuf, exHandler, onExcnCaught) \
- do { \
- int signal; \
- if ((signal = setjmp(jumpBuf)) != 0) { \
- onExcnCaught; \
- } else { \
- __try1(exHandler); \
- } \
- } while (0);
-
-#define TRY_END() __except1
-
-extern
-EXCEPTION_DISPOSITION
-catchDivZero(struct _EXCEPTION_RECORD*,
- void*,
- struct _CONTEXT*,
- void*);
-
-#define ON_EXCN \
- if (seh_excn_code == 1) { \
- ON_STACK_OVERFLOW; \
- } else if ( seh_excn_code == 2 ) { \
- ON_SIGSEGV; \
- } else { \
- ON_DIV_ZERO; \
- }
-
-#define BEGIN_CATCH TRY_BEGIN(seh_unwind_to, catchDivZero, ON_EXCN)
-#define END_CATCH TRY_END()
-#elif defined(_MSC_VER)
-#define BEGIN_CATCH __try {
-#define END_CATCH } __except ( ( ((GetExceptionCode() == EXCEPTION_FLT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) || (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) ) { \
- switch ( (GetExceptionCode()) ) { \
- case EXCEPTION_FLT_DIVIDE_BY_ZERO: \
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- ON_DIV_ZERO; break; \
- case EXCEPTION_STACK_OVERFLOW: \
- ON_STACK_OVERFLOW; break; \
- case EXCEPTION_ACCESS_VIOLATION: \
- ON_SIGSEGV; break; \
- } \
- }
-#else
-#error Cannot determine what sort of Windows system this is
-#endif
-
-#endif /* WIN32_SEH_EXCN_H */
-
diff --git a/rts/win32/veh_excn.c b/rts/win32/veh_excn.c
new file mode 100644
index 0000000000..a24354e9d6
--- /dev/null
+++ b/rts/win32/veh_excn.c
@@ -0,0 +1,100 @@
+/* -----------------------------------------------------------------------------
+*
+* (c) The GHC Team 1998-2000
+*
+* Error Handling implementations for windows
+*
+* ---------------------------------------------------------------------------*/
+
+#include "Rts.h"
+#include "ghcconfig.h"
+#include "veh_excn.h"
+#include <assert.h>
+
+/////////////////////////////////
+// Exception / signal handlers.
+/////////////////////////////////
+
+// Define some values for the ordering of VEH Handlers:
+// - CALL_FIRST means call this exception handler first
+// - CALL_LAST means call this exception handler last
+#define CALL_FIRST 1
+#define CALL_LAST 0
+
+// this should be in <excpt.h>, but it's been removed from MinGW distributions
+#ifndef EH_UNWINDING
+#define EH_UNWINDING 0x02
+#endif /* EH_UNWINDING */
+
+// Registered exception handler
+PVOID __hs_handle = NULL;
+
+long WINAPI __hs_exception_handler(struct _EXCEPTION_POINTERS *exception_data)
+{
+ long action = EXCEPTION_CONTINUE_SEARCH;
+
+ // When the system unwinds the VEH stack after having handled an excn,
+ // return immediately.
+ if ((exception_data->ExceptionRecord->ExceptionFlags & EH_UNWINDING) == 0)
+ {
+
+ // Error handling cases covered by this implementation.
+ switch (exception_data->ExceptionRecord->ExceptionCode) {
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ fprintf(stdout, "divide by zero\n");
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ fprintf(stdout, "C stack overflow in generated code\n");
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ case EXCEPTION_ACCESS_VIOLATION:
+ fprintf(stdout, "Segmentation fault/access violation in generated code\n");
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ default:;
+ }
+
+ // If an error has occurred and we've decided to continue execution
+ // then we've done so to prevent something else from handling the error.
+ // But the correct action is still to exit as fast as possible.
+ if (EXCEPTION_CONTINUE_EXECUTION == action)
+ {
+ fflush(stdout);
+ stg_exit(1);
+ }
+ }
+
+ return action;
+}
+
+void __register_hs_exception_handler( void )
+{
+ // Allow the VEH handler to be registered only once.
+ if (NULL == __hs_handle)
+ {
+ __hs_handle = AddVectoredExceptionHandler(CALL_FIRST, __hs_exception_handler);
+ // should the handler not be registered this will return a null.
+ assert(__hs_handle);
+ }
+ else
+ {
+ errorBelch("There is no need to call __register_hs_exception_handler() twice, VEH handlers are global per process.");
+ }
+}
+
+void __unregister_hs_exception_handler( void )
+{
+ if (__hs_handle != NULL)
+ {
+ // Should the return value be checked? we're terminating anyway.
+ RemoveVectoredExceptionHandler(__hs_handle);
+ __hs_handle = NULL;
+ }
+ else
+ {
+ errorBelch("__unregister_hs_exception_handler() called without having called __register_hs_exception_handler() first.");
+ }
+}
+
diff --git a/rts/win32/veh_excn.h b/rts/win32/veh_excn.h
new file mode 100644
index 0000000000..4223a2ae2d
--- /dev/null
+++ b/rts/win32/veh_excn.h
@@ -0,0 +1,73 @@
+/* -----------------------------------------------------------------------------
+*
+* (c) The GHC Team 1998-2000
+*
+* Header for windows Error Handling implementations
+*
+* ---------------------------------------------------------------------------*/
+
+#ifndef WIN32_VEH_EXCN_H
+#define WIN32_VEH_EXCN_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Rts.h>
+
+// Stuff needed to install and use VEH exception handlers
+#include <excpt.h>
+#include <windows.h>
+
+// Exception handling.
+//
+// On Windows, the default action for things like division by zero and
+// segfaults is to pop up a Dr. Watson error reporting dialog if the exception
+// is unhandled by the user code.
+//
+// This is a pain when we are SSHed into a Windows machine, or when we
+// want to debug a problem with gdb (gdb will get a first and second chance to
+// handle the exception, but if it doesn't the pop-up will show).
+//
+//
+// Previously this code was handled using SEH (Structured Exception Handlers)
+// however each compiler and platform have different ways of dealing with SEH.
+//
+// MSVC compilers have the keywords __try, __catch and __except to have the
+// compiler generate the appropriate SEH handler code for you.
+//
+// MinGW compilers have no such keywords and require you to manually set the
+// SEH Handlers, however because SEH is implemented differently in x86 and x64
+// the methods to use them in GCC differs.
+//
+// x86: SEH is based on the stack, the SEH handlers are available at FS[0].
+// On startup one would only need to add a new handler there. This has
+// a number of issues such as hard to share handlers and it can be exploited.
+//
+// x64: In order to fix the issues with the way SEH worked in x86, on x64 SEH handlers
+// are statically compiled and added to the .pdata section by the compiler.
+// Instead of being thread global they can now be Image global since you have to
+// specify the RVA of the region of code that the handlers govern.
+//
+// You can on x64 Dynamically allocate SEH handlers, but it seems that (based on
+// experimentation and it's very under-documented) that the dynamic calls cannot override
+// static SEH handlers in the .pdata section.
+//
+// Because of this and because GHC no longer needs to support < windows XP, the better
+// alternative for handling errors would be using the in XP introduced VEH.
+//
+// The bonus is because VEH (Vectored Exception Handler) are a runtime construct the API
+// is the same for both x86 and x64 (note that the Context object does contain CPU specific
+// structures) and the calls are the same cross compilers. Which means this file can be
+// simplified quite a bit.
+// Using VEH also means we don't have to worry about the dynamic code generated by GHCi.
+
+// Prototype of the VEH callback function.
+// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms681419(v=vs.85).aspx
+//
+long WINAPI __hs_exception_handler( struct _EXCEPTION_POINTERS *exception_data );
+
+// prototypes to the functions doing the registration and unregistration of the VEH handlers
+void __register_hs_exception_handler( void );
+void __unregister_hs_exception_handler( void );
+
+#endif /* WIN32_VEH_EXCN_H */
+
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 88c354f2f5..86b1bcf162 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -7,8 +7,7 @@ test('testblockalloc',
# only GHCi triggers the bug, but we run the test all ways for completeness.
test('bug1010', normal, compile_and_run, ['+RTS -c -RTS'])
test('derefnull',
- [when(opsys('mingw32'), expect_broken(6079)),
- # LLVM Optimiser considers dereference of a null pointer
+ [# LLVM Optimiser considers dereference of a null pointer
# undefined and marks the code as unreachable which means
# that later optimisations remove it altogether.
omit_ways(['optllvm']),
@@ -21,17 +20,24 @@ test('derefnull',
# SIGBUS on OX X (PPC and x86 only; amd64 gives SEGV)
when(platform('i386-apple-darwin'), exit_code(138)),
when(platform('powerpc-apple-darwin'), exit_code(138)),
- when(opsys('mingw32'), exit_code(1))],
+ when(opsys('mingw32'), exit_code(1)),
+ # since these test are supposed to crash the
+ # profile report will be empty always.
+ # so disable the check for profiling
+ when(opsys('mingw32'), omit_ways(prof_ways))],
compile_and_run, [''])
test('divbyzero',
- [when(opsys('mingw32'), expect_broken(6079)),
- # SIGFPE on Linux
+ [# SIGFPE on Linux
exit_code(136),
# Apparently the output can be different on different
# Linux setups, so just ignore it. As long as we get
# the right exit code we're OK.
when(opsys('linux'), ignore_output),
- when(opsys('mingw32'), exit_code(1))],
+ when(opsys('mingw32'), exit_code(1)),
+ # since these test are supposed to crash the
+ # profile report will be empty always.
+ # so disable the check for profiling
+ when(opsys('mingw32'), omit_ways(prof_ways))],
compile_and_run, [''])
test('outofmem', when(opsys('darwin'), skip),
diff --git a/testsuite/tests/rts/derefnull.stdout-x86_64-unknown-mingw32 b/testsuite/tests/rts/derefnull.stdout-x86_64-unknown-mingw32
new file mode 100644
index 0000000000..cbabc63f88
--- /dev/null
+++ b/testsuite/tests/rts/derefnull.stdout-x86_64-unknown-mingw32
@@ -0,0 +1 @@
+Segmentation fault/access violation in generated code
diff --git a/testsuite/tests/rts/divbyzero.stdout-x86_64-unknown-mingw32 b/testsuite/tests/rts/divbyzero.stdout-x86_64-unknown-mingw32
new file mode 100644
index 0000000000..275d5d4601
--- /dev/null
+++ b/testsuite/tests/rts/divbyzero.stdout-x86_64-unknown-mingw32
@@ -0,0 +1 @@
+divide by zero