X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fwin32%2Fseh_excn.h;fp=rts%2Fwin32%2Fseh_excn.h;h=410d4308717b21f2f55172cd2fe02ddf6513117a;hb=49b8105e8d56c90099234e31c32ba3f1643276fe;hp=0000000000000000000000000000000000000000;hpb=32f2ee11b7288a53b89ea81ebdf4f8a74b707fed;p=ghc-hetmet.git diff --git a/rts/win32/seh_excn.h b/rts/win32/seh_excn.h new file mode 100644 index 0000000..410d430 --- /dev/null +++ b/rts/win32/seh_excn.h @@ -0,0 +1,91 @@ +#ifndef __SEH_EXCN_H__ +#define __SEH_EXCN_H__ +#include +#include + +#if defined(__MINGW32__) +/* Stuff needed to install and use SEH exception handlers */ +#include +#include +#include +#elif defined(_MSC_VER) +#include +#else +#include +#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 exit(1). + */ +#define ON_DIV_ZERO fprintf(stdout,"divide by zero\n"); fflush(stdout);exit(1) +#define ON_STACK_OVERFLOW fprintf(stdout,"C stack overflow in generated code\n"); fflush(stdout); exit(1) +#define ON_SIGSEGV fprintf(stdout,"Segmentation fault/access violation in generated code\n"); fflush(stdout); 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 Don't know what sort of Windows system this is +#endif + +#endif /* __SEH_EXCN_H__ */ +