#define ALIGN_TO(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
#ifdef TARGET_WIN32
+static void (*restore_stack) (void);
static MonoW32ExceptionHandler fpe_handler;
static MonoW32ExceptionHandler ill_handler;
static MonoW32ExceptionHandler segv_handler;
return EXCEPTION_CONTINUE_SEARCH;
}
+static gpointer
+get_win32_restore_stack (void)
+{
+ static guint8 *start = NULL;
+ guint8 *code;
+
+ if (start)
+ return start;
+
+ /* restore_stack (void) */
+ start = code = mono_global_codeman_reserve (128);
+
+ amd64_push_reg (code, AMD64_RBP);
+ amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, 8);
+
+ /* push 32 bytes of stack space for Win64 calling convention */
+ amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 32);
+
+ /* restore guard page */
+ amd64_mov_reg_imm (code, AMD64_R11, _resetstkoflw);
+ amd64_call_reg (code, AMD64_R11);
+
+ /* get jit_tls with context to restore */
+ amd64_mov_reg_imm (code, AMD64_R11, mono_tls_get_jit_tls);
+ amd64_call_reg (code, AMD64_R11);
+
+ /* move jit_tls from return reg to arg reg */
+ amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, 8);
+
+ /* retrieve pointer to saved context */
+ amd64_alu_reg_imm (code, X86_ADD, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, stack_restore_ctx));
+
+ /* this call does not return */
+ amd64_mov_reg_imm (code, AMD64_R11, mono_restore_context);
+ amd64_call_reg (code, AMD64_R11);
+
+ g_assert ((code - start) < 128);
+
+ mono_arch_flush_icache (start, code - start);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
+
+ return start;
+}
+
/*
* Unhandled Exception Filter
* Top-level per-process exception handler.
CONTEXT* ctx;
LONG res;
MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
+ MonoDomain* domain = mono_domain_get ();
/* If the thread is not managed by the runtime return early */
if (!jit_tls)
ctx = ep->ContextRecord;
switch (er->ExceptionCode) {
+ case EXCEPTION_STACK_OVERFLOW:
+ if (!mono_aot_only) {
+ if (mono_arch_handle_exception (ctx, domain->stack_overflow_ex)) {
+ /* need to restore stack protection once stack is unwound
+ * restore_stack will restore stack protection and then
+ * resume control to the saved stack_restore_ctx */
+ mono_sigctx_to_monoctx (ctx, &jit_tls->stack_restore_ctx);
+ ctx->Rip = (guint64)restore_stack;
+ }
+ } else {
+ jit_tls->mono_win_chained_exception_needs_run = TRUE;
+ }
+ break;
case EXCEPTION_ACCESS_VIOLATION:
W32_SEH_HANDLE_EX(segv);
break;
void win32_seh_init()
{
+ if (!mono_aot_only)
+ restore_stack = get_win32_restore_stack ();
+
mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_unhandled_exception_filter);
mono_win_vectored_exception_handle = AddVectoredExceptionHandler (1, seh_vectored_exception_handler);
}