/* Windows exception handling */
/* Support for handling exceptions in Dylan (other than MM traps) */
/* Currently, we just handle stack overflows arithmetic exceptions */
extern int inside_dylan_ffi_barrier();
extern void dylan_stack_overflow_handler(PVOID base_address, int size, DWORD protection);
extern void dylan_integer_overflow_handler();
extern void dylan_integer_divide_0_handler();
extern void dylan_float_divide_0_handler();
extern void dylan_float_overflow_handler();
extern void dylan_float_underflow_handler();
PVOID current_stack_pointer ()
{
PVOID stack_ptr;
__asm
{
mov stack_ptr, esp
};
return(stack_ptr);
};
#define VPAGESIZE 0x1000
void call_dylan_stack_overflow_handler ()
{
MEMORY_BASIC_INFORMATION memBuf;
PVOID stack_ptr = current_stack_pointer();
int res = VirtualQuery(stack_ptr, &memBuf, sizeof(memBuf));
PVOID baseAddress = memBuf.BaseAddress; // base address of region
PVOID allocationBase = memBuf.AllocationBase; // allocation base address
DWORD protect = memBuf.Protect; // current access protection
dylan_stack_overflow_handler(baseAddress, VPAGESIZE, PAGE_GUARD + protect);
}
/* Establish the stack overflow filter outside the MPS handler because
it has less requirement for efficiency */
#define EXCEPTION_PREAMBLE() \
__try {
#define EXCEPTION_POSTAMBLE() \
} \
__except (DylanExceptionFilter(GetExceptionInformation())) { }
LONG DylanExceptionFilter (LPEXCEPTION_POINTERS info)
{
LPEXCEPTION_RECORD er = info->ExceptionRecord;
if (inside_dylan_ffi_barrier() == 0)
{ return(EXCEPTION_CONTINUE_SEARCH);
}
switch (er->ExceptionCode)
{
case EXCEPTION_STACK_OVERFLOW:
{
// On a stack overflow, the filter calls into Dylan to signal
// an error, via dylan_signal_overflow_handler. The dylan
// code will arrange to re-establish the guard protection on
// the appropriate page of the stack (probably during the
// rewind when recovering from the error). Before calling the
// handler, we do a check to ensure that there is sufficient
// spare stack space after the guard to allow the handler itself
// to run.
MEMORY_BASIC_INFORMATION memBuf;
PVOID stack_ptr = current_stack_pointer();
int res = VirtualQuery(stack_ptr, &memBuf, sizeof(memBuf));
PVOID baseAddress = memBuf.BaseAddress; // base address of region
PVOID allocationBase = memBuf.AllocationBase; // allocation base addr
if ( ((int)baseAddress - (int)allocationBase) >= (2 * VPAGESIZE))
{
// There's enough space past the guard to invoke the Dylan handler.
// Rather than attempt a long-jump within the filter (by simply
// calling the Dylan handler) we destructively modify the execution
// context, so that when Windows continues from the exception, it
// actually continues in the Dylan handler calling code instead.
// This handler will never return - instead it will ultimatly NLX
info->ContextRecord->Eip = (unsigned long) &call_dylan_stack_overflow_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
else
return(EXCEPTION_CONTINUE_SEARCH);
}
case EXCEPTION_INT_OVERFLOW:
{ info->ContextRecord->Eip = (unsigned long) &dylan_integer_overflow_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
case EXCEPTION_INT_DIVIDE_BY_ZERO:
{ info->ContextRecord->Eip = (unsigned long) &dylan_integer_divide_0_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
{ info->ContextRecord->Eip = (unsigned long) &dylan_float_divide_0_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
case EXCEPTION_FLT_OVERFLOW:
{ info->ContextRecord->Eip = (unsigned long) &dylan_float_overflow_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
case EXCEPTION_FLT_UNDERFLOW:
{ info->ContextRecord->Eip = (unsigned long) &dylan_float_underflow_handler;
return(EXCEPTION_CONTINUE_EXECUTION);
}
/*
case DBG_CONTROL_C:
{ dylan_keyboard_interruptQ = TRUE;
return(EXCEPTION_CONTINUE_EXECUTION);
}
*/
default:
return(EXCEPTION_CONTINUE_SEARCH);
}
}
syntax highlighted by Code2HTML, v. 0.9.1