#include <mono/metadata/exception.h>
#include <mono/metadata/gc-internal.h>
#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include "mini.h"
#include "mini-x86.h"
/* restore_contect (struct sigcontext *ctx) */
/* we do not restore X86_EAX, X86_EDX */
- start = code = g_malloc (1024);
+ start = code = mono_global_codeman_reserve (128);
/* load ctx */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
gpointer
mono_arch_get_call_filter (void)
{
- static guint8 start [64];
+ static guint8* start;
static int inited = 0;
guint8 *code;
inited = 1;
/* call_filter (struct sigcontext *ctx, unsigned long eip) */
- code = start;
+ start = code = mono_global_codeman_reserve (64);
x86_push_reg (code, X86_EBP);
x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
static void
throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx,
unsigned long esi, unsigned long edi, unsigned long ebp, MonoObject *exc,
- unsigned long eip, unsigned long esp)
+ unsigned long eip, unsigned long esp, gboolean rethrow)
{
static void (*restore_context) (struct sigcontext *);
struct sigcontext ctx;
if (!restore_context)
restore_context = mono_arch_get_restore_context ();
- /* adjust eip so that it point into the call instruction */
- eip -= 1;
-
/* Pop argument and return address */
ctx.SC_ESP = esp + (2 * sizeof (gpointer));
ctx.SC_EIP = eip;
ctx.SC_EDX = edx;
ctx.SC_ECX = ecx;
ctx.SC_EAX = eax;
-
- mono_handle_exception (&ctx, exc, eip + 1, FALSE);
+
+ if (mono_debugger_throw_exception ((gpointer)(eip - 5), (gpointer)esp, exc)) {
+ /*
+ * The debugger wants us to stop on the `throw' instruction.
+ * 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);
+ restore_context (&ctx);
+ g_assert_not_reached ();
+ }
+
+ /* adjust eip so that it point into the call instruction */
+ ctx.SC_EIP -= 1;
+
+ if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+ MonoException *mono_ex = (MonoException*)exc;
+ if (!rethrow)
+ mono_ex->stack_trace = NULL;
+ }
+ mono_handle_exception (&ctx, exc, (gpointer)eip, FALSE);
restore_context (&ctx);
g_assert_not_reached ();
}
+static guint8*
+get_throw_exception (gboolean rethrow)
+{
+ guint8 *start, *code;
+
+ start = code = mono_global_codeman_reserve (64);
+
+ x86_push_reg (code, X86_ESP);
+ x86_push_membase (code, X86_ESP, 4); /* IP */
+ x86_push_membase (code, X86_ESP, 12); /* exception */
+ x86_push_reg (code, X86_EBP);
+ x86_push_reg (code, X86_EDI);
+ x86_push_reg (code, X86_ESI);
+ x86_push_reg (code, X86_EBX);
+ x86_push_reg (code, X86_EDX);
+ x86_push_reg (code, X86_ECX);
+ x86_push_reg (code, X86_EAX);
+ x86_call_code (code, throw_exception);
+ /* we should never reach this breakpoint */
+ x86_breakpoint (code);
+
+ g_assert ((code - start) < 64);
+
+ return start;
+}
+
/**
* mono_arch_get_throw_exception:
*
gpointer
mono_arch_get_throw_exception (void)
{
- static guint8 start [24];
+ static guint8 *start;
static int inited = 0;
- guint8 *code;
if (inited)
return start;
+ start = get_throw_exception (FALSE);
+
inited = 1;
- code = start;
- x86_push_reg (code, X86_ESP);
- x86_push_membase (code, X86_ESP, 4); /* IP */
- x86_push_membase (code, X86_ESP, 12); /* exception */
- x86_push_reg (code, X86_EBP);
- x86_push_reg (code, X86_EDI);
- x86_push_reg (code, X86_ESI);
- x86_push_reg (code, X86_EBX);
- x86_push_reg (code, X86_EDX);
- x86_push_reg (code, X86_ECX);
- x86_push_reg (code, X86_EAX);
- x86_call_code (code, throw_exception);
- /* we should never reach this breakpoint */
- x86_breakpoint (code);
+ return start;
+}
+
+gpointer
+mono_arch_get_rethrow_exception (void)
+{
+ static guint8 *start;
+ static int inited = 0;
+
+ if (inited)
+ return start;
+
+ start = get_throw_exception (TRUE);
+
+ inited = 1;
- g_assert ((code - start) < 24);
return start;
}
*
* Returns a function pointer which can be used to raise
* corlib exceptions. The returned function has the following
- * signature: void (*func) (char *exc_name);
+ * signature: void (*func) (gpointer ip, char *exc_name);
* For example to raise an arithmetic exception you can use:
*
* x86_push_imm (code, "ArithmeticException");
- * x86_call_code (code, arch_get_throw_exception_by_name ());
+ * x86_push_imm (code, <IP>)
+ * x86_jump_code (code, arch_get_throw_exception_by_name ());
*
*/
gpointer
mono_arch_get_throw_exception_by_name (void)
{
- static guint8 start [32];
+ static guint8* start;
static int inited = 0;
guint8 *code;
return start;
inited = 1;
- code = start;
+ code = start = mono_global_codeman_reserve (32);
x86_push_membase (code, X86_ESP, 4); /* exception name */
x86_push_imm (code, "System");
return start;
}
+/**
+ * mono_arch_get_throw_corlib_exception:
+ *
+ * Returns a function pointer which can be used to raise
+ * corlib exceptions. The returned function has the following
+ * signature: void (*func) (guint32 ex_token, guint32 offset);
+ * Here, offset is the offset which needs to be substracted from the caller IP
+ * to get the IP of the throw. Passing the offset has the advantage that it
+ * needs no relocations in the caller.
+ */
+gpointer
+mono_arch_get_throw_corlib_exception (void)
+{
+ static guint8* start;
+ static int inited = 0;
+ guint8 *code;
+
+ if (inited)
+ return start;
+
+ inited = 1;
+ code = start = mono_global_codeman_reserve (64);
+
+ x86_push_membase (code, X86_ESP, 4); /* token */
+ x86_push_imm (code, mono_defaults.exception_class->image);
+ x86_call_code (code, mono_exception_from_token);
+ x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
+ /* Compute caller ip */
+ x86_pop_reg (code, X86_ECX);
+ /* Pop token */
+ x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
+ x86_pop_reg (code, X86_EDX);
+ x86_alu_reg_reg (code, X86_SUB, X86_ECX, X86_EDX);
+ /* Push exception object */
+ x86_push_reg (code, X86_EAX);
+ /* Push throw IP */
+ x86_push_reg (code, X86_ECX);
+ x86_jump_code (code, mono_arch_get_throw_exception ());
+
+ g_assert ((code - start) < 64);
+
+ return start;
+}
+
/* mono_arch_find_jit_info:
*
* This function is used to gather information from @ctx. It return the
else
ji = mono_jit_info_table_find (domain, ip);
- if (trace)
- *trace = NULL;
-
- if (native_offset)
- *native_offset = -1;
-
if (managed)
*managed = FALSE;
if (ji != NULL) {
- char *source_location, *tmpaddr, *fname;
- gint32 address, iloffset;
int offset;
*new_ctx = *ctx;
- address = (char *)ip - (char *)ji->code_start;
-
- if (native_offset)
- *native_offset = address;
-
if (managed)
if (!ji->method->wrapper_type)
*managed = TRUE;
- if (trace) {
- source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain);
- iloffset = mono_debug_il_offset_from_address (ji->method, address, domain);
-
- if (iloffset < 0)
- tmpaddr = g_strdup_printf ("<0x%05x>", address);
- else
- tmpaddr = g_strdup_printf ("[0x%05x]", iloffset);
-
- fname = mono_method_full_name (ji->method, TRUE);
-
- if (source_location)
- *trace = g_strdup_printf ("in %s (at %s) %s", tmpaddr, source_location, fname);
- else
- *trace = g_strdup_printf ("in %s %s", tmpaddr, fname);
-
- g_free (fname);
- g_free (source_location);
- g_free (tmpaddr);
- }
-
/*
* Some managed methods like pinvoke wrappers might have save_lmf set.
* In this case, register save/restore code is not generated by the
new_ctx->SC_EIP = *((int *)ctx->SC_EBP + 1) - 1;
new_ctx->SC_EBP = *((int *)ctx->SC_EBP);
- *res = *ji;
- return res;
-#ifdef MONO_USE_EXC_TABLES
- } else if ((ji = x86_unwind_native_frame (domain, jit_tls, ctx, new_ctx, *lmf, trace))) {
- *res = *ji;
- return res;
-#endif
+ /* 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;
+ }
+
+ return ji;
} else if (*lmf) {
*new_ctx = *ctx;
return (gpointer)-1;
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
- *res = *ji;
} else {
memset (res, 0, sizeof (MonoJitInfo));
res->method = (*lmf)->method;
}
- if (trace)
- *trace = g_strdup_printf ("in (unmanaged) %s", mono_method_full_name (res->method, TRUE));
-
new_ctx->SC_ESI = (*lmf)->esi;
new_ctx->SC_EDI = (*lmf)->edi;
new_ctx->SC_EBX = (*lmf)->ebx;
*lmf = (*lmf)->previous_lmf;
- return res;
-
+ return ji ? ji : res;
}
return NULL;