[m-dev.] for review: use Win32 exceptions in the runtime
Peter Ross
petdr at cs.mu.OZ.AU
Fri Jun 23 22:00:21 AEST 2000
Hi,
This is for Fergus to review.
===================================================================
Estimated hours taken: 40
Use Win32 exceptions to report problems, when we are in a Win32
environment.
runtime/mercury_conf_param.h:
If we are compiling in Win32 environment, we can check for overflow
via a mprotect like mechanism, so define
MR_CHECK_OVERFLOW_VIA_MPROTECT.
If HAVE_MPROTECT or MR_WIN32 is defined, define MR_PROTECTPAGE.
MR_PROTECTPAGE means that we have access to mprotect like
functionality.
runtime/mercury_memory_zones.c:
Define a function ProtectPage() which has the same interface as
mprotect. It just calls mprotect when it exists or equivalent code
to emulate it under Win32.
Use MR_PROTECTPAGE in place of HAVE_MPROTECT, and replace all calls
to mprotect() with ProtectPage().
Define a Win32 version of memalign.
runtime/mercury_memory_handlers.c:
Use ProtectPage instead of mprotect.
Don't use signal handlers when in a Win32 environment, as we now use
Win32 exceptions.
Code to explain Win32 exceptions on stderr.
runtime/mercury_memory_handlers.h:
Export MR_FilterWin32Exception for use in mercury_wrapper.c
runtime/mercury_memory_zones.h:
Use MR_PROTECTPAGE in place of HAVE_MPROTECT.
Define PROT_{NONE,READ,WRITE} if we are in a Win32 environment.
Export the definition of ProtectPage().
runtime/mercury_wrapper.c:
Wrap the call to main in a __try __except block if we are in a Win32
environment, so that any exceptions generated are caught and
debugging info about them printed to stderr.
runtime/mercury_memory.c:
Add a Win32 version of getpagesize().
Index: mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.36
diff -u -r1.36 mercury_conf_param.h
--- mercury_conf_param.h 2000/04/05 06:28:55 1.36
+++ mercury_conf_param.h 2000/06/23 11:57:59
@@ -345,8 +345,12 @@
#define MR_CAN_GET_PC_AT_SIGNAL
#endif
-#if defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(MR_WIN32)
#define MR_CHECK_OVERFLOW_VIA_MPROTECT
+#endif
+
+#if defined(HAVE_MPROTECT) || defined(MR_WIN32)
+ #define MR_PROTECTPAGE
#endif
/*---------------------------------------------------------------------------*/
Index: mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.18
diff -u -r1.18 mercury_memory.c
--- mercury_memory.c 2000/06/08 07:59:04 1.18
+++ mercury_memory.c 2000/06/23 11:58:00
@@ -96,7 +96,19 @@
#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
#define getpagesize() sysconf(_SC_PAGESIZE)
#elif !defined(HAVE_GETPAGESIZE)
- #define getpagesize() 8192
+ #if defined(MR_WIN32)
+ #include <windows.h>
+
+ static
+ size_t getpagesize(void)
+ {
+ SYSTEM_INFO SysInfo;
+ GetSystemInfo(&SysInfo);
+ return (size_t) SysInfo.dwPageSize;
+ }
+ #else
+ #define getpagesize() 8192
+ #endif
#endif
/*---------------------------------------------------------------------------*/
Index: mercury_memory_handlers.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_handlers.c,v
retrieving revision 1.11
diff -u -r1.11 mercury_memory_handlers.c
--- mercury_memory_handlers.c 2000/06/08 07:59:04 1.11
+++ mercury_memory_handlers.c 2000/06/23 11:58:01
@@ -132,7 +132,7 @@
static bool
try_munprotect(void *addr, void *context)
{
-#ifndef HAVE_SIGINFO
+#if !(defined(HAVE_SIGINFO) || defined(MR_WIN32))
return FALSE;
#else
Word * fault_addr;
@@ -221,7 +221,7 @@
zone->name, zone->id, (void *) zone->redzone, (void *) new_zone,
(int)zone_size);
}
- if (mprotect((char *)zone->redzone, zone_size,
+ if (ProtectPage((char *)zone->redzone, zone_size,
PROT_READ|PROT_WRITE) < 0)
{
char buf[2560];
@@ -262,12 +262,18 @@
void
setup_signals(void)
{
-#ifdef SIGBUS
+/*
+** When using Win32 don't set any signal handler.
+** See mercury_wrapper.c for the reason why.
+*/
+#ifndef MR_WIN32
+ #ifdef SIGBUS
MR_setup_signal(SIGBUS, (Code *) bus_handler, TRUE,
"Mercury runtime: cannot set SIGBUS handler");
-#endif
+ #endif
MR_setup_signal(SIGSEGV, (Code *) segv_handler, TRUE,
"Mercury runtime: cannot set SIGSEGV handler");
+#endif
}
static char *
@@ -547,6 +553,272 @@
}
#endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
+
+#ifdef MR_WIN32
+#include <tchar.h>
+
+/*
+** Exception code and their string representation
+*/
+#define DEFINE_EXCEPTION_NAME(a) {a,_T(#a)}
+
+typedef struct
+{
+ DWORD dwExceptionCode;
+ LPTSTR pszExceptionName;
+} MR_ExceptionName;
+
+static
+MR_ExceptionName MR_ExceptionNames[] =
+{
+ DEFINE_EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_DATATYPE_MISALIGNMENT),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_BREAKPOINT),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_SINGLE_STEP),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_DENORMAL_OPERAND),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_DIVIDE_BY_ZERO),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_INEXACT_RESULT),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_INVALID_OPERATION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_OVERFLOW),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_STACK_CHECK),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_UNDERFLOW),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_INT_DIVIDE_BY_ZERO),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_INT_OVERFLOW),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_PRIV_INSTRUCTION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_IN_PAGE_ERROR),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_ILLEGAL_INSTRUCTION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_NONCONTINUABLE_EXCEPTION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_STACK_OVERFLOW),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_INVALID_DISPOSITION),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_GUARD_PAGE),
+ DEFINE_EXCEPTION_NAME(EXCEPTION_INVALID_HANDLE)
+};
+
+
+/*
+** Retrieve the name of a Win32 exception code as a string
+*/
+static
+LPTSTR MR_FindExceptionName(DWORD ExceptionCode)
+{
+ int i;
+ for (i = 0; i < sizeof(MR_ExceptionNames)
+ / sizeof(MR_ExceptionName); i++)
+ {
+ if (MR_ExceptionNames[i].dwExceptionCode == ExceptionCode) {
+ return MR_ExceptionNames[i].pszExceptionName;
+ }
+ }
+ return _T("Unknown exception code");
+}
+
+
+/*
+** Explain an EXCEPTION_RECORD content into stderr.
+*/
+static
+void MR_ExplainExceptionRecord(EXCEPTION_RECORD *Rec)
+{
+ fprintf(stderr, "\n");
+ fprintf(stderr, "\n*** Explanation of the exception record");
+ if (Rec == NULL)
+ {
+ fprintf(stderr, "\n*** Cannot explain because it is NULL");
+ return;
+ }
+ {
+ void *lpAddress;
+ int AccessMode;
+
+ /* If the exception is an access violation */
+ if (MR_ExceptionRecordIsAccessViolation(Rec,
+ &lpAddress, &AccessMode))
+ {
+ MemoryZone *zone;
+
+ /* Display AV address and acces mode */
+ fprintf(stderr, "\n*** An access violation occured"
+ " at address 0x%08x, while attempting"
+ " to ", (void *)lpAddress);
+
+ if (AccessMode == 0) {
+ fprintf(stderr, "\n*** read "
+ "inaccessible data");
+ }
+ else if (AccessMode == 1) {
+ fprintf(stderr, "\n*** write to an "
+ "inaccessible (or protected)"
+ " address");
+ }
+ else
+ "mode %d (strange...)]",
+ AccessMode);
+
+ fprintf(stderr, "\n*** Trying to see if this "
+ "stands within a mercury zone...");
+ /*
+ ** Browse the mercury memory zones to see if the
+ ** AV address references one of them.
+ */
+ zone = get_used_memory_zones();
+ while(zone != NULL)
+ {
+ fprintf(stderr,
+ "\n*** Checking zone %s#%d: "
+ "0x%08x - 0x%08x - 0x%08x",
+ zone->name, zone->id,
+ (void *) zone->bottom,
+ (void *) zone->redzone,
+ (void *) zone->top);
+
+ if ((zone->redzone <= lpAddress) &&
+ (lpAddress <= zone->top))
+ {
+ fprintf(stderr,
+ "\n*** Address is within"
+ " redzone of "
+ "%s#%d (!!zone overflowed!!)\n",
+ zone->name, zone->id);
+ }
+ else if ((zone->bottom <= lpAddress) &&
+ (lpAddress <= zone->top))
+ {
+ fprintf(stderr, "\n*** Address is"
+ " within zone %s#%d\n",
+ zone->name, zone->id);
+ }
+ /*
+ ** Dont need to call handler, because it
+ ** has much less information than us
+ */
+ /* return zone->handler(fault_addr,
+ zone, Rec); */
+ zone = zone->next;
+ }
+ }
+ return;
+ }
+}
+
+/*
+** Dump an EXCEPTION_RECORD content into stderr.
+*/
+static
+void MR_DumpExceptionRecord(EXCEPTION_RECORD *Rec)
+{
+ int i;
+
+ if (Rec == NULL) {
+ return;
+ }
+
+ fprintf(stderr, "\n*** Exception record at 0x%08x:", Rec);
+ fprintf(stderr, "\n*** Code : 0x%08x (%s)",
+ Rec->ExceptionCode,
+ MR_FindExceptionName(Rec->ExceptionCode));
+ fprintf(stderr, "\n*** Flags : 0x%08x", Rec->ExceptionFlags);
+ fprintf(stderr, "\n*** Address : 0x%08x", Rec->ExceptionAddress);
+ for (i = 0; i < Rec->NumberParameters; i++)
+ {
+ fprintf(stderr, "\n*** Parameter %d : 0x%08x", i,
+ Rec->ExceptionInformation[i]);
+ }
+ fprintf(stderr, "\n*** Next Record : 0x%08x", Rec->ExceptionRecord);
+
+ /* Try to explain the exception more "gracefully" */
+ MR_ExplainExceptionRecord(Rec);
+ MR_DumpExceptionRecord(Rec->ExceptionRecord);
+}
+
+
+/*
+** Return TRUE iff ExecpPtrs indicates an Access Violation
+** If TRUE, lpAddress is set to the accessed address and
+** lpAccessMode is set to the desired access (0 = read, 1 = write)
+*/
+BOOL MR_ExceptionRecordIsAccessViolation(EXCEPTION_RECORD *Rec,
+ void **lpAddress, int *lpAccessMode)
+{
+ if (Rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ {
+ if (Rec->NumberParameters >= 2)
+ {
+ (*lpAccessMode) = (int)Rec->ExceptionInformation[0];
+ (*lpAddress) = (void *)Rec->ExceptionInformation[1];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/*
+** Filter a Win32 exception (to be called in the __except filter
+** part).
+** Possible return values are:
+**
+** EXCEPTION_CONTINUE_EXECUTION (-1)
+** Exception is dismissed. Continue execution at the point where
+** the exception occurred.
+**
+** EXCEPTION_CONTINUE_SEARCH (0)
+** Exception is not recognized. Continue to search up the stack for
+** a handler, first for containing try-except statements, then for
+** handlers with the next highest precedence.
+**
+** EXCEPTION_EXECUTE_HANDLER (1)
+** Exception is recognized. Transfer control to the exception handler
+** by executing the __except compound statement, then continue
+** execution at the assembly instruction that was executing
+** when the exception was raised.
+*/
+int MR_FilterWin32Exception(LPEXCEPTION_POINTERS ExcepPtrs)
+{
+ void *lpAddress;
+ int AccessMode;
+
+ /* If the exception is an access violation */
+ if (MR_ExceptionRecordIsAccessViolation(ExcepPtrs->ExceptionRecord,
+ &lpAddress, &AccessMode))
+ {
+ /* If we can unprotect to memory zone */
+ if (try_munprotect(lpAddress, ExcepPtrs))
+ {
+ if (MR_memdebug)
+ {
+ fprintf(stderr, "returning from "
+ "signal handler\n\n");
+ }
+ /* Continue execution where it stopped */
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+
+ /*
+ ** We can't handle the exception. Just dump all the information we got
+ */
+ fflush(stdout);
+ fprintf(stderr, "\n*** Mercury runtime: Unhandled exception ");
+ MR_DumpExceptionRecord(ExcepPtrs->ExceptionRecord);
+
+ print_dump_stack();
+ dump_prev_locations();
+
+ fprintf(stderr, "\n\n*** Now passing exception to default handler\n\n");
+ fflush(stderr);
+
+ /*
+ * Pass exception back to upper handler. In most cases, this
+ * means activating UnhandledExceptionFilter, which will display
+ * a dialog box asking to user ro activate the Debugger or simply
+ * to kill the application
+ */
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* MR_WIN32 */
+
/*
** get_pc_from_context:
Index: mercury_memory_handlers.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_handlers.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_memory_handlers.h
--- mercury_memory_handlers.h 1998/05/14 06:35:09 1.2
+++ mercury_memory_handlers.h 2000/06/23 11:58:01
@@ -37,4 +37,31 @@
void setup_signals(void);
+#ifdef MR_WIN32
+/*
+** Filter a Win32 exception (to be called in the __except filter
+** part).
+** Possible return values are:
+**
+** EXCEPTION_CONTINUE_EXECUTION (-1)
+** Exception is dismissed. Continue execution at the point where
+** the exception occurred.
+**
+** EXCEPTION_CONTINUE_SEARCH (0)
+** Exception is not recognized. Continue to search up the stack for
+** a handler, first for containing try-except statements, then for
+** handlers with the next highest precedence.
+**
+** EXCEPTION_EXECUTE_HANDLER (1)
+** Exception is recognized. Transfer control to the exception handler
+** by executing the __except compound statement, then continue
+** execution at the assembly instruction that was executing
+** when the exception was raised.
+*/
+#include <windows.h>
+#include <winnt.h>
+
+int MR_FilterWin32Exception(LPEXCEPTION_POINTERS ExcepPtrs);
+#endif
+
#endif /* not MERCURY_MEMORY_HANDLERS_H */
Index: mercury_memory_zones.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.10
diff -u -r1.10 mercury_memory_zones.c
--- mercury_memory_zones.c 2000/06/08 07:59:05 1.10
+++ mercury_memory_zones.c 2000/06/23 11:58:01
@@ -51,9 +51,86 @@
#include "mercury_thread.h"
#endif
+#ifdef MR_WIN32
+ #include <windows.h>
+#endif
+
/*---------------------------------------------------------------------------*/
-#ifdef CONSERVATIVE_GC
+/*
+** MR_PROTECTPAGE is now defined if we have some sort of mprotect like
+** functionality, all checks for HAVE_MPROTECT should now use MR_PROTECTPAGE.
+*/
+#if defined(HAVE_MPROTECT)
+int
+ProtectPage(void *Addr, size_t Size, int ProtFlags)
+{
+ return mprotect((char *)Addr, Size, ProtFlags);
+}
+#elif defined(MR_WIN32)
+/*
+** Emulate mprotect under Win32.
+** Return -1 on failure
+*/
+int
+ProtectPage(void *Addr, size_t Size, int ProtFlags)
+{
+ int rc;
+ DWORD Flags, OldFlags;
+
+ if (ProtFlags & PROT_WRITE) {
+ Flags = PAGE_READWRITE;
+ }
+ else if (ProtFlags & PROT_READ) {
+ Flags = PAGE_READONLY;
+ }
+ else {
+ Flags = PAGE_NOACCESS;
+ }
+
+ if (rc < 0) {
+ fprintf(stderr,
+ "Error in VirtualProtect(Addr=0x%08x, Size=0x%08x):"
+ " 0x%08x\n", Addr, Size, GetLastError());
+ }
+
+ return rc;
+}
+#endif /* HAVE_MPROTECT */
+
+
+/*---------------------------------------------------------------------------*/
+
+
+#if defined(MR_WIN32)
+/*
+** Under Win32, we use VirtualAlloc instead of the standard malloc,
+** since we will have to call VirtualProtect later on the pages
+** allocated here.
+*/
+void *
+memalign(size_t Unit, size_t Size)
+{
+ void *rc;
+
+ /*RPA: We don't need to specify 'unit' of anything else, because
+ the memory will be anyway aligned under Win32 */
+ rc = VirtualAlloc(NULL,
+ Size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (rc == NULL)
+ fprintf(stderr, "Error in VirtualAlloc(Size=0x%08x): 0x%08x\n",
+ Size, GetLastError());
+
+ #ifdef CONSERVATIVE_GC
+ if (rc != NULL)
+ GC_add_roots((char *)rc, (char *)rc + Size);
+ #endif
+ return rc;
+}
+#elif defined(CONSERVATIVE_GC)
#define memalign(a,s) GC_MALLOC_UNCOLLECTABLE(s)
#elif defined(HAVE_MEMALIGN)
extern void *memalign(size_t, size_t);
@@ -74,7 +151,7 @@
** PROT_EXEC page can be executed
** PROT_NONE page can not be accessed
*/
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
#ifdef CONSERVATIVE_GC
/*
@@ -94,7 +171,7 @@
#define PROT_NONE 0
#endif
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
/*---------------------------------------------------------------------------*/
@@ -256,13 +333,13 @@
** unit (an extra page for protection if
** mprotect is being used)
*/
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
total_size = size + 2 * unit;
#else
total_size = size + unit;
#endif
- base = memalign(unit, total_size);
+ base = (Word *) memalign(unit, total_size);
if (base == NULL) {
char buf[2560];
sprintf(buf, "unable allocate memory zone: %s#%d", name, id);
@@ -295,11 +372,11 @@
zone->bottom = base;
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
total_size = size + unit;
#else
total_size = size;
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
zone->top = (Word *) ((char *)base + total_size);
zone->min = (Word *) ((char *)base + offset);
@@ -313,7 +390,7 @@
#ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
zone->redzone_base = zone->redzone = (Word *)
round_up((Unsigned)base + size - redsize, unit);
- if (mprotect((char *)zone->redzone, redsize + unit, MY_PROT) < 0) {
+ if (ProtectPage((char *)zone->redzone, redsize + unit, MY_PROT) < 0) {
char buf[2560];
sprintf(buf, "unable to set %s#%d redzone\n"
"base=%p, redzone=%p",
@@ -325,9 +402,9 @@
/*
** setup the hardzone
*/
-#if defined(HAVE_MPROTECT)
+#if defined(MR_PROTECTPAGE)
zone->hardmax = (Word *) round_up((Unsigned)zone->top - unit, unit);
- if (mprotect((char *)zone->hardmax, unit, MY_PROT) < 0) {
+ if (ProtectPage((char *)zone->hardmax, unit, MY_PROT) < 0) {
char buf[2560];
sprintf(buf, "unable to set %s#%d hardmax\n"
"base=%p, hardmax=%p top=%p",
@@ -335,7 +412,7 @@
zone->top);
fatal_error(buf);
}
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
return zone;
@@ -347,7 +424,7 @@
#ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
zone->redzone = zone->redzone_base;
- if (mprotect((char *)zone->redzone,
+ if (ProtectPage((char *)zone->redzone,
((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0)
{
char buf[2560];
@@ -397,7 +474,7 @@
fprintf(stderr, "%-16s#%d-redzone_base = %p\n",
zone->name, zone->id, (void *) zone->redzone_base);
#endif /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
fprintf(stderr, "%-16s#%d-hardmax = %p\n",
zone->name, zone->id, (void *) zone->hardmax);
fprintf(stderr, "%-16s#%d-size = %lu\n",
@@ -407,7 +484,7 @@
fprintf(stderr, "%-16s#%d-size = %lu\n",
zone->name, zone->id, (unsigned long)
((char *)zone->top - (char *)zone->min));
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
fprintf(stderr, "\n");
}
}
Index: mercury_memory_zones.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_memory_zones.h
--- mercury_memory_zones.h 1999/10/05 20:21:41 1.5
+++ mercury_memory_zones.h 2000/06/23 11:58:02
@@ -101,10 +101,10 @@
Word *max; /* highest word of the area to be used;
computed only if MR_LOWLEVEL_DEBUG is
enabled */
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
Word *hardmax; /* last page of the zone which can't be
unprotected */
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
#ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
Word *redzone_base; /* beginning of the original redzone */
Word *redzone; /* beginning of the current redzone */
@@ -118,7 +118,7 @@
*/
#ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
#define MR_zone_end redzone
-#elif defined(HAVE_MPROTECT)
+#elif defined(MR_PROTECTPAGE)
#define MR_zone_end hardmax
#else
#define MR_zone_end top
@@ -137,6 +137,21 @@
(char*)((zone)->MR_zone_end) - (char *)(start_address)))
/*
+** Rather then using mprotect directly, we call ProtectPage which
+** is OS independent.
+*/
+#ifdef MR_PROTECTPAGE
+
+ #ifdef MR_WIN32
+ #define PROT_NONE 0x0000
+ #define PROT_READ 0x0001
+ #define PROT_WRITE 0x0002
+ #endif
+
+int ProtectPage(void *Addr, size_t Size, int ProtFlags);
+#endif
+
+/*
** init_memory_arena() allocates (if necessary) the top-level memory pool
** from which all allocations should come. If PARALLEL is defined, then
** this pool should be shared memory. In the absence of PARALLEL, it
@@ -175,7 +190,7 @@
** construct_zone(Name, Id, Base, Size, Offset, RedZoneSize, FaultHandler)
** has the same behaviour as create_zone, except instread of allocating
** the memory, it takes a pointer to a region of memory that must be at
-** least Size + unit[*] bytes, or if HAVE_MPROTECT is defined, then it
+** least Size + unit[*] bytes, or if MR_PROTECTPAGE is defined, then it
** must be at least Size + 2 * unit[*] bytes.
** If it fails to protect the redzone then it exits.
** If MR_CHECK_OVERFLOW_VIA_MPROTECT is unavailable, then the last two
Index: mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.62
diff -u -r1.62 mercury_wrapper.c
--- mercury_wrapper.c 2000/06/08 07:59:06 1.62
+++ mercury_wrapper.c 2000/06/23 11:58:06
@@ -32,6 +32,10 @@
#include <stdio.h>
#include <string.h>
+#ifdef MR_WIN32
+#include <excpt.h>
+#endif
+
#include "mercury_getopt.h"
#include "mercury_timing.h"
#include "mercury_init.h"
@@ -894,6 +898,30 @@
static int repcounter;
+#ifdef MR_WIN32
+ /*
+ ** Under Win32 we use the following construction to handle exceptions.
+ ** __try
+ ** {
+ ** <various stuff>
+ ** }
+ ** __except(MR_FilterWin32Exception(GetExceptionInformation())
+ ** {
+ ** }
+ **
+ ** This type of contruction allows us to retrieve all the information
+ ** we need (exception type, address, etc) to display a "meaningful"
+ ** message to the user. Using signal() in Win32 is less powerful,
+ ** since we can only trap a subset of all possible exceptions, and
+ ** we can't retrieve the exception address. The VC runtime implements
+ ** signal() by surrounding main() with a __try __except block and
+ ** calling the signal handler in the __except filter, exactly the way
+ ** we do it here.
+ */
+ __try
+ {
+#endif
+
/*
** Save the C callee-save registers
** and restore the Mercury registers
@@ -989,6 +1017,14 @@
*/
save_registers();
restore_regs_from_mem(c_regs);
+
+#ifdef MR_WIN32
+ }
+ __except(MR_FilterWin32Exception(GetExceptionInformation()))
+ {
+ /* Everything is done in MR_FilterWin32Exception */
+ }
+#endif
} /* end mercury_runtime_main() */
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list