[m-dev.] for review: use Win32 exceptions in the runtime
Peter Ross
petdr at cs.mu.OZ.AU
Wed Jun 28 23:20:11 AEST 2000
On Wed, Jun 28, 2000 at 07:44:00AM +1000, Fergus Henderson wrote:
> On 27-Jun-2000, Peter Ross <petdr at cs.mu.OZ.AU> wrote:
> > 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.
>
> Ah, I see. Thanks.
>
> I think the documentation of MR_WIN32 is not clear.
>
> For example, if MS port MSVC++ to Linux, should MR_WIN32
> be defined when using the Linux version of MSVC++?
>
Good point, a search of MSDN documentation found _WIN32 which is defined
if we are in Win32 land.
> > > > +#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.
>
> But the above definitions are not protected by `#ifndef'.
> So you define PROT_* regardless of whether or not they are already defined.
> This might cause problems on systems that define both MR_WIN32 and PROT_NONE.
> I suppose you could change them to
>
> #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
>
> and that would be a bit safer. Oh, wait, I see from the diff that is
> exactly what you did. Still, even then, there might be problems if
> those macros were not defined at this point because the appropriate
> system header file has not been included, but that system header file
> was then included later on in the compilation unit. If that were to
> happen, you might get errors in the system header file because
> PROT_NONE etc. were already defined.
>
I can live with this solution at the moment.
> > +++ runtime/mercury_memory_handlers.c Tue Jun 27 14:08:08 2000
> > @@ -554,7 +553,7 @@
> >
> > #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
> >
> > -#ifdef MR_WIN32
> > +#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
> > #include <tchar.h>
>
> Hmm, here you're assuming that MR_WIN32_STRUCTURED_EXCEPTIONS
> implies that we have <tchar.h>. Is that necessary?
> What are you using <tchar.h> for? Is it just the `_T' macro?
> What exactly does that do, and why do you need it?
>
It is something to do with Unicode strings (I believe), which we don't
need so I have removed.
> If you really do need <tchar.h>, it would be a good idea to document
> it in the documentation for MR_WIN32_STRUCTURED_EXCEPTIONS.
>
No I don't need it.
> 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
>
> Shouldn't that be `#ifdef MR_WIN32_VIRTUAL_ALLOC'?
>
Yes.
And now here is a relative diff and full diff.
Estimated hours taken: 48
Use Win32 exceptions to report problems when Win32 structured exceptions
are available.
configure.in:
runtime/mercury_conf.h.in:
No longer define MR_WIN32, just because we are using a Microsoft
compiler, instead we use _WIN32 to detect the presence of the Win32
API.
runtime/mercury_conf_param.h:
Define the following symbolic constants:
MR_WIN32 which is true if the Win32 API is available.
MR_WIN32_GETSYSTEMINFO which is true if GetSystemInfo() is
availabe.
MR_WIN32_VIRTUALALLOC which is true if VirtualAlloc() is
availabe.
MR_MSVC_STRUCTURED_EXCEPTIONS if we can use Microsoft Visual C
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.h.in runtime/mercury_conf.h.in
--- runtime.old/mercury_conf.h.in Thu Jun 8 09:59:04 2000
+++ runtime/mercury_conf.h.in Wed Jun 28 14:42:23 2000
@@ -346,12 +346,6 @@
#undef HAVE_READLINE_READLINE
#undef HAVE_READLINE_HISTORY
-/*
-** MR_WIN32
-** Set this if you are using Microsoft Visual C++ as your C compiler.
-*/
-#undef MR_WIN32
-
/*---------------------------------------------------------------------------*/
#include "mercury_conf_param.h"
diff -u runtime.old/mercury_conf_param.h runtime/mercury_conf_param.h
--- runtime.old/mercury_conf_param.h Tue Jun 27 14:15:52 2000
+++ runtime/mercury_conf_param.h Wed Jun 28 14:52:06 2000
@@ -345,18 +345,29 @@
#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)
+/*
+** MR_CHECK_OVERFLOW_VIA_MPROTECT -- Can check for overflow of various
+** memory zones using mprotect() like
+** functionality.
+*/
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(_WIN32)
#define MR_CHECK_OVERFLOW_VIA_MPROTECT
#endif
- /* The functionality of mprotect can be provided */
-#if defined(HAVE_MPROTECT) || defined(MR_WIN32)
+/*
+** MR_PROTECTPAGE -- MR_protect_pages() can be defined to provide the same
+** functionality as the system call mprotect().
+*/
+#if defined(HAVE_MPROTECT) || defined(_WIN32)
#define MR_PROTECTPAGE
#endif
-#if defined(MR_WIN32)
- #define MR_WIN32_STRUCTURED_EXCEPTIONS
+/*
+** MR_MSVC_STRUCTURED_EXCEPTIONS
+** Use Microsoft Visual C structured exceptions for signal handling.
+*/
+#if defined(_MSC_VER)
+ #define MR_MSVC_STRUCTURED_EXCEPTIONS
#endif
/*---------------------------------------------------------------------------*/
@@ -364,9 +375,18 @@
/*
** Win32 API specific.
*/
-#if defined(MR_WIN32)
- #define MR_WIN32_GETSYSTEMINFO /* to determine page size */
- #define MR_WIN32_VIRTUAL_ALLOC /* to provide mprotect functionality */
+
+/*
+** MR_WIN32 -- The Win32 API is available.
+**
+** MR_WIN32_GETSYSTEMINFO -- Is GetSystemInfo() available?
+**
+** MR_WIN32_VIRTUAL_ALLOC -- Is VirtualAlloc() available?
+*/
+#if _WIN32
+ #define MR_WIN32
+ #define MR_WIN32_GETSYSTEMINFO
+ #define MR_WIN32_VIRTUAL_ALLOC
#endif
/*---------------------------------------------------------------------------*/
diff -u runtime.old/mercury_memory.c runtime/mercury_memory.c
--- runtime.old/mercury_memory.c Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory.c Wed Jun 28 14:42:23 2000
@@ -99,8 +99,8 @@
#if defined(MR_WIN32_GETSYSTEMINFO)
#include <windows.h>
- static
- size_t getpagesize(void)
+ static size_t
+ getpagesize(void)
{
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
diff -u runtime.old/mercury_memory_handlers.c runtime/mercury_memory_handlers.c
--- runtime.old/mercury_memory_handlers.c Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_handlers.c Wed Jun 28 14:42:23 2000
@@ -222,7 +222,8 @@
(int)zone_size);
}
if (MR_protect_pages((char *)zone->redzone, zone_size,
- PROT_READ|PROT_WRITE) < 0) {
+ PROT_READ|PROT_WRITE) < 0)
+ {
char buf[2560];
sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
zone->name, zone->id);
@@ -262,10 +263,11 @@
setup_signals(void)
{
/*
-** When using Win32 structured exceptions don't set any signal handler.
+** When using Microsoft Visual C structured exceptions don't set any
+** signal handlers.
** See mercury_wrapper.c for the reason why.
*/
-#ifndef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifndef MR_MSVC_STRUCTURED_EXCEPTIONS
#ifdef SIGBUS
MR_setup_signal(SIGBUS, (Code *) bus_handler, TRUE,
"Mercury runtime: cannot set SIGBUS handler");
@@ -553,21 +555,25 @@
#endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
-#include <tchar.h>
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+static const char *MR_find_exception_name(DWORD exception_code);
+static void MR_explain_exception_record(EXCEPTION_RECORD *rec);
+static void MR_dump_exception_record(EXCEPTION_RECORD *rec);
+static bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+ void **address_ptr, int *access_mode_ptr);
/*
** Exception code and their string representation
*/
-#define DEFINE_EXCEPTION_NAME(a) {a,_T(#a)}
+#define DEFINE_EXCEPTION_NAME(a) {a,#a}
typedef struct
{
- DWORD exception_code;
- LPTSTR exception_name;
+ DWORD exception_code;
+ const char *exception_name;
} MR_ExceptionName;
-static
+static const
MR_ExceptionName MR_exception_names[] =
{
DEFINE_EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION),
@@ -598,17 +604,18 @@
/*
** Retrieve the name of a Win32 exception code as a string
*/
-static
-LPTSTR MR_find_exception_name(DWORD exception_code)
+static const char *
+MR_find_exception_name(DWORD exception_code)
{
int i;
for (i = 0; i < sizeof(MR_exception_names)
- / sizeof(MR_ExceptionName); i++) {
+ / 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");
+ return "Unknown exception code";
}
/*
@@ -621,8 +628,8 @@
/*
** Explain an EXCEPTION_RECORD content into stderr.
*/
-static
-void MR_explain_exception_record(EXCEPTION_RECORD *rec)
+static void
+MR_explain_exception_record(EXCEPTION_RECORD *rec)
{
fprintf(stderr, "\n");
fprintf(stderr, "\n*** Explanation of the exception record");
@@ -634,11 +641,12 @@
int access_mode;
/* If the exception is an access violation */
- if (MR_ExceptionrecordIsAccessViolation(rec,
- &address, &access_mode)) {
+ if (MR_exception_record_is_access_violation(rec,
+ &address, &access_mode))
+ {
MemoryZone *zone;
- /* Display AV address and acces mode */
+ /* Display AV address and access mode */
fprintf(stderr, "\n*** An access violation occured"
" at address 0x%08lx, while attempting"
" to ", (unsigned long) address);
@@ -666,21 +674,23 @@
while(zone != NULL) {
fprintf(stderr,
"\n*** Checking zone %s#%d: "
- "0x%08x - 0x%08x - 0x%08x",
+ "0x%08lx - 0x%08lx - 0x%08lx",
zone->name, zone->id,
- (void *) zone->bottom,
- (void *) zone->redzone,
- (void *) zone->top);
+ (unsigned long) zone->bottom,
+ (unsigned long) zone->redzone,
+ (unsigned long) zone->top);
if ((zone->redzone <= address) &&
- (address <= zone->top)) {
+ (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)) {
+ (address <= zone->top))
+ {
fprintf(stderr, "\n*** Address is"
" within zone %s#%d\n",
zone->name, zone->id);
@@ -701,8 +711,8 @@
/*
** Dump an EXCEPTION_RECORD content into stderr.
*/
-static
-void MR_dump_exception_record(EXCEPTION_RECORD *rec)
+static void
+MR_dump_exception_record(EXCEPTION_RECORD *rec)
{
int i;
@@ -712,16 +722,20 @@
fprintf(stderr, "\n*** Exception record at 0x%08lx:",
(unsigned long) rec);
- fprintf(stderr, "\n*** Code : 0x%08x (%s)",
- rec->ExceptionCode,
+ fprintf(stderr, "\n*** Code : 0x%08lx (%s)",
+ (unsigned long) rec->ExceptionCode,
MR_find_exception_name(rec->ExceptionCode));
- fprintf(stderr, "\n*** Flags : 0x%08x", rec->ExceptionFlags);
- fprintf(stderr, "\n*** Address : 0x%08x", rec->ExceptionAddress);
+ fprintf(stderr, "\n*** Flags : 0x%08lx",
+ (unsigned long) rec->ExceptionFlags);
+ fprintf(stderr, "\n*** Address : 0x%08lx",
+ (unsigned long) rec->ExceptionAddress);
+
for (i = 0; i < rec->NumberParameters; i++) {
- fprintf(stderr, "\n*** Parameter %d : 0x%08x", i,
- rec->ExceptionInformation[i]);
+ fprintf(stderr, "\n*** Parameter %d : 0x%08lx", i,
+ (unsigned long) rec->ExceptionInformation[i]);
}
- fprintf(stderr, "\n*** Next record : 0x%08x", rec->ExceptionRecord);
+ fprintf(stderr, "\n*** Next record : 0x%08lx",
+ (unsigned long) rec->ExceptionRecord);
/* Try to explain the exception more "gracefully" */
MR_explain_exception_record(rec);
@@ -730,17 +744,19 @@
/*
-** 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)
+** Return TRUE iff exception_ptrs indicates an access violation.
+** If TRUE, the dereferenced address_ptr is set to the accessed address and
+** the dereferenced access_mode_ptr 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)
+static bool
+MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+ void **address_ptr, int *access_mode_ptr)
{
if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
if (rec->NumberParameters >= 2) {
- (*access_mode) = (int)rec->ExceptionInformation[0];
- (*address) = (void *)rec->ExceptionInformation[1];
+ (*access_mode_ptr) = (int) rec->ExceptionInformation[0];
+ (*address_ptr) = (void *) rec->ExceptionInformation[1];
return TRUE;
}
}
@@ -749,8 +765,7 @@
/*
-** Filter a Win32 exception (to be called in the __except filter
-** part).
+** Filter a Win32 exception (to be called in the __except filter part).
** Possible return values are:
**
** EXCEPTION_CONTINUE_EXECUTION (-1)
@@ -768,7 +783,8 @@
** execution at the assembly instruction that was executing
** when the exception was raised.
*/
-int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
+int
+MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
{
void *address;
int access_mode;
@@ -776,7 +792,8 @@
/* If the exception is an access violation */
if (MR_exception_record_is_access_violation(
exception_ptrs->ExceptionRecord,
- &address, &access_mode)) {
+ &address, &access_mode))
+ {
/* If we can unprotect the memory zone */
if (try_munprotect(address, exception_ptrs)) {
@@ -803,14 +820,14 @@
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
- */
+ ** 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 */
+#endif /* MR_MSVC_STRUCTURED_EXCEPTIONS */
/*
diff -u runtime.old/mercury_memory_handlers.h runtime/mercury_memory_handlers.h
--- runtime.old/mercury_memory_handlers.h Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_handlers.h Wed Jun 28 14:42:23 2000
@@ -37,7 +37,7 @@
void setup_signals(void);
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
/*
** Filter a Win32 exception (to be called in the __except filter
** part).
diff -u runtime.old/mercury_memory_zones.c runtime/mercury_memory_zones.c
--- runtime.old/mercury_memory_zones.c Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_zones.c Wed Jun 28 15:15:37 2000
@@ -51,7 +51,7 @@
#include "mercury_thread.h"
#endif
-#ifdef MR_WIN32
+#ifdef MR_WIN32_VIRTUAL_ALLOC
#include <windows.h>
#endif
@@ -63,9 +63,9 @@
*/
#if defined(HAVE_MPROTECT)
int
-MR_protect_pages(void *Addr, size_t Size, int ProtFlags)
+MR_protect_pages(void *addr, size_t size, int prot_flags)
{
- return mprotect((char *)Addr, Size, ProtFlags);
+ return mprotect((char *) addr, size, prot_flags);
}
#elif defined(MR_WIN32_VIRTUAL_ALLOC)
/*
@@ -79,23 +79,24 @@
DWORD Flags, OldFlags;
if (prot_flags & PROT_WRITE) {
- Flags = PAGE_READWRITE;
+ flags = PAGE_READWRITE;
} else if (prot_flags & PROT_READ) {
- Flags = PAGE_READONLY;
+ flags = PAGE_READONLY;
} else {
- Flags = PAGE_NOACCESS;
+ 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%08lx, size=0x%08lx):"
+ " 0x%08lx\n", (unsigned long) addr,
+ (unsigned long) size, (unsigned long) GetLastError());
}
return rc;
}
-#endif /* HAVE_MPROTECT */
+#endif /* MR_WIN32_VIRTUAL_ALLOC */
/*---------------------------------------------------------------------------*/
@@ -110,23 +111,24 @@
void *
memalign(size_t unit, size_t size)
{
- void *rc;
+ void *ptr;
/*
** 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());
+ ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+ if (ptr == NULL) {
+ fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx):"
+ " 0x%08lx\n", (unsigned long) size,
+ (unsigned long) GetLastError());
}
#ifdef CONSERVATIVE_GC
- if (rc != NULL)
- GC_add_roots((char *)rc, (char *)rc + size);
+ if (ptr != NULL)
+ GC_add_roots((char *)ptr, (char *)ptr + size);
#endif
- return rc;
+ return ptr;
}
#elif defined(CONSERVATIVE_GC)
#define memalign(a,s) GC_MALLOC_UNCOLLECTABLE(s)
@@ -389,7 +391,8 @@
zone->redzone_base = zone->redzone = (Word *)
round_up((Unsigned)base + size - redsize, unit);
if (MR_protect_pages((char *)zone->redzone,
- redsize + unit, MY_PROT) < 0) {
+ redsize + unit, MY_PROT) < 0)
+ {
char buf[2560];
sprintf(buf, "unable to set %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 Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_zones.h Wed Jun 28 14:42:23 2000
@@ -154,7 +154,7 @@
#endif
#endif
-int MR_protect_pages(void *Addr, size_t Size, int ProtFlags);
+int MR_protect_pages(void *addr, size_t size, int prot_flags);
#endif
/*
diff -u runtime.old/mercury_wrapper.c runtime/mercury_wrapper.c
--- runtime.old/mercury_wrapper.c Tue Jun 27 14:08:08 2000
+++ runtime/mercury_wrapper.c Wed Jun 28 14:42:23 2000
@@ -32,7 +32,7 @@
#include <stdio.h>
#include <string.h>
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
#include <excpt.h>
#endif
@@ -898,7 +898,7 @@
static int repcounter;
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
/*
** Under Win32 we use the following construction to handle exceptions.
** __try
@@ -1018,7 +1018,7 @@
save_registers();
restore_regs_from_mem(c_regs);
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
}
__except(MR_filter_win32_exception(GetExceptionInformation()))
{
*** full diff ***
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.211
diff -u -r1.211 configure.in
--- configure.in 2000/06/23 07:40:34 1.211
+++ configure.in 2000/06/28 12:58:09
@@ -261,8 +261,6 @@
CYGPATH="cygpath -w"
- AC_DEFINE(MR_WIN32)
-
# MS doesn't use a ranlib.
RANLIB="echo"
AC_SUBST(RANLIB)
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.26
diff -u -r1.26 mercury_conf.h.in
--- runtime/mercury_conf.h.in 2000/06/08 07:59:04 1.26
+++ runtime/mercury_conf.h.in 2000/06/28 12:58:22
@@ -346,12 +346,6 @@
#undef HAVE_READLINE_READLINE
#undef HAVE_READLINE_HISTORY
-/*
-** MR_WIN32
-** Set this if you are using Microsoft Visual C++ as your C compiler.
-*/
-#undef MR_WIN32
-
/*---------------------------------------------------------------------------*/
#include "mercury_conf_param.h"
Index: runtime/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
--- runtime/mercury_conf_param.h 2000/04/05 06:28:55 1.36
+++ runtime/mercury_conf_param.h 2000/06/28 12:58:31
@@ -345,8 +345,48 @@
#define MR_CAN_GET_PC_AT_SIGNAL
#endif
-#if defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)
+/*
+** MR_CHECK_OVERFLOW_VIA_MPROTECT -- Can check for overflow of various
+** memory zones using mprotect() like
+** functionality.
+*/
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(_WIN32)
#define MR_CHECK_OVERFLOW_VIA_MPROTECT
+#endif
+
+/*
+** MR_PROTECTPAGE -- MR_protect_pages() can be defined to provide the same
+** functionality as the system call mprotect().
+*/
+#if defined(HAVE_MPROTECT) || defined(_WIN32)
+ #define MR_PROTECTPAGE
+#endif
+
+/*
+** MR_MSVC_STRUCTURED_EXCEPTIONS
+** Use Microsoft Visual C structured exceptions for signal handling.
+*/
+#if defined(_MSC_VER)
+ #define MR_MSVC_STRUCTURED_EXCEPTIONS
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Win32 API specific.
+*/
+
+/*
+** MR_WIN32 -- The Win32 API is available.
+**
+** MR_WIN32_GETSYSTEMINFO -- Is GetSystemInfo() available?
+**
+** MR_WIN32_VIRTUAL_ALLOC -- Is VirtualAlloc() available?
+*/
+#if _WIN32
+ #define MR_WIN32
+ #define MR_WIN32_GETSYSTEMINFO
+ #define MR_WIN32_VIRTUAL_ALLOC
#endif
/*---------------------------------------------------------------------------*/
Index: runtime/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
--- runtime/mercury_memory.c 2000/06/08 07:59:04 1.18
+++ runtime/mercury_memory.c 2000/06/28 12:58:33
@@ -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: runtime/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
--- runtime/mercury_memory_handlers.c 2000/06/08 07:59:04 1.11
+++ runtime/mercury_memory_handlers.c 2000/06/28 12:58:37
@@ -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,8 +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",
@@ -262,12 +262,19 @@
void
setup_signals(void)
{
-#ifdef SIGBUS
+/*
+** When using Microsoft Visual C structured exceptions don't set any
+** signal handlers.
+** See mercury_wrapper.c for the reason why.
+*/
+#ifndef MR_MSVC_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 +554,281 @@
}
#endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
+
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+static const char *MR_find_exception_name(DWORD exception_code);
+static void MR_explain_exception_record(EXCEPTION_RECORD *rec);
+static void MR_dump_exception_record(EXCEPTION_RECORD *rec);
+static bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+ void **address_ptr, int *access_mode_ptr);
+
+/*
+** Exception code and their string representation
+*/
+#define DEFINE_EXCEPTION_NAME(a) {a,#a}
+
+typedef struct
+{
+ DWORD exception_code;
+ const char *exception_name;
+} MR_ExceptionName;
+
+static const
+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 const char *
+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 "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_exception_record_is_access_violation(rec,
+ &address, &access_mode))
+ {
+ MemoryZone *zone;
+
+ /* Display AV address and access 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%08lx - 0x%08lx - 0x%08lx",
+ zone->name, zone->id,
+ (unsigned long) zone->bottom,
+ (unsigned long) zone->redzone,
+ (unsigned long) 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%08lx (%s)",
+ (unsigned long) rec->ExceptionCode,
+ MR_find_exception_name(rec->ExceptionCode));
+ fprintf(stderr, "\n*** Flags : 0x%08lx",
+ (unsigned long) rec->ExceptionFlags);
+ fprintf(stderr, "\n*** Address : 0x%08lx",
+ (unsigned long) rec->ExceptionAddress);
+
+ for (i = 0; i < rec->NumberParameters; i++) {
+ fprintf(stderr, "\n*** Parameter %d : 0x%08lx", i,
+ (unsigned long) rec->ExceptionInformation[i]);
+ }
+ fprintf(stderr, "\n*** Next record : 0x%08lx",
+ (unsigned long) rec->ExceptionRecord);
+
+ /* Try to explain the exception more "gracefully" */
+ MR_explain_exception_record(rec);
+ MR_dump_exception_record(rec->ExceptionRecord);
+}
+
+
+/*
+** Return TRUE iff exception_ptrs indicates an access violation.
+** If TRUE, the dereferenced address_ptr is set to the accessed address and
+** the dereferenced access_mode_ptr is set to the desired access
+** (0 = read, 1 = write)
+*/
+static bool
+MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+ void **address_ptr, int *access_mode_ptr)
+{
+ if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+ if (rec->NumberParameters >= 2) {
+ (*access_mode_ptr) = (int) rec->ExceptionInformation[0];
+ (*address_ptr) = (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_MSVC_STRUCTURED_EXCEPTIONS */
+
/*
** get_pc_from_context:
Index: runtime/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
--- runtime/mercury_memory_handlers.h 1998/05/14 06:35:09 1.2
+++ runtime/mercury_memory_handlers.h 2000/06/28 12:58:37
@@ -37,4 +37,30 @@
void setup_signals(void);
+#ifdef MR_MSVC_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: runtime/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
--- runtime/mercury_memory_zones.c 2000/06/08 07:59:05 1.10
+++ runtime/mercury_memory_zones.c 2000/06/28 12:58:39
@@ -51,9 +51,86 @@
#include "mercury_thread.h"
#endif
+#ifdef MR_WIN32_VIRTUAL_ALLOC
+ #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%08lx, size=0x%08lx):"
+ " 0x%08lx\n", (unsigned long) addr,
+ (unsigned long) size, (unsigned long) GetLastError());
+ }
+
+ return rc;
+}
+#endif /* MR_WIN32_VIRTUAL_ALLOC */
+
-#ifdef CONSERVATIVE_GC
+/*---------------------------------------------------------------------------*/
+
+
+#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 *ptr;
+
+ /*
+ ** We don't need to use the 'unit' value as the memory is always
+ ** aligned under Win32.
+ */
+ ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+ if (ptr == NULL) {
+ fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx):"
+ " 0x%08lx\n", (unsigned long) size,
+ (unsigned long) GetLastError());
+ }
+
+ #ifdef CONSERVATIVE_GC
+ if (ptr != NULL)
+ GC_add_roots((char *)ptr, (char *)ptr + size);
+ #endif
+ return ptr;
+}
+#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,9 @@
#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 +404,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 +414,7 @@
zone->top);
fatal_error(buf);
}
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
return zone;
@@ -347,9 +426,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 +475,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 +485,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: runtime/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
--- runtime/mercury_memory_zones.h 1999/10/05 20:21:41 1.5
+++ runtime/mercury_memory_zones.h 2000/06/28 12:58:41
@@ -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 prot_flags);
+#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: runtime/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
--- runtime/mercury_wrapper.c 2000/06/08 07:59:06 1.62
+++ runtime/mercury_wrapper.c 2000/06/28 12:58:45
@@ -32,6 +32,10 @@
#include <stdio.h>
#include <string.h>
+#ifdef MR_MSVC_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_MSVC_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_MSVC_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