[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