[m-dev.] for review: use Win32 exceptions in the runtime

Peter Ross petdr at cs.mu.OZ.AU
Tue Jun 27 22:37:37 AEST 2000


On Tue, Jun 27, 2000 at 10:56:20AM +1000, Fergus Henderson wrote:
> Where does MR_WIN32 get defined?
> 
It is defined in mercury_conf.h, which is generate by configure.

> On 23-Jun-2000, Peter Ross <petdr at cs.mu.OZ.AU> wrote:
> > +++ mercury_memory_handlers.h	2000/06/23 11:58:01
> > @@ -37,4 +37,31 @@
> >  
> >  void	setup_signals(void);
> >  
> > +#ifdef MR_WIN32
> ...
> > +#include <windows.h>
> > +#include <winnt.h>
> > +
> > +int MR_FilterWin32Exception(LPEXCEPTION_POINTERS ExcepPtrs);
> > +#endif
> 
> Why do you include <winnt.h>?
> Will that cause problems on Windows 95?
> 

At some stage I needed it to compile, I don't appear to anymore, so I
have removed the reference.

> >  /*
> > +** 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
> 
> That could cause problems on systems that offer both Win32 and Unix APIs,
> and thus define MR_WIN32 but also include a definition of PROT_NONE in
> the system header files.  I suggest using MR_PROT_NONE etc.
> and defining MR_PROT_NONE as PROT_NONE on systems for which MR_WIN32
> is not defined.
> 

If PROT_* are not defined, I define them as above, this is all that
needs to be done.


Here is the new log message and a relative diff, plus the full diff at
the end.

===================================================================


Estimated hours taken: 44

Use Win32 exceptions to report problems when Win32 structured exceptions
are available.

runtime/mercury_conf_param.h:
    Define the following symbolic constants:
        MR_WIN32_GETSYSTEMINFO which is true if GetSystemInfo() is
        availabe.
        MR_WIN32_VIRTUALALLOC which is true if VirtualAlloc() is
        availabe.
        MR_WIN32_STRUCTURED_EXCEPTIONS if we can use Win32 structured
        exceptions.
        MR_PROTECTPAGE if can provide mprotect like functionality.
    All of the above are assumed true if the Win32 API is available.
    MR_CHECK_OVERFLOW_VIA_MPROTECT is also true if MR_WIN32, because the
    Win32 API provides mprotect like functionality.
    
runtime/mercury_memory_zones.c:
    Define a function MR_protect_pages() 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 MR_protect_pages().
    Define a Win32 version of memalign.

runtime/mercury_memory_handlers.c:
    Use MR_protect_pages() instead of mprotect().
    Don't use signal handlers when in a Win32 structured exceptions are
    available.
    Code to explain Win32 exceptions on stderr.

runtime/mercury_memory_handlers.h:
    Export MR_filter_win32_exception 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 the Win32 API is available and
    they are not already defined.
    Export the definition of MR_protect_pages().

runtime/mercury_wrapper.c:
    Wrap the call to main in a __try __except block if we are using
    Win32 structured exceptions, 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().

*** Relative diff ***
Common subdirectories: runtime.old/CVS and runtime/CVS
Common subdirectories: runtime.old/GETOPT and runtime/GETOPT
Common subdirectories: runtime.old/machdeps and runtime/machdeps
diff -u runtime.old/mercury_conf_param.h runtime/mercury_conf_param.h
--- runtime.old/mercury_conf_param.h	Fri Jun 23 10:18:15 2000
+++ runtime/mercury_conf_param.h	Tue Jun 27 14:15:52 2000
@@ -345,12 +345,28 @@
   #define MR_CAN_GET_PC_AT_SIGNAL
 #endif
 
+        /* We can check for overflow using mprotect like functionality */
 #if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(MR_WIN32)
   #define MR_CHECK_OVERFLOW_VIA_MPROTECT
 #endif
 
