if (start)
return start;
- /* restore_contect (struct sigcontext *ctx) */
+ /* restore_contect (MonoContext *ctx) */
/* we do not restore X86_EAX, X86_EDX */
start = code = mono_global_codeman_reserve (128);
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
/* get return address, stored in EDX */
- x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EIP), 4);
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4);
/* restore EBX */
- x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBX), 4);
+ x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
/* restore EDI */
- x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EDI), 4);
+ x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* restore ESI */
- x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_ESI), 4);
+ x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
/* restore ESP */
- x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_ESP), 4);
+ x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4);
/* restore EBP */
- x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBP), 4);
+ x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* jump to the saved IP */
x86_jump_reg (code, X86_EDX);
return start;
inited = 1;
- /* call_filter (struct sigcontext *ctx, unsigned long eip) */
+ /* call_filter (MonoContext *ctx, unsigned long eip) */
start = code = mono_global_codeman_reserve (64);
x86_push_reg (code, X86_EBP);
x86_push_reg (code, X86_EBP);
/* set new EBP */
- x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBP), 4);
+ x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* restore registers used by global register allocation (EBX & ESI) */
- x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBX), 4);
- x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_ESI), 4);
- x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EDI), 4);
+ x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
+ x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
+ x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* call the handler */
x86_call_reg (code, X86_ECX);
unsigned long esi, unsigned long edi, unsigned long ebp, MonoObject *exc,
unsigned long eip, unsigned long esp, gboolean rethrow)
{
- static void (*restore_context) (struct sigcontext *);
- struct sigcontext ctx;
+ static void (*restore_context) (MonoContext *);
+ MonoContext ctx;
if (!restore_context)
restore_context = mono_arch_get_restore_context ();
/* Pop argument and return address */
- ctx.SC_ESP = esp + (2 * sizeof (gpointer));
- ctx.SC_EIP = eip;
- ctx.SC_EBP = ebp;
- ctx.SC_EDI = edi;
- ctx.SC_ESI = esi;
- ctx.SC_EBX = ebx;
- ctx.SC_EDX = edx;
- ctx.SC_ECX = ecx;
- ctx.SC_EAX = eax;
+ ctx.esp = esp + (2 * sizeof (gpointer));
+ ctx.eip = eip;
+ ctx.ebp = ebp;
+ ctx.edi = edi;
+ ctx.esi = esi;
+ ctx.ebx = ebx;
+ ctx.edx = edx;
+ ctx.ecx = ecx;
+ ctx.eax = eax;
if (mono_debugger_throw_exception ((gpointer)(eip - 5), (gpointer)esp, exc)) {
/*
* By the time we get here, it already inserted a breakpoint on
* eip - 5 (which is the address of the call).
*/
- ctx.SC_EIP = eip - 5;
- ctx.SC_ESP = esp + sizeof (gpointer);
+ ctx.eip = eip - 5;
+ ctx.esp = esp + sizeof (gpointer);
restore_context (&ctx);
g_assert_not_reached ();
}
/* adjust eip so that it point into the call instruction */
- ctx.SC_EIP -= 1;
+ ctx.eip -= 1;
if (mono_object_isinst (exc, mono_defaults.exception_class)) {
MonoException *mono_ex = (MonoException*)exc;
* code, since otherwise the lmf was already popped of the stack.
*/
if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
- new_ctx->SC_ESI = (*lmf)->esi;
- new_ctx->SC_EDI = (*lmf)->edi;
- new_ctx->SC_EBX = (*lmf)->ebx;
+ new_ctx->esi = (*lmf)->esi;
+ new_ctx->edi = (*lmf)->edi;
+ new_ctx->ebx = (*lmf)->ebx;
}
}
else {
offset = -1;
/* restore caller saved registers */
if (ji->used_regs & X86_EBX_MASK) {
- new_ctx->SC_EBX = *((int *)ctx->SC_EBP + offset);
+ new_ctx->ebx = *((int *)ctx->ebp + offset);
offset--;
}
if (ji->used_regs & X86_EDI_MASK) {
- new_ctx->SC_EDI = *((int *)ctx->SC_EBP + offset);
+ new_ctx->edi = *((int *)ctx->ebp + offset);
offset--;
}
if (ji->used_regs & X86_ESI_MASK) {
- new_ctx->SC_ESI = *((int *)ctx->SC_EBP + offset);
+ new_ctx->esi = *((int *)ctx->ebp + offset);
}
}
}
/* Pop EBP and the return address */
- new_ctx->SC_ESP = ctx->SC_EBP + (2 * sizeof (gpointer));
+ new_ctx->esp = ctx->SC_EBP + (2 * sizeof (gpointer));
/* we substract 1, so that the IP points into the call instruction */
- new_ctx->SC_EIP = *((int *)ctx->SC_EBP + 1) - 1;
- new_ctx->SC_EBP = *((int *)ctx->SC_EBP);
+ new_ctx->eip = *((int *)ctx->ebp + 1) - 1;
+ new_ctx->ebp = *((int *)ctx->ebp);
/* Pop arguments off the stack */
{
MonoJitArgumentInfo *arg_info = g_newa (MonoJitArgumentInfo, mono_method_signature (ji->method)->param_count + 1);
guint32 stack_to_pop = mono_arch_get_argument_info (mono_method_signature (ji->method), mono_method_signature (ji->method)->param_count, arg_info);
- new_ctx->SC_ESP += stack_to_pop;
+ new_ctx->esp += stack_to_pop;
}
return ji;
res->method = (*lmf)->method;
}
- new_ctx->SC_ESI = (*lmf)->esi;
- new_ctx->SC_EDI = (*lmf)->edi;
- new_ctx->SC_EBX = (*lmf)->ebx;
- new_ctx->SC_EBP = (*lmf)->ebp;
- new_ctx->SC_EIP = (*lmf)->eip;
+ new_ctx->esi = (*lmf)->esi;
+ new_ctx->edi = (*lmf)->edi;
+ new_ctx->ebx = (*lmf)->ebx;
+ new_ctx->ebp = (*lmf)->ebp;
+ new_ctx->eip = (*lmf)->eip;
/* the lmf is always stored on the stack, so the following
* expression points to a stack location which can be used as ESP */
- new_ctx->SC_ESP = (unsigned long)&((*lmf)->eip);
+ new_ctx->esp = (unsigned long)&((*lmf)->eip);
*lmf = (*lmf)->previous_lmf;
return NULL;
}
-/**
- * mono_arch_handle_exception:
- *
- * @ctx: saved processor state
- * @obj: the exception object
- */
-gboolean
-mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
+void
+mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
{
- return mono_handle_exception (sigctx, obj, mono_arch_ip_from_context (sigctx), test_only);
+ ucontext_t *ctx = (ucontext_t*)sigctx;
+
+#ifdef MONO_ARCH_USE_SIGACTION
+ mctx->eax = ctx->uc_mcontext.gregs [REG_EAX];
+ mctx->ebx = ctx->uc_mcontext.gregs [REG_EBX];
+ mctx->ecx = ctx->uc_mcontext.gregs [REG_ECX];
+ mctx->edx = ctx->uc_mcontext.gregs [REG_EDX];
+ mctx->ebp = ctx->uc_mcontext.gregs [REG_EBP];
+ mctx->esp = ctx->uc_mcontext.gregs [REG_ESP];
+ mctx->esi = ctx->uc_mcontext.gregs [REG_ESI];
+ mctx->edi = ctx->uc_mcontext.gregs [REG_EDI];
+ mctx->eip = ctx->uc_mcontext.gregs [REG_EIP];
+#else
+ memcpy (mctx, sigctx, sizeof (MonoContext));
+#endif
}
+void
+mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
+{
+ ucontext_t *ctx = (ucontext_t*)sigctx;
+
+#ifdef MONO_ARCH_USE_SIGACTION
+ ctx->uc_mcontext.gregs [REG_EAX] = mctx->eax;
+ ctx->uc_mcontext.gregs [REG_EBX] = mctx->ebx;
+ ctx->uc_mcontext.gregs [REG_ECX] = mctx->ecx;
+ ctx->uc_mcontext.gregs [REG_EDX] = mctx->edx;
+ ctx->uc_mcontext.gregs [REG_EBP] = mctx->ebp;
+ ctx->uc_mcontext.gregs [REG_ESP] = mctx->esp;
+ ctx->uc_mcontext.gregs [REG_ESI] = mctx->esi;
+ ctx->uc_mcontext.gregs [REG_EDI] = mctx->edi;
+ ctx->uc_mcontext.gregs [REG_EIP] = mctx->eip;
+#else
+ memcpy (ctx, mctx, sizeof (MonoContext));
+#endif
+}
+
gpointer
mono_arch_ip_from_context (void *sigctx)
{
+#ifdef MONO_ARCH_USE_SIGACTION
+ ucontext_t *ctx = (ucontext_t*)sigctx;
+ return (gpointer)ctx->uc_mcontext.gregs [REG_EIP];
+#else
struct sigcontext *ctx = sigctx;
return (gpointer)ctx->SC_EIP;
+#endif
}
+gboolean
+mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
+{
+ MonoContext mctx;
+
+ mono_arch_sigctx_to_monoctx (sigctx, &mctx);
+
+ mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);
+
+ mono_arch_monoctx_to_sigctx (&mctx, sigctx);
+
+ return TRUE;
+}
#include <string.h>
#include <math.h>
+#ifndef PLATFORM_WIN32
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/threads.h>
gboolean
mono_arch_is_int_overflow (void *sigctx, void *info)
{
- struct sigcontext *ctx = (struct sigcontext*)sigctx;
+ MonoContext ctx;
guint8* ip;
- ip = (guint8*)ctx->SC_EIP;
+ mono_arch_sigctx_to_monoctx (sigctx, &ctx);
+
+ ip = (guint8*)ctx.eip;
if ((ip [0] == 0xf7) && (x86_modrm_mod (ip [1]) == 0x3) && (x86_modrm_reg (ip [1]) == 0x7)) {
gint32 reg;
/* idiv REG */
switch (x86_modrm_rm (ip [1])) {
case X86_ECX:
- reg = ctx->SC_ECX;
+ reg = ctx.ecx;
break;
case X86_EBX:
- reg = ctx->SC_EBX;
+ reg = ctx.ebx;
break;
default:
g_assert_not_reached ();
{
}
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+
+static void
+setup_stack (MonoJitTlsData *tls)
+{
+ pthread_t self = pthread_self();
+ pthread_attr_t attr;
+ size_t stsize = 0;
+ struct sigaltstack sa;
+ guint8 *staddr = NULL;
+ guint8 *current = (guint8*)&staddr;
+
+ if (mono_running_on_valgrind ())
+ return;
+
+ /* Determine stack boundaries */
+#ifdef HAVE_PTHREAD_GETATTR_NP
+ pthread_getattr_np( self, &attr );
+#else
+#ifdef HAVE_PTHREAD_ATTR_GET_NP
+ pthread_attr_get_np( self, &attr );
+#elif defined(sun)
+ pthread_attr_init( &attr );
+ pthread_attr_getstacksize( &attr, &stsize );
+#else
+#error "Not implemented"
+#endif
+#endif
+#ifndef sun
+ pthread_attr_getstack( &attr, (void**)&staddr, &stsize );
+#endif
+
+ g_assert (staddr);
+
+ g_assert ((current > staddr) && (current < staddr + stsize));
+
+ tls->end_of_stack = staddr + stsize;
+
+ /*
+ * threads created by nptl does not seem to have a guard page, and
+ * since the main thread is not created by us, we can't even set one.
+ * Increasing stsize fools the SIGSEGV signal handler into thinking this
+ * is a stack overflow exception.
+ */
+ tls->stack_size = stsize + getpagesize ();
+
+ /* Setup an alternate signal stack */
+ tls->signal_stack = mmap (0, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ tls->signal_stack_size = SIGNAL_STACK_SIZE;
+
+ g_assert (tls->signal_stack);
+
+ sa.ss_sp = tls->signal_stack;
+ sa.ss_size = SIGNAL_STACK_SIZE;
+ sa.ss_flags = SS_ONSTACK;
+ sigaltstack (&sa, NULL);
+}
+
+#endif
+
/*
* Support for fast access to the thread-local lmf structure using the GS
* segment register on NPTL + kernel 2.6.x.
void
mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
{
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- pthread_t self = pthread_self();
- pthread_attr_t attr;
- void *staddr = NULL;
- size_t stsize = 0;
- struct sigaltstack sa;
-#endif
-
if (!tls_offset_inited) {
if (!getenv ("MONO_NO_TLS")) {
#ifdef PLATFORM_WIN32
}
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-
- /* Determine stack boundaries */
- if (!mono_running_on_valgrind ()) {
-#ifdef HAVE_PTHREAD_GETATTR_NP
- pthread_getattr_np( self, &attr );
-#else
-#ifdef HAVE_PTHREAD_ATTR_GET_NP
- pthread_attr_get_np( self, &attr );
-#elif defined(sun)
- pthread_attr_init( &attr );
- pthread_attr_getstacksize( &attr, &stsize );
-#else
-#error "Not implemented"
-#endif
-#endif
-#ifndef sun
- pthread_attr_getstack( &attr, &staddr, &stsize );
-#endif
- }
-
- /*
- * staddr seems to be wrong for the main thread, so we keep the value in
- * tls->end_of_stack
- */
- tls->stack_size = stsize;
-
- /* Setup an alternate signal stack */
- tls->signal_stack = g_malloc (SIGNAL_STACK_SIZE);
- tls->signal_stack_size = SIGNAL_STACK_SIZE;
-
- sa.ss_sp = tls->signal_stack;
- sa.ss_size = SIGNAL_STACK_SIZE;
- sa.ss_flags = SS_ONSTACK;
- sigaltstack (&sa, NULL);
+ setup_stack (tls);
#endif
}
sigaltstack (&sa, NULL);
if (tls->signal_stack)
- g_free (tls->signal_stack);
+ munmap (tls->signal_stack, SIGNAL_STACK_SIZE);
#endif
}
#endif /* PLATFORM_WIN32 */
#ifdef sun // Solaris x86
-# undef SIGSEGV_ON_ALTSTACK
# define MONO_ARCH_USE_SIGACTION 1
struct sigcontext {
unsigned short gs, __gsh;
};
#endif // sun, Solaris x86
+#ifdef __linux__
+#define MONO_ARCH_USE_SIGACTION
+#endif
+
+#ifndef PLATFORM_WIN32
+
+#ifdef HAVE_WORKING_SIGALTSTACK
+
+#define MONO_ARCH_SIGSEGV_ON_ALTSTACK
+#define MONO_ARCH_USE_SIGACTION
+
+/* NetBSD doesn't define SA_STACK */
+#ifndef SA_STACK
+#define SA_STACK SA_ONSTACK
+#endif
+#endif
+
+#endif
+
/* Enables OP_LSHL, OP_LSHL_IMM, OP_LSHR, OP_LSHR_IMM, OP_LSHR_UN, OP_LSHR_UN_IMM */
#define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
# define SC_ESI esi
#endif
+#ifdef MONO_ARCH_USE_SIGACTION
+
+typedef struct {
+ guint32 eax;
+ guint32 ebx;
+ guint32 ecx;
+ guint32 edx;
+ guint32 ebp;
+ guint32 esp;
+ guint32 esi;
+ guint32 edi;
+ guint32 eip;
+} MonoContext;
+
+#else
+
typedef struct sigcontext MonoContext;
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->SC_EIP = (long)(ip); } while (0);
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->SC_EBP = (long)(bp); } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->SC_ESP = (long)(esp); } while (0);
+#endif
+
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->eip = (long)(ip); } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->ebp = (long)(bp); } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->esp = (long)(sp); } while (0);
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->SC_EIP))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->SC_EBP))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->SC_ESP))
+#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->eip))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->ebp))
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->esp))
#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do { \
mono_arch_flush_register_windows (); \
MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
} while (0)
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_WORKING_SIGALTSTACK
-#define MONO_ARCH_SIGSEGV_ON_ALTSTACK
-/* NetBSD doesn't define SA_STACK */
-#ifndef SA_STACK
-#define SA_STACK SA_ONSTACK
-#endif
-#endif
-
-#endif
-
#define MONO_ARCH_BIGMUL_INTRINS 1
#define MONO_ARCH_NEED_DIV_CHECK 1
#define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1