diff options
author | Tamar Christina <tamar@zhox.com> | 2015-03-03 07:20:55 -0600 |
---|---|---|
committer | Austin Seipp <austin@well-typed.com> | 2015-03-03 07:20:56 -0600 |
commit | 5200bdeb26c5ec98739b14b10fc8907296bceeb9 (patch) | |
tree | 7964b84458f70f7e1544b9ade6d953040f53290a /rts/Excn.h | |
parent | f6609b0ed031135b8402fd179b3370958698ecb2 (diff) | |
download | haskell-5200bdeb26c5ec98739b14b10fc8907296bceeb9.tar.gz |
Replaced SEH handles with VEH handlers which should work uniformly across x86 and x64
Summary:
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).
veh_excn provides two macros, `BEGIN_CATCH` and `END_CATCH`, which
will catch such exceptions in the entire process and die by
printing a message and calling `stg_exit(1)`.
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.
Test Plan:
Prior to this diff the tests for `derefnull` and `divbyzero` seem to have been disabled for windows.
To reproduce the issue on x64:
1) open ghci
2) import GHC.Base
3) run: 1 `divInt` 0
which should lead to ghci crashing an a watson error box displaying.
After applying the patch, run:
make TEST="derefnull divbyzero"
on both x64 and x86 builds of ghc to verify fix.
Reviewers: simonmar, austin
Reviewed By: austin
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D691
GHC Trac Issues: #6079
Diffstat (limited to 'rts/Excn.h')
-rw-r--r-- | rts/Excn.h | 34 |
1 files changed, 34 insertions, 0 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 */ + |