Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs3
-rw-r--r--mcs/class/Mono.Debugger.Soft/Test/dtest.cs4
-rw-r--r--mono/mini/debugger-agent.c52
-rw-r--r--mono/mini/debugger-agent.h4
-rw-r--r--mono/mini/interp/interp-stubs.c16
-rw-r--r--mono/mini/interp/interp.c98
-rw-r--r--mono/mini/interp/interp.h8
-rw-r--r--mono/mini/interp/transform.c9
-rw-r--r--mono/mini/mini-exceptions.c107
9 files changed, 214 insertions, 87 deletions
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
index d2b408a68ed..82efc79e51d 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
@@ -343,7 +343,8 @@ public class Tests : TestsBase, ITest2
gc_suspend ();
set_ip ();
step_filters ();
- local_reflect ();
+ if (args.Length > 0 && args [0] == "local-reflect")
+ local_reflect ();
if (args.Length > 0 && args [0] == "domain-test")
/* This takes a lot of time, so execute it conditionally */
domains ();
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
index b9cc720155d..ccd3b6b7602 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
@@ -560,6 +560,10 @@ public class DebuggerTests
[Test]
public void ClassLocalReflection () {
+ vm.Detach ();
+
+ Start (new string [] { "dtest-app.exe", "local-reflect" });
+
MethodMirror m = entry_point.DeclaringType.Assembly.GetType ("LocalReflectClass").GetMethod ("RunMe");
Assert.IsNotNull (m);
diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c
index 71a050b0703..eb02291e5df 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -239,11 +239,8 @@ typedef struct {
*/
InvokeData *invoke;
- /*
- * The context where single stepping should resume while the thread is suspended because
- * of an EXCEPTION event.
- */
- MonoThreadUnwindState catch_state;
+ StackFrameInfo catch_frame;
+ gboolean has_catch_frame;
/*
* The context which needs to be restored after handling a single step/breakpoint
@@ -3239,8 +3236,10 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls)
*
* First we add all the frames from inside the filter; 'tls->ctx' has the current context.
*/
- if (tls->context.valid)
+ if (tls->context.valid) {
mono_walk_stack_with_state (process_filter_frame, &tls->context, opts, &user_data);
+ DEBUG_PRINTF (1, "\tFrame: <call filter>\n");
+ }
/*
* After that, we resume unwinding from the location where the exception has been thrown.
*/
@@ -5843,23 +5842,14 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte
ss_req->start_sp = ss_req->last_sp = MONO_CONTEXT_GET_SP (&tls->context.ctx);
- if (tls->catch_state.valid) {
- gboolean res;
+ if (tls->has_catch_frame) {
StackFrameInfo frame;
- MonoContext new_ctx;
- MonoLMF *lmf = NULL;
/*
* We are stopped at a throw site. Stepping should go to the catch site.
*/
-
- /* Find the the jit info for the catch context */
- res = mono_find_jit_info_ext (
- (MonoDomain *)tls->catch_state.unwind_data [MONO_UNWIND_DATA_DOMAIN],
- (MonoJitTlsData *)((MonoThreadInfo*)thread->thread_info)->jit_data,
- NULL, &tls->catch_state.ctx, &new_ctx, NULL, &lmf, NULL, &frame);
- g_assert (res);
- g_assert (frame.type == FRAME_TYPE_MANAGED);
+ frame = tls->catch_frame;
+ g_assert (frame.type == FRAME_TYPE_MANAGED || frame.type == FRAME_TYPE_INTERP);
/*
* Find the seq point corresponding to the landing site ip, which is the first seq
@@ -6028,8 +6018,8 @@ mono_debugger_agent_unhandled_exception (MonoException *exc)
#endif
void
-mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx,
- MonoContext *catch_ctx)
+mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx,
+ MonoContext *catch_ctx, StackFrameInfo *catch_frame)
{
int i, j, suspend_policy;
GSList *events;
@@ -6096,8 +6086,8 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx
return;
ji = mini_jit_info_table_find (mono_domain_get (), (char *)MONO_CONTEXT_GET_IP (throw_ctx), NULL);
- if (catch_ctx)
- catch_ji = mini_jit_info_table_find (mono_domain_get (), (char *)MONO_CONTEXT_GET_IP (catch_ctx), NULL);
+ if (catch_frame)
+ catch_ji = catch_frame->ji;
else
catch_ji = NULL;
@@ -6135,16 +6125,18 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx
mono_loader_unlock ();
if (tls && ei.caught && catch_ctx) {
- memset (&tls->catch_state, 0, sizeof (tls->catch_state));
- tls->catch_state.ctx = *catch_ctx;
- tls->catch_state.unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
- tls->catch_state.valid = TRUE;
+ if (catch_frame) {
+ tls->has_catch_frame = TRUE;
+ tls->catch_frame = *catch_frame;
+ } else {
+ memset (&tls->catch_frame, 0, sizeof (tls->catch_frame));
+ }
}
process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, suspend_policy);
if (tls)
- tls->catch_state.valid = FALSE;
+ tls->has_catch_frame = FALSE;
}
void
@@ -9566,7 +9558,7 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
if (tls->frames [0]->ji->is_interp) {
MonoJitTlsData *jit_data = ((MonoThreadInfo*)thread->thread_info)->jit_data;
- mono_interp_set_resume_state (jit_data, NULL, tls->frames [0]->interp_frame, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
+ mono_interp_set_resume_state (jit_data, NULL, NULL, tls->frames [0]->interp_frame, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
} else {
MONO_CONTEXT_SET_IP (&tls->restore_state.ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
}
@@ -10586,8 +10578,8 @@ mono_debugger_agent_free_domain_info (MonoDomain *domain)
}
void
-mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *throw_ctx,
- MonoContext *catch_ctx)
+mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx,
+ MonoContext *catch_ctx, StackFrameInfo *catch_frame)
{
}
diff --git a/mono/mini/debugger-agent.h b/mono/mini/debugger-agent.h
index 3267f82740e..1ff9de11db4 100644
--- a/mono/mini/debugger-agent.h
+++ b/mono/mini/debugger-agent.h
@@ -6,6 +6,7 @@
#define __MONO_DEBUGGER_AGENT_H__
#include "mini.h"
+#include <mono/utils/mono-stack-unwinding.h>
MONO_API void
mono_debugger_agent_parse_options (char *options);
@@ -34,7 +35,8 @@ mono_debugger_agent_unhandled_exception (MonoException *exc);
#endif
void
-mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *throw_ctx, MonoContext *catch_ctx);
+mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx,
+ MonoContext *catch_ctx, StackFrameInfo *catch_frame);
void
mono_debugger_agent_begin_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx);
diff --git a/mono/mini/interp/interp-stubs.c b/mono/mini/interp/interp-stubs.c
index 176e45b6080..294e6e55311 100644
--- a/mono/mini/interp/interp-stubs.c
+++ b/mono/mini/interp/interp-stubs.c
@@ -59,6 +59,13 @@ mono_interp_frame_get_this (MonoInterpFrameHandle frame)
return NULL;
}
+MonoInterpFrameHandle
+mono_interp_frame_get_parent (MonoInterpFrameHandle frame)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
void
mono_interp_start_single_stepping (void)
{
@@ -70,7 +77,7 @@ mono_interp_stop_single_stepping (void)
}
void
-mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoJitExceptionInfo *ei, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
{
g_assert_not_reached ();
}
@@ -81,6 +88,13 @@ mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handl
g_assert_not_reached ();
}
+gboolean
+mono_interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, gpointer handler_ip)
+{
+ g_assert_not_reached ();
+ return FALSE;
+}
+
void
mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
{
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index 627480c44ac..5ca1ea7f18b 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -109,7 +109,8 @@ static gboolean ss_enabled;
static char* dump_frame (InterpFrame *inv);
static MonoArray *get_trace_ips (MonoDomain *domain, InterpFrame *top);
-static void ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception, int exit_at_finally);
+static void interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *start_with_ip, MonoException *filter_exception, int exit_at_finally, InterpFrame *base_frame);
+static void interp_exec_method (InterpFrame *frame, ThreadContext *context);
typedef void (*ICallMethod) (InterpFrame *frame);
@@ -1252,7 +1253,7 @@ get_trace_ips (MonoDomain *domain, InterpFrame *top)
if (inv->imethod != NULL)
++i;
- res = mono_array_new_checked (domain, mono_defaults.int_class, 2 * i, &error);
+ res = mono_array_new_checked (domain, mono_defaults.int_class, 3 * i, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
for (i = 0, inv = top; inv; inv = inv->parent)
@@ -1261,6 +1262,8 @@ get_trace_ips (MonoDomain *domain, InterpFrame *top)
++i;
mono_array_set (res, gpointer, i, (gpointer)inv->ip);
++i;
+ mono_array_set (res, gpointer, i, NULL);
+ ++i;
}
return res;
@@ -1393,7 +1396,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
if (exc)
frame.invoke_trap = 1;
- ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
+ interp_exec_method (&frame, context);
if (context == &context_struct)
set_context (NULL);
@@ -1537,7 +1540,7 @@ interp_entry (InterpEntryData *data)
break;
}
- ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
+ interp_exec_method (&frame, context);
if (context == &context_struct)
set_context (NULL);
else
@@ -2185,9 +2188,10 @@ static int opcode_counts[512];
/*
* If EXIT_AT_FINALLY is not -1, exit after exiting the finally clause with that index.
+ * If BASE_FRAME is not NULL, copy arguments/locals from BASE_FRAME.
*/
static void
-ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception, int exit_at_finally)
+interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *start_with_ip, MonoException *filter_exception, int exit_at_finally, InterpFrame *base_frame)
{
InterpFrame child_frame;
GSList *finally_ips = NULL;
@@ -2239,13 +2243,17 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
}
rtm = frame->imethod;
- if (!start_with_ip ) {
+ if (!start_with_ip) {
frame->args = alloca (rtm->alloca_size);
memset (frame->args, 0, rtm->alloca_size);
ip = rtm->code;
} else {
ip = start_with_ip;
+ if (base_frame) {
+ frame->args = alloca (rtm->alloca_size);
+ memcpy (frame->args, base_frame->args, rtm->alloca_size);
+ }
}
sp = frame->stack = (stackval *) ((char *) frame->args + rtm->args_size);
vt_sp = (unsigned char *) sp + rtm->stack_size;
@@ -2444,7 +2452,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
}
}
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -2536,7 +2544,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
--sp;
child_frame.stack_args = sp;
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -2578,7 +2586,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
}
child_frame.stack_args = sp;
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -2651,7 +2659,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
sp [0].data.p = unboxed;
}
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -2705,7 +2713,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
sp [0].data.p = unboxed;
}
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -3523,7 +3531,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
g_assert (csig->call_convention == MONO_CALL_DEFAULT);
- ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
+ interp_exec_method (&child_frame, context);
context->current_frame = frame;
@@ -4410,7 +4418,6 @@ array_constructed:
frame->ip = ip;
if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
- MonoException *exc = frame->ex;
frame->ex_handler = NULL;
frame->ex = NULL;
if (frame->imethod->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) {
@@ -4991,7 +4998,7 @@ array_constructed:
stackval retval;
memcpy (&dup_frame, inv, sizeof (InterpFrame));
dup_frame.retval = &retval;
- ves_exec_method_with_context (&dup_frame, context, inv->imethod->code + clause->data.filter_offset, frame->ex, -1);
+ interp_exec_method_full (&dup_frame, context, inv->imethod->code + clause->data.filter_offset, frame->ex, -1, NULL);
if (dup_frame.retval->data.i) {
#if DEBUG_INTERP
if (tracing)
@@ -5159,6 +5166,9 @@ check_lmf:
exit_frame:
+ if (base_frame)
+ memcpy (base_frame->args, frame->args, rtm->alloca_size);
+
if (!frame->ex && MONO_PROFILER_ENABLED (method_leave) &&
frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE) {
MonoProfilerCallContext *prof_ctx = NULL;
@@ -5191,6 +5201,12 @@ exit_frame:
DEBUG_LEAVE ();
}
+static void
+interp_exec_method (InterpFrame *frame, ThreadContext *context)
+{
+ interp_exec_method_full (frame, context, NULL, NULL, -1, NULL);
+}
+
void
mono_interp_parse_options (const char *options)
{
@@ -5385,7 +5401,7 @@ mono_interp_regression_list (int verbose, int count, char *images [])
* Set the state the interpeter will continue to execute from after execution returns to the interpreter.
*/
void
-mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoJitExceptionInfo *ei, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
{
ThreadContext *context;
@@ -5397,6 +5413,9 @@ mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoIn
context->handler_frame = interp_frame;
/* This is on the stack, so it doesn't need a wbarrier */
context->handler_frame->ex = ex;
+ /* Ditto */
+ if (ei)
+ *(MonoException**)(context->handler_frame->locals + ei->exvar_offset) = ex;
context->handler_ip = handler_ip;
}
@@ -5409,10 +5428,38 @@ mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoIn
void
mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
{
- InterpFrame *iframe = frame->interp_frame;
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
+ InterpFrame *iframe = frame->interp_frame;
+ ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- ves_exec_method_with_context (iframe, context, handler_ip, NULL, clause_index);
+ interp_exec_method_full (iframe, context, handler_ip, NULL, clause_index, NULL);
+}
+
+/*
+ * mono_interp_run_filter:
+ *
+ * Run the filter clause identified by CLAUSE_INDEX in the intepreter frame given by
+ * frame->interp_frame.
+ */
+gboolean
+mono_interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, gpointer handler_ip)
+{
+ InterpFrame *iframe = frame->interp_frame;
+ ThreadContext *context = mono_native_tls_get_value (thread_context_id);
+ InterpFrame child_frame;
+ stackval retval;
+
+ /*
+ * Have to run the clause in a new frame which is a copy of IFRAME, since
+ * during debugging, there are two copies of the frame on the stack.
+ */
+ memset (&child_frame, 0, sizeof (InterpFrame));
+ child_frame.imethod = iframe->imethod;
+ child_frame.retval = &retval;
+ child_frame.parent = iframe;
+
+ interp_exec_method_full (&child_frame, context, handler_ip, ex, clause_index, iframe);
+ /* ENDFILTER stores the result into child_frame->retval */
+ return child_frame.retval->data.i ? TRUE : FALSE;
}
typedef struct {
@@ -5432,6 +5479,11 @@ mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_dat
stack_iter->current = (InterpFrame*)interp_exit_data;
}
+/*
+ * mono_interp_frame_iter_next:
+ *
+ * Fill out FRAME with date for the next interpreter frame.
+ */
gboolean
mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
{
@@ -5440,7 +5492,7 @@ mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
memset (frame, 0, sizeof (StackFrameInfo));
/* pinvoke frames doesn't have imethod set */
- while (iframe && !(iframe->imethod && iframe->imethod->code))
+ while (iframe && !(iframe->imethod && iframe->imethod->code && iframe->imethod->jinfo))
iframe = iframe->parent;
if (!iframe)
return FALSE;
@@ -5541,6 +5593,14 @@ mono_interp_frame_get_this (MonoInterpFrameHandle frame)
return iframe->args + arg_offset;
}
+MonoInterpFrameHandle
+mono_interp_frame_get_parent (MonoInterpFrameHandle frame)
+{
+ InterpFrame *iframe = (InterpFrame*)frame;
+
+ return iframe->parent;
+}
+
void
mono_interp_start_single_stepping (void)
{
diff --git a/mono/mini/interp/interp.h b/mono/mini/interp/interp.h
index 8415c6f43fe..ad2ddc9703c 100644
--- a/mono/mini/interp/interp.h
+++ b/mono/mini/interp/interp.h
@@ -66,11 +66,14 @@ void
interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data);
void
-mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip);
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoJitExceptionInfo *ei, MonoInterpFrameHandle interp_frame, gpointer handler_ip);
void
mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip);
+gboolean
+mono_interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, gpointer handler_ip);
+
void
mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data);
@@ -101,6 +104,9 @@ mono_interp_frame_get_local (MonoInterpFrameHandle frame, int pos);
gpointer
mono_interp_frame_get_this (MonoInterpFrameHandle frame);
+MonoInterpFrameHandle
+mono_interp_frame_get_parent (MonoInterpFrameHandle frame);
+
void
mono_interp_start_single_stepping (void);
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index a3d0e60df75..5605a196b72 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -1656,6 +1656,15 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig
mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
}
g_free (sps);
+
+ MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
+ if (asyncMethod) {
+ for (i = 0; asyncMethod != NULL && i < asyncMethod->num_awaits; i++) {
+ mono_bitset_set_fast (seq_point_locs, asyncMethod->resume_offsets [i]);
+ mono_bitset_set_fast (seq_point_locs, asyncMethod->yield_offsets [i]);
+ }
+ mono_debug_free_method_async_debug_info (asyncMethod);
+ }
} else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
/* Methods without line number info like auto-generated property accessors */
seq_point_locs = mono_bitset_new (header->code_size, 0);
diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c
index 10fe33c2a2c..42a43d48ce7 100644
--- a/mono/mini/mini-exceptions.c
+++ b/mono/mini/mini-exceptions.c
@@ -98,6 +98,8 @@ typedef struct
{
gpointer ip;
gpointer generic_info;
+ /* Only for interpreter frames */
+ MonoJitInfo *ji;
} ExceptionTraceIp;
/* Number of words in trace_ips belonging to one entry */
@@ -701,10 +703,30 @@ unwinder_unwind_frame (Unwinder *unwinder,
StackFrameInfo *frame)
{
if (unwinder->in_interp) {
+ gpointer parent;
+ memcpy (new_ctx, ctx, sizeof (MonoContext));
+
+ /* Process debugger invokes */
+ /* The DEBUGGER_INVOKE should be returned before the first interpreter frame for the invoke */
+ if ((gpointer)MONO_CONTEXT_GET_SP (ctx) > (gpointer)(*lmf)) {
+ if (((guint64)(*lmf)->previous_lmf) & 2) {
+ MonoLMFExt *ext = (MonoLMFExt*)(*lmf);
+ if (ext->debugger_invoke) {
+ *lmf = (MonoLMF *)(((guint64)(*lmf)->previous_lmf) & ~7);
+ frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
+ return TRUE;
+ }
+ }
+ }
+
unwinder->in_interp = mono_interp_frame_iter_next (&unwinder->interp_iter, frame);
- if (!unwinder->in_interp) {
- return unwinder_unwind_frame (unwinder, domain, jit_tls, prev_ji, ctx, new_ctx, trace, lmf, save_locations, frame);
+ if (frame->type == FRAME_TYPE_INTERP) {
+ parent = mono_interp_frame_get_parent (frame->interp_frame);
+ /* This is needed so code which uses ctx->sp for frame ordering would work */
+ MONO_CONTEXT_SET_SP (new_ctx, parent);
}
+ if (!unwinder->in_interp)
+ return unwinder_unwind_frame (unwinder, domain, jit_tls, prev_ji, ctx, new_ctx, trace, lmf, save_locations, frame);
return TRUE;
} else {
gboolean res = mono_find_jit_info_ext (domain, jit_tls, prev_ji, ctx, new_ctx, trace, lmf,
@@ -929,16 +951,20 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
gpointer generic_info = trace_ip.generic_info;
MonoMethod *method;
- ji = mono_jit_info_table_find (domain, (char *)ip);
- if (ji == NULL) {
- /* Unmanaged frame */
- mono_array_setref (res, i, sf);
- continue;
+ if (trace_ip.ji) {
+ ji = trace_ip.ji;
+ } else {
+ ji = mono_jit_info_table_find (domain, (char *)ip);
+ if (ji == NULL) {
+ /* Unmanaged frame */
+ mono_array_setref (res, i, sf);
+ continue;
+ }
}
g_assert (ji != NULL);
- if (mono_llvm_only)
+ if (mono_llvm_only || !generic_info)
/* Can't resolve actual method */
method = jinfo_get_method (ji);
else
@@ -1581,14 +1607,14 @@ setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, GList **trac
}
/*
- * mono_handle_exception_internal_first_pass:
+ * handle_exception_first_pass:
*
* The first pass of exception handling. Unwind the stack until a catch clause which can catch
- * OBJ is found. Run the index of the filter clause which caught the exception into
+ * OBJ is found. Store the index of the filter clause which caught the exception into
* OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
*/
static gboolean
-mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
+handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception, StackFrameInfo *catch_frame)
{
MonoError error;
MonoDomain *domain = mono_domain_get ();
@@ -1704,8 +1730,9 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
// avoid giant stack traces during a stack overflow
if (frame_count < 1000) {
- trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
+ trace_ips = g_list_prepend (trace_ips, ip);
trace_ips = g_list_prepend (trace_ips, get_generic_info_from_stack_frame (ji, ctx));
+ trace_ips = g_list_prepend (trace_ips, ji);
}
}
@@ -1747,33 +1774,39 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
mono_atomic_inc_i32 (&mono_perfcounters->exceptions_filters);
#endif
+ if (!ji->is_interp) {
#ifndef MONO_CROSS_COMPILE
#ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
- if (ji->from_llvm)
- MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
- else
- /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
- *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
+ if (ji->from_llvm)
+ MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
+ else
+ /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
+ *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
#else
- g_assert (!ji->from_llvm);
- /* store the exception object in bp + ei->exvar_offset */
- *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
+ g_assert (!ji->from_llvm);
+ /* store the exception object in bp + ei->exvar_offset */
+ *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
#endif
#endif
#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
- /*
- * Pass the original il clause index to the landing pad so it can
- * branch to the landing pad associated with the il clause.
- * This is needed because llvm compiled code assumes that the EH
- * code always branches to the innermost landing pad.
- */
- if (ji->from_llvm)
- MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
+ /*
+ * Pass the original il clause index to the landing pad so it can
+ * branch to the landing pad associated with the il clause.
+ * This is needed because llvm compiled code assumes that the EH
+ * code always branches to the innermost landing pad.
+ */
+ if (ji->from_llvm)
+ MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
#endif
+ }
mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
- filtered = call_filter (ctx, ei->data.filter);
+ if (ji->is_interp) {
+ filtered = mono_interp_run_filter (&frame, (MonoException*)ex_obj, i, ei->data.filter);
+ } else {
+ filtered = call_filter (ctx, ei->data.filter);
+ }
mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
if (filtered && out_filter_idx)
*out_filter_idx = filter_idx;
@@ -1787,6 +1820,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
/* mono_debugger_agent_handle_exception () needs this */
mini_set_abort_threshold (ctx);
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
+ frame.native_offset = (char*)ei->handler_start - (char*)ji->code_start;
+ *catch_frame = frame;
return TRUE;
}
}
@@ -1803,6 +1838,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
/* mono_debugger_agent_handle_exception () needs this */
if (!in_interp)
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
+ frame.native_offset = (char*)ei->handler_start - (char*)ji->code_start;
+ *catch_frame = frame;
return TRUE;
}
mono_error_cleanup (&isinst_error);
@@ -1969,12 +2006,13 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
MONO_PROFILER_RAISE (exception_throw, (obj));
jit_tls->orig_ex_ctx_set = FALSE;
- res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
+ StackFrameInfo catch_frame;
+ res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame);
if (!res) {
if (mini_get_debug_options ()->break_on_exc)
G_BREAKPOINT ();
- mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
+ mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL, NULL);
if (mini_get_debug_options ()->suspend_on_unhandled) {
mono_runtime_printf_err ("Unhandled exception, suspending...");
@@ -2002,9 +2040,9 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
}
if (unhandled)
- mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
+ mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL, NULL);
else
- mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, &ctx_cp);
+ mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, &ctx_cp, &catch_frame);
}
}
@@ -2179,7 +2217,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
* like the call which transitioned to JITted code has succeeded, but the
* return value register etc. is not set, so we have to be careful.
*/
- mono_interp_set_resume_state (jit_tls, mono_ex, frame.interp_frame, ei->handler_start);
+ mono_interp_set_resume_state (jit_tls, mono_ex, ei, frame.interp_frame, ei->handler_start);
/* Undo the IP adjustment done by mono_arch_unwind_frame () */
#if defined(TARGET_AMD64)
ctx->gregs [AMD64_RIP] ++;
@@ -3234,6 +3272,7 @@ throw_exception (MonoObject *ex, gboolean rethrow)
for (l = ips; l; l = l->next) {
trace = g_list_append (trace, l->data);
trace = g_list_append (trace, NULL);
+ trace = g_list_append (trace, NULL);
}
MonoArray *ips_arr = mono_glist_to_array (trace, mono_defaults.int_class, &error);
mono_error_assert_ok (&error);