/*
- * exception.c: exception support
+ * exceptions-x86.c: exception support for x86
*
* Authors:
* Dietmar Maurer (dietmar@ximian.com)
/* adjust eip so that it point into the call instruction */
eip -= 1;
- ctx.SC_ESP = esp;
+ /* Pop argument and return address */
+ ctx.SC_ESP = esp + (2 * sizeof (gpointer));
ctx.SC_EIP = eip;
ctx.SC_EBP = ebp;
ctx.SC_EDI = edi;
*new_ctx = *ctx;
- if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
- /* remove any unused lmf */
- *lmf = (*lmf)->previous_lmf;
- }
-
address = (char *)ip - (char *)ji->code_start;
if (native_offset)
g_free (source_location);
g_free (tmpaddr);
}
-
- offset = -1;
- /* restore caller saved registers */
- if (ji->used_regs & X86_EBX_MASK) {
- new_ctx->SC_EBX = *((int *)ctx->SC_EBP + offset);
- offset--;
+
+ /*
+ * Some managed methods like pinvoke wrappers might have save_lmf set.
+ * In this case, register save/restore code is not generated by the
+ * JIT, so we have to restore callee saved registers from the lmf.
+ */
+ if (ji->method->save_lmf) {
+ /*
+ * We only need to do this if the exception was raised in managed
+ * 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;
+ }
}
- if (ji->used_regs & X86_EDI_MASK) {
- new_ctx->SC_EDI = *((int *)ctx->SC_EBP + offset);
- offset--;
+ else {
+ offset = -1;
+ /* restore caller saved registers */
+ if (ji->used_regs & X86_EBX_MASK) {
+ new_ctx->SC_EBX = *((int *)ctx->SC_EBP + offset);
+ offset--;
+ }
+ if (ji->used_regs & X86_EDI_MASK) {
+ new_ctx->SC_EDI = *((int *)ctx->SC_EBP + offset);
+ offset--;
+ }
+ if (ji->used_regs & X86_ESI_MASK) {
+ new_ctx->SC_ESI = *((int *)ctx->SC_EBP + offset);
+ }
}
- if (ji->used_regs & X86_ESI_MASK) {
- new_ctx->SC_ESI = *((int *)ctx->SC_EBP + offset);
+
+ if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+ /* remove any unused lmf */
+ *lmf = (*lmf)->previous_lmf;
}
- new_ctx->SC_ESP = ctx->SC_EBP;
+ /* Pop EBP and the return address */
+ new_ctx->SC_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);
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
MonoLMF *lmf = jit_tls->lmf;
GList *trace_ips = NULL;
+ MonoException *mono_ex;
g_assert (ctx != NULL);
if (!obj) {
obj = (MonoObject *)ex;
}
- g_assert (mono_object_isinst (obj, mono_defaults.exception_class));
+ if (mono_object_isinst (obj, mono_defaults.exception_class)) {
+ mono_ex = (MonoException*)obj;
+ mono_ex->stack_trace = NULL;
+ } else {
+ mono_ex = NULL;
+ }
if (!call_filter)
call_filter = arch_get_call_filter ();
if (!test_only) {
MonoContext ctx_cp = *ctx;
- if (mono_jit_trace_calls)
+ if (mono_jit_trace_calls != NULL)
g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) {
if (mono_break_on_exc)
if (ji != (gpointer)-1) {
- if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) {
+ if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
char *tmp, *strace;
trace_ips = g_list_append (trace_ips, MONO_CONTEXT_GET_IP (ctx));
- if (!((MonoException*)obj)->stack_trace)
+ if (!mono_ex->stack_trace)
strace = g_strdup ("");
else
- strace = mono_string_to_utf8 (((MonoException*)obj)->stack_trace);
+ strace = mono_string_to_utf8 (mono_ex->stack_trace);
tmp = g_strdup_printf ("%s%s\n", strace, trace);
g_free (strace);
- ((MonoException*)obj)->stack_trace = mono_string_new (domain, tmp);
+ mono_ex->stack_trace = mono_string_new (domain, tmp);
g_free (tmp);
}
((ei->flags == MONO_EXCEPTION_CLAUSE_FILTER &&
call_filter (ctx, ei->data.filter)))) {
if (test_only) {
- ((MonoException*)obj)->trace_ips = glist_to_array (trace_ips);
+ if (mono_ex)
+ mono_ex->trace_ips = glist_to_array (trace_ips);
g_list_free (trace_ips);
g_free (trace);
return TRUE;
}
- if (mono_jit_trace_calls)
+ if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method))
g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
jit_tls->lmf = lmf;
if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
(ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
- if (mono_jit_trace_calls)
+ if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method))
g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
call_filter (ctx, ei->handler_start);
}
jit_tls->abort_func (obj);
g_assert_not_reached ();
} else {
- ((MonoException*)obj)->trace_ips = glist_to_array (trace_ips);
+ if (mono_ex)
+ mono_ex->trace_ips = glist_to_array (trace_ips);
g_list_free (trace_ips);
return FALSE;
}