+        /* The functionality of mprotect can be provided */
 #if defined(HAVE_MPROTECT) || defined(MR_WIN32)
   #define MR_PROTECTPAGE
+#endif
+
+#if defined(MR_WIN32)
+  #define MR_WIN32_STRUCTURED_EXCEPTIONS
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Win32 API specific.
+*/
+#if defined(MR_WIN32)
+  #define MR_WIN32_GETSYSTEMINFO	/* to determine page size */
+  #define MR_WIN32_VIRTUAL_ALLOC	/* to provide mprotect functionality */
 #endif
 
 /*---------------------------------------------------------------------------*/
diff -u runtime.old/mercury_memory.c runtime/mercury_memory.c
--- runtime.old/mercury_memory.c	Fri Jun 23 10:18:15 2000
+++ runtime/mercury_memory.c	Tue Jun 27 14:08:08 2000
@@ -96,7 +96,7 @@
 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
   #define	getpagesize()	sysconf(_SC_PAGESIZE)
 #elif !defined(HAVE_GETPAGESIZE)
-  #if defined(MR_WIN32)
+  #if defined(MR_WIN32_GETSYSTEMINFO)
     #include <windows.h>
 
     static
Only in runtime.old: mercury_memory.o
Only in runtime.old: mercury_memory.pic_o
diff -u runtime.old/mercury_memory_handlers.c runtime/mercury_memory_handlers.c
--- runtime.old/mercury_memory_handlers.c	Fri Jun 23 13:53:44 2000
+++ runtime/mercury_memory_handlers.c	Tue Jun 27 14:08:08 2000
@@ -221,9 +221,8 @@
 	    zone->name, zone->id, (void *) zone->redzone, (void *) new_zone,
 	    (int)zone_size);
 	}
