diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 4c14f2a195c00..7a918ea3e1660 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,25 @@ +2009-06-08 Martin Baulig + + * debug-mini.c + (MonoDebuggerExceptionAction): Moved into debug-mini.h. + (_mono_debugger_throw_exception): Don't make this static. + (_mono_debugger_unhandled_exception): Likewise. + (mono_debugger_handle_exception): Moved to mini-exceptions.c + + * debug-mini.c + (MonoDebuggerExceptionAction): Moved here from debug-mini.c. + (_mono_debugger_throw_exception): Add function prototype. + (_mono_debugger_unhandled_exception): Likewise. + + * mini-exceptions.c + (mono_handle_exception_internal): Added `MonoJitInfo **out_ji' + arg; return the first exception handler if the exception is caught + and we're running inside the debugger. + (mono_debugger_handle_exception): Moved here from debug-mini.c; + improve exception handle inside runtime-invoke, check whether the + exception is actually caught in the method being invoked and not + by the runtime-invoke-wrapper. + 2009-05-26 Zoltan Varga * mini-sparc.c (add_outarg_load): Fix the sparc build. @@ -56,6 +78,28 @@ * aot-compiler.c (add_wrappers): Add remoting-invoke-with-check wrappers for virtual methods too. +2009-06-08 Martin Baulig + + * debug-mini.c + (MonoDebuggerExceptionAction): Moved into debug-mini.h. + (_mono_debugger_throw_exception): Don't make this static. + (_mono_debugger_unhandled_exception): Likewise. + (mono_debugger_handle_exception): Moved to mini-exceptions.c + + * debug-mini.c + (MonoDebuggerExceptionAction): Moved here from debug-mini.c. + (_mono_debugger_throw_exception): Add function prototype. + (_mono_debugger_unhandled_exception): Likewise. + + * mini-exceptions.c + (mono_handle_exception_internal): Added `MonoJitInfo **out_ji' + arg; return the first exception handler if the exception is caught + and we're running inside the debugger. + (mono_debugger_handle_exception): Moved here from debug-mini.c; + improve exception handle inside runtime-invoke, check whether the + exception is actually caught in the method being invoked and not + by the runtime-invoke-wrapper. + 2009-05-06 Zoltan Varga Backport of r133651. diff --git a/mono/mini/debug-mini.c b/mono/mini/debug-mini.c index 796a70106cff7..46fe06e85383b 100644 --- a/mono/mini/debug-mini.c +++ b/mono/mini/debug-mini.c @@ -81,12 +81,6 @@ typedef struct { guint32 stop_unhandled; } MonoDebuggerExceptionInfo; -typedef enum { - MONO_DEBUGGER_EXCEPTION_ACTION_NONE = 0, - MONO_DEBUGGER_EXCEPTION_ACTION_STOP = 1, - MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED = 2 -} MonoDebuggerExceptionAction; - MonoDebuggerThreadInfo *mono_debugger_thread_table = NULL; static inline void @@ -887,7 +881,7 @@ find_debugger_thread_info (MonoThread *thread) } #endif -static MonoDebuggerExceptionAction +MonoDebuggerExceptionAction _mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc) { #ifdef MONO_DEBUGGER_SUPPORTED @@ -952,7 +946,7 @@ _mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc) return MONO_DEBUGGER_EXCEPTION_ACTION_NONE; } -static gboolean +gboolean _mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc) { #ifdef MONO_DEBUGGER_SUPPORTED @@ -1036,61 +1030,6 @@ mono_debugger_call_exception_handler (gpointer addr, gpointer stack, MonoObject #endif } -/* - * mono_debugger_handle_exception: - * - * Notify the debugger about exceptions. Returns TRUE if the debugger wants us to stop - * at the exception and FALSE to resume with the normal exception handling. - * - * The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and - * MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the - * `callq throw' instruction. - */ -gboolean -mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj) -{ - MonoDebuggerExceptionAction action; - - if (!mono_debug_using_mono_debugger ()) - return FALSE; - - if (!obj) { - MonoException *ex = mono_get_exception_null_reference (); - MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object")); - obj = (MonoObject *)ex; - } - - action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj); - - if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) { - /* - * The debugger wants us to stop on the `throw' instruction. - * By the time we get here, it already inserted a breakpoint there. - */ - return TRUE; - } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) { - MonoContext ctx_cp = *ctx; - - /* - * The debugger wants us to stop only if this exception is user-unhandled. - */ - - if (!mono_handle_exception (&ctx_cp, obj, MONO_CONTEXT_GET_IP (ctx), TRUE)) { - /* - * The exception is user-unhandled - tell the debugger to stop. - */ - return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj); - } - - /* - * The exception is catched somewhere - resume with the normal exception handling and don't - * stop in the debugger. - */ - } - - return FALSE; -} - #ifdef MONO_DEBUGGER_SUPPORTED static gchar * diff --git a/mono/mini/debug-mini.h b/mono/mini/debug-mini.h index 975df604bdea2..73f98c760ed20 100644 --- a/mono/mini/debug-mini.h +++ b/mono/mini/debug-mini.h @@ -30,6 +30,22 @@ mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj); MonoObject * mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc); +/* + * Internal exception API. + */ + +typedef enum { + MONO_DEBUGGER_EXCEPTION_ACTION_NONE = 0, + MONO_DEBUGGER_EXCEPTION_ACTION_STOP = 1, + MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED = 2 +} MonoDebuggerExceptionAction; + +MonoDebuggerExceptionAction +_mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc); + +gboolean +_mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc); + /* * This is the old breakpoint interface. * It isn't used by the debugger anymore, but still when using the `--break' command diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 09cf8cd178e58..dee9316783f95 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -850,7 +850,7 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex * the first filter clause which caught the exception. */ static gboolean -mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer original_ip, gboolean test_only, gint32 *out_filter_idx) +mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer original_ip, gboolean test_only, gint32 *out_filter_idx, MonoJitInfo **out_ji) { MonoDomain *domain = mono_domain_get (); MonoJitInfo *ji, rji; @@ -919,7 +919,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina if (mono_trace_is_enabled ()) g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name); mono_profiler_exception_thrown (obj); - if (!mono_handle_exception_internal (&ctx_cp, obj, original_ip, TRUE, &first_filter_idx)) { + if (!mono_handle_exception_internal (&ctx_cp, obj, original_ip, TRUE, &first_filter_idx, out_ji)) { if (mono_break_on_exc) G_BREAKPOINT (); // FIXME: This runs managed code so it might cause another stack overflow when @@ -930,6 +930,8 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina if (out_filter_idx) *out_filter_idx = -1; + if (out_ji) + *out_ji = NULL; filter_idx = 0; initial_ctx = *ctx; memset (&rji, 0, sizeof (rji)); @@ -1014,12 +1016,14 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina } if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { - // mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), obj); if (test_only) { mono_perfcounters->exceptions_filters++; + mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), obj); filtered = call_filter (ctx, ei->data.filter); if (filtered && out_filter_idx) *out_filter_idx = filter_idx; + if (out_ji) + *out_ji = ji; } else { /* @@ -1110,6 +1114,72 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina g_assert_not_reached (); } +/* + * mono_debugger_handle_exception: + * + * Notify the debugger about exceptions. Returns TRUE if the debugger wants us to stop + * at the exception and FALSE to resume with the normal exception handling. + * + * The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and + * MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the + * `callq throw' instruction. + */ +gboolean +mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj) +{ + MonoDebuggerExceptionAction action; + + if (!mono_debug_using_mono_debugger ()) + return FALSE; + + if (!obj) { + MonoException *ex = mono_get_exception_null_reference (); + MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object")); + obj = (MonoObject *)ex; + } + + action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj); + + if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) { + /* + * The debugger wants us to stop on the `throw' instruction. + * By the time we get here, it already inserted a breakpoint there. + */ + return TRUE; + } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) { + MonoContext ctx_cp = *ctx; + MonoJitInfo *ji = NULL; + gboolean ret; + + /* + * The debugger wants us to stop only if this exception is user-unhandled. + */ + + ret = mono_handle_exception_internal (&ctx_cp, obj, MONO_CONTEXT_GET_IP (ctx), TRUE, NULL, &ji); + if (ret && (ji != NULL) && (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) { + /* + * The exception is handled in a runtime-invoke wrapper, that means that it's unhandled + * inside the method being invoked, so we handle it like a user-unhandled exception. + */ + ret = FALSE; + } + + if (!ret) { + /* + * The exception is user-unhandled - tell the debugger to stop. + */ + return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj); + } + + /* + * The exception is catched somewhere - resume with the normal exception handling and don't + * stop in the debugger. + */ + } + + return FALSE; +} + /** * mono_debugger_run_finally: * @start_ctx: saved processor state @@ -1163,7 +1233,7 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo { if (!test_only) mono_perfcounters->exceptions_thrown++; - return mono_handle_exception_internal (ctx, obj, original_ip, test_only, NULL); + return mono_handle_exception_internal (ctx, obj, original_ip, test_only, NULL, NULL); } #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK