Mon Mar 8 17:58:26 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / debug-mini.c
index 83add8e2f80c93a0bc94ea7c5ac352d75aed100f..29131f9c3c6f8741a0a31ba2ce37bcf32921864e 100644 (file)
@@ -20,9 +20,7 @@
 #include <mono/metadata/mono-debug-debugger.h>
 #include "debug-mini.h"
 
-#ifdef HAVE_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
+#include <mono/utils/valgrind.h>
 
 #ifdef MONO_DEBUGGER_SUPPORTED
 #include <libgc/include/libgc-mono-debugger.h>
@@ -47,6 +45,18 @@ typedef struct {
        guint32 stopped_on_unhandled : 1;
 } MonoDebuggerExceptionState;
 
+typedef enum {
+       MONO_DEBUGGER_THREAD_FLAGS_NONE         = 0,
+       MONO_DEBUGGER_THREAD_FLAGS_INTERNAL     = 1,
+       MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL   = 2
+} MonoDebuggerThreadFlags;
+
+typedef enum {
+       MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_NONE                = 0,
+       MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE   = 1,
+       MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED     = 2
+} MonoDebuggerInternalThreadFlags;
+
 struct _MonoDebuggerThreadInfo {
        guint64 tid;
        guint64 lmf_addr;
@@ -65,13 +75,17 @@ struct _MonoDebuggerThreadInfo {
        guint32 stack_size;
        guint32 signal_stack_size;
 
-       MonoDebuggerExceptionState exception_state;
+       guint32 thread_flags;
 
        /*
         * The debugger doesn't access anything beyond this point.
         */
+       MonoDebuggerExceptionState exception_state;
+
+       guint32 internal_flags;
+
        MonoJitTlsData *jit_tls;
-       MonoThread *thread;
+       MonoInternalThread *thread;
 };
 
 typedef struct {
@@ -81,12 +95,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
@@ -128,7 +136,7 @@ mono_debug_open_method (MonoCompile *cfg)
 
        mono_class_init (cfg->method->klass);
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
        g_assert (header);
        
        info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
@@ -251,6 +259,7 @@ mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
 
        g_free (addresses);
        g_free (lines);
+       mono_metadata_free_mh (header);
 #endif /* VALGRIND_ADD_LINE_INFO */
 }
 
@@ -273,7 +282,7 @@ mono_debug_close_method (MonoCompile *cfg)
        }
 
        method = cfg->method;
-       header = mono_method_get_header (method);
+       header = cfg->header;
        sig = mono_method_signature (method);
 
        jit = info->jit;
@@ -304,7 +313,7 @@ mono_debug_close_method (MonoCompile *cfg)
        for (i = 0; i < jit->num_line_numbers; i++)
                jit->line_numbers [i] = g_array_index (info->line_numbers, MonoDebugLineNumberEntry, i);
 
-       debug_info = mono_debug_add_method (method, jit, cfg->domain);
+       debug_info = mono_debug_add_method (cfg->method_to_register, jit, cfg->domain);
 
        mono_debug_add_vg_method (method, jit);
 
@@ -326,7 +335,7 @@ mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address)
        if (!info || !info->jit || !ins->cil_code)
                return;
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
        g_assert (header);
 
        if ((ins->cil_code < header->code) ||
@@ -353,7 +362,7 @@ mono_debug_open_block (MonoCompile *cfg, MonoBasicBlock *bb, guint32 address)
        if (!info || !info->jit || !bb->cil_code)
                return;
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
        g_assert (header);
 
        if ((bb->cil_code < header->code) ||
@@ -581,6 +590,7 @@ deserialize_debug_info (MonoMethod *method, guint8 *code_start, guint8 *buf, gui
                prev_native_offset = native_offset;
        }
 
+       mono_metadata_free_mh (header);
        return jit;
 }
 
@@ -772,7 +782,7 @@ mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
 }
 
 void
-mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls)
+mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls, gpointer func)
 {
 #ifdef MONO_DEBUGGER_SUPPORTED
        size_t stsize = 0;
@@ -788,7 +798,7 @@ mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit
 
        info = g_new0 (MonoDebuggerThreadInfo, 1);
        info->tid = tid;
-       info->thread = thread;
+       info->thread = thread->internal_thread;
        info->stack_start = (guint64) (gsize) staddr;
        info->signal_stack_start = (guint64) (gsize) jit_tls->signal_stack;
        info->stack_size = stsize;
@@ -797,6 +807,11 @@ mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit
        info->lmf_addr = (guint64) (gsize) mono_get_lmf_addr ();
        info->jit_tls = jit_tls;
 
+       if (func)
+               info->thread_flags = MONO_DEBUGGER_THREAD_FLAGS_INTERNAL;
+       if (thread->internal_thread->threadpool_thread)
+               info->thread_flags |= MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL;
+
        info->next = mono_debugger_thread_table;
        mono_debugger_thread_table = info;
 
@@ -841,7 +856,7 @@ mono_debugger_extended_notification (MonoDebuggerEvent event, guint64 data, guin
 {
 #ifdef MONO_DEBUGGER_SUPPORTED
        MonoDebuggerThreadInfo **ptr;
-       MonoThread *thread = mono_thread_current ();
+       MonoInternalThread *thread = mono_thread_internal_current ();
 
        if (!mono_debug_using_mono_debugger ())
                return;
@@ -865,15 +880,25 @@ mono_debugger_extended_notification (MonoDebuggerEvent event, guint64 data, guin
 }
 
 void
-mono_debugger_trampoline_compiled (MonoMethod *method, const guint8 *code)
+mono_debugger_trampoline_compiled (const guint8 *trampoline, MonoMethod *method, const guint8 *code)
 {
-       mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_TRAMPOLINE,
+#ifdef MONO_DEBUGGER_SUPPORTED
+       struct {
+               const guint8 * trampoline;
+               MonoMethod *method;
+               const guint8 *code;
+       } info = { trampoline, method, code };
+
+       mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_OLD_TRAMPOLINE,
                                             (guint64) (gsize) method, (guint64) (gsize) code);
+       mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_TRAMPOLINE,
+                                            (guint64) (gsize) &info, 0);
+#endif
 }
 
 #if MONO_DEBUGGER_SUPPORTED
 static MonoDebuggerThreadInfo *
-find_debugger_thread_info (MonoThread *thread)
+find_debugger_thread_info (MonoInternalThread *thread)
 {
        MonoDebuggerThreadInfo **ptr;
 
@@ -888,7 +913,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
@@ -900,12 +925,17 @@ _mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
 
        mono_debugger_lock ();
 
-       thread_info = find_debugger_thread_info (mono_thread_current ());
+       thread_info = find_debugger_thread_info (mono_thread_internal_current ());
        if (!thread_info) {
                mono_debugger_unlock ();
                return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
        }
 
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+               mono_debugger_unlock ();
+               return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
+       }
+
        if (thread_info->exception_state.stopped_on_exception ||
            thread_info->exception_state.stopped_on_unhandled) {
                thread_info->exception_state.stopped_on_exception = 0;
@@ -953,7 +983,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
@@ -970,12 +1000,17 @@ _mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *e
 
        mono_debugger_lock ();
 
-       thread_info = find_debugger_thread_info (mono_thread_current ());
+       thread_info = find_debugger_thread_info (mono_thread_internal_current ());
        if (!thread_info) {
                mono_debugger_unlock ();
                return FALSE;
        }
 
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+               mono_debugger_unlock ();
+               return FALSE;
+       }
+
        if (thread_info->exception_state.stopped_on_unhandled) {
                thread_info->exception_state.stopped_on_unhandled = 0;
                mono_debugger_unlock ();
@@ -1016,12 +1051,17 @@ mono_debugger_call_exception_handler (gpointer addr, gpointer stack, MonoObject
 
        mono_debugger_lock ();
 
-       thread_info = find_debugger_thread_info (mono_thread_current ());
+       thread_info = find_debugger_thread_info (mono_thread_internal_current ());
        if (!thread_info) {
                mono_debugger_unlock ();
                return;
        }
 
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+               mono_debugger_unlock ();
+               return;
+       }
+
        // Prevent the object from being finalized.
        thread_info->exception_state.last_exception = exc;
 
@@ -1037,61 +1077,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 *
@@ -1142,7 +1127,7 @@ mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, Mono
 
        mono_debugger_lock ();
 
-       thread_info = find_debugger_thread_info (mono_thread_current ());
+       thread_info = find_debugger_thread_info (mono_thread_internal_current ());
        if (!thread_info) {
                mono_debugger_unlock ();
                return NULL;
@@ -1154,6 +1139,8 @@ mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, Mono
        thread_info->exception_state.stopped_on_unhandled = 0;
        thread_info->exception_state.stopped_on_exception = 0;
 
+       thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
+
        mono_debugger_unlock ();
 
        if (!strcmp (method->name, ".ctor")) {
@@ -1165,9 +1152,18 @@ mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, Mono
 
        mono_debugger_lock ();
 
-       thread_info = find_debugger_thread_info (mono_thread_current ());
-       if (thread_info)
-               thread_info->exception_state = saved_exception_state;
+       thread_info->exception_state = saved_exception_state;
+       thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
+
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+               thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
+               mono_thread_internal_reset_abort (thread_info->thread);
+
+               mono_debugger_unlock ();
+
+               *exc = NULL;
+               return NULL;
+       }
 
        mono_debugger_unlock ();
 
@@ -1184,4 +1180,35 @@ mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, Mono
        return retval;
 }
 
+gboolean
+mono_debugger_abort_runtime_invoke ()
+{
+       MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoDebuggerThreadInfo *thread_info;
+
+       mono_debugger_lock ();
+
+       thread_info = find_debugger_thread_info (thread);
+       if (!thread_info) {
+               mono_debugger_unlock ();
+               return FALSE;
+       }
+
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE) == 0) {
+               mono_debugger_unlock ();
+               return FALSE;
+       }
+
+       if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+               mono_debugger_unlock ();
+               return TRUE;
+       }
+
+       thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
+       ves_icall_System_Threading_Thread_Abort (thread_info->thread, NULL);
+
+       mono_debugger_unlock ();
+       return TRUE;
+}
+
 #endif