-	if (ProtectPage((char *)zone->redzone, zone_size,
-	    PROT_READ|PROT_WRITE) < 0)
-	{
+	if (MR_protect_pages((char *)zone->redzone, zone_size,
+		PROT_READ|PROT_WRITE) < 0) {
 	    char buf[2560];
 	    sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
 		zone->name, zone->id);
@@ -263,10 +262,10 @@
 setup_signals(void)
 {
 /*
-** When using Win32 don't set any signal handler.
+** When using Win32 structured exceptions don't set any signal handler.
 ** See mercury_wrapper.c for the reason why.
 */
-#ifndef MR_WIN32
+#ifndef MR_WIN32_STRUCTURED_EXCEPTIONS
   #ifdef SIGBUS
 	MR_setup_signal(SIGBUS, (Code *) bus_handler, TRUE,
 		"Mercury runtime: cannot set SIGBUS handler");
@@ -554,7 +553,7 @@
 
 #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
 
-#ifdef MR_WIN32
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
 #include <tchar.h>
 
 /*
@@ -564,12 +563,12 @@
 
 typedef struct
 {
-	DWORD dwExceptionCode;
-	LPTSTR pszExceptionName;
+	DWORD exception_code;
+	LPTSTR exception_name;
 } MR_ExceptionName;
 
 static
-MR_ExceptionName MR_ExceptionNames[] =
+MR_ExceptionName MR_exception_names[] =
 {
 	DEFINE_EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION),
 	DEFINE_EXCEPTION_NAME(EXCEPTION_DATATYPE_MISALIGNMENT),
@@ -600,61 +599,62 @@
 ** Retrieve the name of a Win32 exception code as a string
 */
 static
-LPTSTR MR_FindExceptionName(DWORD ExceptionCode)
+LPTSTR MR_find_exception_name(DWORD exception_code)
 {
 	int i;
-	for (i = 0; i < sizeof(MR_ExceptionNames)
-			/ sizeof(MR_ExceptionName); i++)
-	{
-		if (MR_ExceptionNames[i].dwExceptionCode == ExceptionCode) {
-			return MR_ExceptionNames[i].pszExceptionName;
+	for (i = 0; i < sizeof(MR_exception_names)
+			/ sizeof(MR_ExceptionName); i++) {
+		if (MR_exception_names[i].exception_code == exception_code) {
+			return MR_exception_names[i].exception_name;
 		}
 	}
 	return _T("Unknown exception code");
 }
 
+/*
+** Was a page accessed read/write?  The MSDN documentation doens't define
+** symbolic constants for these alternatives.
+*/
+#define READ	0
+#define WRITE	1
 
 /*
 ** Explain an EXCEPTION_RECORD content into stderr.
 */
 static
-void MR_ExplainExceptionRecord(EXCEPTION_RECORD *Rec)
+void MR_explain_exception_record(EXCEPTION_RECORD *rec)
 {
 	fprintf(stderr, "\n");
 	fprintf(stderr, "\n*** Explanation of the exception record");
-	if (Rec == NULL)
-	{
+	if (rec == NULL) {
 		fprintf(stderr, "\n***   Cannot explain because it is NULL");
 		return;
-	}
-	{
-		void *lpAddress;
-		int AccessMode;
+	} else {
+		void *address;
+		int access_mode;
 		
 		/* If the exception is an access violation */
-		if (MR_ExceptionRecordIsAccessViolation(Rec,
-					&lpAddress, &AccessMode))
-		{
+		if (MR_ExceptionrecordIsAccessViolation(rec,
+					&address, &access_mode)) {
 			MemoryZone *zone;
 
 			/* Display AV address and acces mode */
 			fprintf(stderr, "\n***   An access violation occured"
-					" at address 0x%08x, while attempting"
-					" to ", (void *)lpAddress);
+					" at address 0x%08lx, while attempting"
+					" to ", (unsigned long) address);
 			
-			if (AccessMode == 0) {
+			if (access_mode == READ) {
 				fprintf(stderr, "\n***   read "
 						"inaccessible data");
-			}
-			else if (AccessMode == 1) {
+			} else if (access_mode == WRITE) {
 				fprintf(stderr, "\n***   write to an "
 						"inaccessible (or protected)"
 						" address");
-			}
-			else
+			} else {
 				fprintf(stderr, "\n***   ? [unknown access "
 						"mode %d (strange...)]",
-						AccessMode);
+						access_mode);
+			}
 				
 			fprintf(stderr, "\n***   Trying to see if this "
 					"stands within a mercury zone...");
@@ -663,8 +663,7 @@
 			** AV address references one of them.
 			*/
 			zone = get_used_memory_zones();
-			while(zone != NULL)
-			{
+			while(zone != NULL) {
 				fprintf(stderr,
 						"\n***    Checking zone %s#%d: "
 						"0x%08x - 0x%08x - 0x%08x",
@@ -673,28 +672,25 @@
 						(void *) zone->redzone,
 						(void *) zone->top);
 
-				if ((zone->redzone <= lpAddress) &&
-						(lpAddress <= zone->top))
-				{
+				if ((zone->redzone <= address) &&
+						(address <= 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))
-				{
+				} else if ((zone->bottom <= address) &&
+						(address <= 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
+				** Don't need to call handler, because it
+				** has much less information than we do.
 				*/
 				/* return zone->handler(fault_addr,
-				 		zone, Rec); */
+				 		zone, rec); */
 				zone = zone->next;
 			}
 		}
@@ -706,30 +702,30 @@
 ** Dump an EXCEPTION_RECORD content into stderr.
 */
 static
-void MR_DumpExceptionRecord(EXCEPTION_RECORD *Rec)
+void MR_dump_exception_record(EXCEPTION_RECORD *rec)
 {
 	int i;
 	
-	if (Rec == NULL) {
+	if (rec == NULL) {
 		return;
 	}
 	
-	fprintf(stderr, "\n***   Exception record at 0x%08x:", Rec);
+	fprintf(stderr, "\n***   Exception record at 0x%08lx:",
+			(unsigned long) 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++)
-	{
+			rec->ExceptionCode,
+			MR_find_exception_name(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]);
+				rec->ExceptionInformation[i]);
 	}
-	fprintf(stderr, "\n***    Next Record : 0x%08x", Rec->ExceptionRecord);
+	fprintf(stderr, "\n***    Next record : 0x%08x", rec->ExceptionRecord);
 	
 	/* Try to explain the exception more "gracefully" */
-	MR_ExplainExceptionRecord(Rec);
-	MR_DumpExceptionRecord(Rec->ExceptionRecord);
+	MR_explain_exception_record(rec);
+	MR_dump_exception_record(rec->ExceptionRecord);
 }
 
 
@@ -738,15 +734,13 @@
 ** 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)
+bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address, int *access_mode)
 {
-	if (Rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
-	{
-		if (Rec->NumberParameters >= 2)
-		{
-			(*lpAccessMode) = (int)Rec->ExceptionInformation[0];
-			(*lpAddress) = (void *)Rec->ExceptionInformation[1];
+	if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+		if (rec->NumberParameters >= 2) {
+			(*access_mode) = (int)rec->ExceptionInformation[0];
+			(*address) = (void *)rec->ExceptionInformation[1];
 			return TRUE;
 		}
 	}
@@ -774,24 +768,23 @@
 **  execution at the assembly instruction that was executing
 **  when the exception was raised. 
 */
-int MR_FilterWin32Exception(LPEXCEPTION_POINTERS ExcepPtrs)
+int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
 {
-	void *lpAddress;
-	int AccessMode;
+	void *address;
+	int access_mode;
 
-	/* 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)
-			{
+		/* If the exception is an access violation */
+	if (MR_exception_record_is_access_violation(
+			exception_ptrs->ExceptionRecord,
+			&address, &access_mode)) {
+
+			/* If we can unprotect the memory zone */
+		if (try_munprotect(address, exception_ptrs)) {
+			if (MR_memdebug) {
 				fprintf(stderr, "returning from "
 						"signal handler\n\n");
 			}
-			/* Continue execution where it stopped */
+				/* Continue execution where it stopped */
 			return  EXCEPTION_CONTINUE_EXECUTION;
 		}
 	}
@@ -801,7 +794,7 @@
 	*/
 	fflush(stdout);
 	fprintf(stderr, "\n*** Mercury runtime: Unhandled exception ");
-	MR_DumpExceptionRecord(ExcepPtrs->ExceptionRecord);
+	MR_dump_exception_record(exception_ptrs->ExceptionRecord);
 
 	print_dump_stack();
 	dump_prev_locations();
@@ -817,7 +810,7 @@
 	 */
 	return  EXCEPTION_CONTINUE_SEARCH;
 }
-#endif /* MR_WIN32 */
+#endif /* MR_WIN32_STRUCTURED_EXCEPTIONS */
 
 
 /*
diff -u runtime.old/mercury_memory_handlers.h runtime/mercury_memory_handlers.h
--- runtime.old/mercury_memory_handlers.h	Fri Jun 23 13:54:42 2000
+++ runtime/mercury_memory_handlers.h	Tue Jun 27 14:08:08 2000
@@ -37,7 +37,7 @@
 
 void	setup_signals(void);
 
-#ifdef MR_WIN32
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
 /*
 ** Filter a Win32 exception (to be called in the __except filter
 ** part).
@@ -59,9 +59,8 @@
 **  when the exception was raised. 
 */
 #include <windows.h>
-#include <winnt.h>
 
-int MR_FilterWin32Exception(LPEXCEPTION_POINTERS ExcepPtrs);
+int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs);
 #endif
 
 #endif /* not MERCURY_MEMORY_HANDLERS_H */
Only in runtime.old: mercury_memory_handlers.o
Only in runtime.old: mercury_memory_handlers.pic_o
diff -u runtime.old/mercury_memory_zones.c runtime/mercury_memory_zones.c
--- runtime.old/mercury_memory_zones.c	Fri Jun 23 13:56:30 2000
+++ runtime/mercury_memory_zones.c	Tue Jun 27 14:08:08 2000
@@ -63,36 +63,34 @@
 */
 #if defined(HAVE_MPROTECT)
 int
-ProtectPage(void *Addr, size_t Size, int ProtFlags)
+MR_protect_pages(void *Addr, size_t Size, int ProtFlags)
 {
 	return mprotect((char *)Addr, Size, ProtFlags);
 }
-#elif defined(MR_WIN32)
+#elif defined(MR_WIN32_VIRTUAL_ALLOC)
 /*
 ** Emulate mprotect under Win32.
 ** Return -1 on failure
 */
 int
-ProtectPage(void *Addr, size_t Size, int ProtFlags)
+MR_protect_pages(void *addr, size_t size, int prot_flags)
 {
 	int rc;
 	DWORD Flags, OldFlags;
 
-	if (ProtFlags & PROT_WRITE) {
+	if (prot_flags & PROT_WRITE) {
 		Flags = PAGE_READWRITE;
-	}
-	else if (ProtFlags & PROT_READ) {
+	} else if (prot_flags & PROT_READ) {
 		Flags = PAGE_READONLY;
-	}
-	else {
+	} else {
 		Flags = PAGE_NOACCESS;
 	}
 	
-	rc = (VirtualAlloc(Addr, Size, MEM_COMMIT, Flags) ? 0 : -1);
+	rc = (VirtualAlloc(addr, size, MEM_COMMIT, Flags) ? 0 : -1);
 	if (rc < 0) {
 		fprintf(stderr,
-			"Error in VirtualProtect(Addr=0x%08x, Size=0x%08x):"
-			" 0x%08x\n", Addr, Size, GetLastError());
+			"Error in VirtualProtect(addr=0x%08x, size=0x%08x):"
+			" 0x%08x\n", addr, size, GetLastError());
 	}
 
 	return rc;
@@ -103,30 +101,30 @@
 /*---------------------------------------------------------------------------*/
 
 
-#if defined(MR_WIN32)
+#if defined(MR_WIN32_VIRTUAL_ALLOC)
 /*
 ** 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)
+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());
+	/*
+	** We don't need to use the 'unit' value as the memory is always
+	** 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);
+		GC_add_roots((char *)rc, (char *)rc + size);
   #endif
 	return rc;
 }
@@ -390,7 +388,8 @@
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
 	zone->redzone_base = zone->redzone = (Word *)
 			round_up((Unsigned)base + size - redsize, unit);
-	if (ProtectPage((char *)zone->redzone, redsize + unit, MY_PROT) < 0) {
+	if (MR_protect_pages((char *)zone->redzone,
+			redsize + unit, MY_PROT) < 0) {
 		char buf[2560];
 		sprintf(buf, "unable to set %s#%d redzone\n"
 			"base=%p, redzone=%p",
@@ -404,7 +403,7 @@
 	*/
 #if	defined(MR_PROTECTPAGE)
 	zone->hardmax = (Word *) round_up((Unsigned)zone->top - unit, unit);
-	if (ProtectPage((char *)zone->hardmax, unit, MY_PROT) < 0) {
+	if (MR_protect_pages((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",
@@ -424,9 +423,8 @@
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
 	zone->redzone = zone->redzone_base;
 
-	if (ProtectPage((char *)zone->redzone,
-		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0)
-	{
+	if (MR_protect_pages((char *)zone->redzone,
+		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0) {
 		char buf[2560];
 		sprintf(buf, "unable to reset %s#%d redzone\n"
 			"base=%p, redzone=%p",
diff -u runtime.old/mercury_memory_zones.h runtime/mercury_memory_zones.h
--- runtime.old/mercury_memory_zones.h	Fri Jun 23 10:18:15 2000
+++ runtime/mercury_memory_zones.h	Tue Jun 27 14:08:08 2000
@@ -137,18 +137,24 @@
 		(char*)((zone)->MR_zone_end) - (char *)(start_address)))
 
 /*
-** Rather then using mprotect directly, we call ProtectPage which
+** Rather then using mprotect directly, we call MR_protect_pages which
 ** is OS independent.
 */
 #ifdef MR_PROTECTPAGE
 
   #ifdef MR_WIN32
-    #define PROT_NONE  0x0000
-    #define PROT_READ  0x0001
-    #define PROT_WRITE 0x0002
+    #ifndef PROT_NONE
+      #define PROT_NONE  0x0000
+    #endif
+    #ifndef PROT_READ
+      #define PROT_READ  0x0001
+    #endif
+    #ifndef PROT_WRITE
+      #define PROT_WRITE 0x0002
+    #endif
   #endif
 
-int ProtectPage(void *Addr, size_t Size, int ProtFlags);
+int MR_protect_pages(void *Addr, size_t Size, int ProtFlags);
 #endif
 
 /*
Only in runtime.old: mercury_memory_zones.o
Only in runtime.old: mercury_memory_zones.pic_o
diff -u runtime.old/mercury_wrapper.c runtime/mercury_wrapper.c
--- runtime.old/mercury_wrapper.c	Fri Jun 23 10:18:15 2000
+++ runtime/mercury_wrapper.c	Tue Jun 27 14:08:08 2000
@@ -32,8 +32,8 @@
 #include	<stdio.h>
 #include	<string.h>
 
-#ifdef MR_WIN32
-#include <excpt.h>
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+  #include <excpt.h>
 #endif
 
 #include	"mercury_getopt.h"
@@ -898,14 +898,14 @@
 
 	static	int	repcounter;
 
-#ifdef MR_WIN32
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
 	/*
 	** Under Win32 we use the following construction to handle exceptions.
 	**   __try
 	**   {
 	**     <various stuff>
 	**   }
-	**   __except(MR_FilterWin32Exception(GetExceptionInformation())
+	**   __except(MR_filter_win32_exception(GetExceptionInformation())
 	**   {
 	**   }
 	**
@@ -1018,11 +1018,11 @@
 	save_registers();
 	restore_regs_from_mem(c_regs);
 
-#ifdef MR_WIN32
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
 	}
-	__except(MR_FilterWin32Exception(GetExceptionInformation()))
+	__except(MR_filter_win32_exception(GetExceptionInformation()))
 	{
-		/* Everything is done in MR_FilterWin32Exception */
+		/* Everything is done in MR_filter_win32_exception */
 	}
 #endif
 

*** Full diff ***
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/27 12:16:22
@@ -345,8 +345,28 @@
   #define MR_CAN_GET_PC_AT_SIGNAL
 #endif
 
-#if defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)
+        /* We can check for overflow using mprotect like functionality */
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(MR_WIN32)
   #define MR_CHECK_OVERFLOW_VIA_MPROTECT
+#endif
+
+        /* The functionality of mprotect can be provided */
+#if defined(HAVE_MPROTECT) || defined(MR_WIN32)
+  #define MR_PROTECTPAGE
+#endif
+
+#if defined(MR_WIN32)
+  #define MR_WIN32_STRUCTURED_EXCEPTIONS
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Win32 API specific.
+*/
+#if defined(MR_WIN32)
+  #define MR_WIN32_GETSYSTEMINFO	/* to determine page size */
+  #define MR_WIN32_VIRTUAL_ALLOC	/* to provide mprotect functionality */
 #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/27 12:16:23
@@ -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_GETSYSTEMINFO)
+    #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/27 12:16:25
@@ -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,9 +221,8 @@
 	    zone->name, zone->id, (void *) zone->redzone, (void *) new_zone,
 	    (int)zone_size);
 	}
-	if (mprotect((char *)zone->redzone, zone_size,
-	    PROT_READ|PROT_WRITE) < 0)
-	{
+	if (MR_protect_pages((char *)zone->redzone, zone_size,
+		PROT_READ|PROT_WRITE) < 0) {
 	    char buf[2560];
 	    sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
 		zone->name, zone->id);
@@ -262,12 +261,18 @@
 void
 setup_signals(void)
 {
-#ifdef SIGBUS
+/*
+** When using Win32 structured exceptions don't set any signal handler.
+** See mercury_wrapper.c for the reason why.
+*/
+#ifndef MR_WIN32_STRUCTURED_EXCEPTIONS
+  #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 +552,266 @@
 }
 
 #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
+
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#include <tchar.h>
+
+/*
+** Exception code and their string representation
+*/
+#define DEFINE_EXCEPTION_NAME(a)   {a,_T(#a)}
+
+typedef struct
+{
+	DWORD exception_code;
+	LPTSTR exception_name;
+} MR_ExceptionName;
+
+static
+MR_ExceptionName MR_exception_names[] =
+{
+	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_find_exception_name(DWORD exception_code)
+{
+	int i;
+	for (i = 0; i < sizeof(MR_exception_names)
+			/ sizeof(MR_ExceptionName); i++) {
+		if (MR_exception_names[i].exception_code == exception_code) {
+			return MR_exception_names[i].exception_name;
+		}
+	}
+	return _T("Unknown exception code");
+}
+
+/*
+** symbolic constants for these alternatives.
+*/
+#define READ	0
+#define WRITE	1
+
+/*
+** Explain an EXCEPTION_RECORD content into stderr.
+*/
+static
+void MR_explain_exception_record(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;
+	} else {
+		void *address;
+		int access_mode;
+		
+		/* If the exception is an access violation */
+		if (MR_ExceptionrecordIsAccessViolation(rec,
+					&address, &access_mode)) {
+			MemoryZone *zone;
+
+			/* Display AV address and acces mode */
+			fprintf(stderr, "\n***   An access violation occured"
+					" at address 0x%08lx, while attempting"
+					" to ", (unsigned long) address);
+			
+			if (access_mode == READ) {
+				fprintf(stderr, "\n***   read "
+						"inaccessible data");
+			} else if (access_mode == WRITE) {
+				fprintf(stderr, "\n***   write to an "
+						"inaccessible (or protected)"
+						" address");
+			} else {
+						"mode %d (strange...)]",
+						access_mode);
+			}
+				
+			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 <= address) &&
+						(address <= zone->top)) {
+					fprintf(stderr,
+						"\n***     Address is within"
+						" redzone of "
+						"%s#%d (!!zone overflowed!!)\n",
+						zone->name, zone->id);
+				} else if ((zone->bottom <= address) &&
+						(address <= zone->top)) {
+					fprintf(stderr, "\n***     Address is"
+							" within zone %s#%d\n",
+							zone->name, zone->id);
+				}
+				/*
+				** Don't need to call handler, because it
+				** has much less information than we do.
+				*/
+				/* return zone->handler(fault_addr,
+				 		zone, rec); */
+				zone = zone->next;
+			}
+		}
+		return;
+	}
+}
+
+/*
+** Dump an EXCEPTION_RECORD content into stderr.
+*/
+static
+void MR_dump_exception_record(EXCEPTION_RECORD *rec)
+{
+	int i;
+	
+	if (rec == NULL) {
+		return;
+	}
+	
+	fprintf(stderr, "\n***   Exception record at 0x%08lx:",
+			(unsigned long) rec);
+	fprintf(stderr, "\n***    Code        : 0x%08x (%s)",
+			rec->ExceptionCode,
+			MR_find_exception_name(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_explain_exception_record(rec);
+	MR_dump_exception_record(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_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address, int *access_mode)
+{
+	if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+		if (rec->NumberParameters >= 2) {
+			(*access_mode) = (int)rec->ExceptionInformation[0];
+			(*address) = (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_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
+{
+	void *address;
+	int access_mode;
+
+		/* If the exception is an access violation */
+	if (MR_exception_record_is_access_violation(
+			exception_ptrs->ExceptionRecord,
+			&address, &access_mode)) {
+
+			/* If we can unprotect the memory zone */
+		if (try_munprotect(address, exception_ptrs)) {
+			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_dump_exception_record(exception_ptrs->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_STRUCTURED_EXCEPTIONS */
+
 
 /*
 ** 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/27 12:16:25
@@ -37,4 +37,30 @@
 
 void	setup_signals(void);
 
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+/*
+** 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>
+
+int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs);
+#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/27 12:16:25
@@ -51,9 +51,84 @@
   #include "mercury_thread.h"
 #endif
 
+#ifdef MR_WIN32
+  #include <windows.h>
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** 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
+MR_protect_pages(void *Addr, size_t Size, int ProtFlags)
+{
+	return mprotect((char *)Addr, Size, ProtFlags);
+}
+#elif defined(MR_WIN32_VIRTUAL_ALLOC)
+/*
+** Emulate mprotect under Win32.
+** Return -1 on failure
+*/
+int
+MR_protect_pages(void *addr, size_t size, int prot_flags)
+{
+	int rc;
+	DWORD Flags, OldFlags;
+
+	if (prot_flags & PROT_WRITE) {
+		Flags = PAGE_READWRITE;
+	} else if (prot_flags & 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_VIRTUAL_ALLOC)
+/*
+** 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;
+
+	/*
+	** We don't need to use the 'unit' value as the memory is always
+	** 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
+  #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 +149,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 +169,7 @@
     #define PROT_NONE 0
   #endif
 
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
 
 /*---------------------------------------------------------------------------*/
 
@@ -256,13 +331,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 +370,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 +388,8 @@
 #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 (MR_protect_pages((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 +401,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 (MR_protect_pages((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 +411,7 @@
 			zone->top);
 		fatal_error(buf);
 	}
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_PROTECTPAGE */
 
 
 	return zone;
@@ -347,9 +423,8 @@
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
 	zone->redzone = zone->redzone_base;
 
-	if (mprotect((char *)zone->redzone,
-		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0)
-	{
+	if (MR_protect_pages((char *)zone->redzone,
+		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0) {
 		char buf[2560];
 		sprintf(buf, "unable to reset %s#%d redzone\n"
 			"base=%p, redzone=%p",
@@ -397,7 +472,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 +482,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/27 12:16:26
@@ -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,27 @@
 		(char*)((zone)->MR_zone_end) - (char *)(start_address)))
 
 /*
+** Rather then using mprotect directly, we call MR_protect_pages which
+** is OS independent.
+*/
+#ifdef MR_PROTECTPAGE
+
+  #ifdef MR_WIN32
+    #ifndef PROT_NONE
+      #define PROT_NONE  0x0000
+    #endif
+    #ifndef PROT_READ
+      #define PROT_READ  0x0001
+    #endif
+    #ifndef PROT_WRITE
+      #define PROT_WRITE 0x0002
+    #endif
+  #endif
+
+int MR_protect_pages(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 +196,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/27 12:16:30
@@ -32,6 +32,10 @@
 #include	<stdio.h>
 #include	<string.h>
 
+#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+  #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_STRUCTURED_EXCEPTIONS
+	/*
+	** Under Win32 we use the following construction to handle exceptions.
+	**   __try
+	**   {
+	**     <various stuff>
+	**   }
+	**   __except(MR_filter_win32_exception(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_STRUCTURED_EXCEPTIONS
+	}
+	__except(MR_filter_win32_exception(GetExceptionInformation()))
+	{
+		/* Everything is done in MR_filter_win32_exception */
+	}
+#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