Merge pull request #2200 from xmcclure/image-audit-oops
[mono.git] / mono / mini / debugger-agent.c
index 5a5faf35c4663f289bbf2821a3059955f12068af..db2dc5defcfb927f74c874c9584a600c9fab007a 100644 (file)
@@ -662,7 +662,7 @@ static MonoGHashTable *tid_to_thread;
 /* Protected by the loader lock */
 static MonoGHashTable *tid_to_thread_obj;
 
-static gsize debugger_thread_id;
+static MonoNativeThreadId debugger_thread_id;
 
 static HANDLE debugger_thread_handle;
 
@@ -811,7 +811,7 @@ register_socket_transport (void);
 static inline gboolean
 is_debugger_thread (void)
 {
-       return GetCurrentThreadId () == debugger_thread_id;
+       return mono_native_thread_id_equals (mono_native_thread_id_get (), debugger_thread_id);
 }
 
 static int
@@ -1602,7 +1602,7 @@ stop_debugger_thread (void)
         * If we continue with the shutdown without waiting for it, then the client might
         * not receive an answer to its last command like a resume.
         */
-       if (GetCurrentThreadId () != debugger_thread_id) {
+       if (!is_debugger_thread ()) {
                do {
                        MONO_TRY_BLOCKING;
                        mono_mutex_lock (&debugger_thread_exited_mutex);
@@ -2392,10 +2392,10 @@ buffer_add_typeid (Buffer *buf, MonoDomain *domain, MonoClass *klass)
                char *s;
 
                s = mono_type_full_name (&klass->byval_arg);
-               if (GetCurrentThreadId () == debugger_thread_id)
+               if (is_debugger_thread ())
                        DEBUG_PRINTF (2, "[dbg]   send class [%s]\n", s);
                else
-                       DEBUG_PRINTF (2, "[%p]   send class [%s]\n", (gpointer)GetCurrentThreadId (), s);
+                       DEBUG_PRINTF (2, "[%p]   send class [%s]\n", (gpointer)mono_native_thread_id_get (), s);
                g_free (s);
        }
 }
@@ -2502,6 +2502,7 @@ typedef struct
        gboolean last_frame_set;
        MonoContext ctx;
        gpointer lmf;
+       MonoDomain *domain;
 } GetLastFrameUserData;
 
 static gboolean
@@ -2521,19 +2522,32 @@ get_last_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
                /* Store the context/lmf for the frame above the last frame */
                memcpy (&data->ctx, ctx, sizeof (MonoContext));
                data->lmf = info->lmf;
+               data->domain = info->domain;
                return TRUE;
        }
 }
 
+static void
+copy_unwind_state_from_frame_data (MonoThreadUnwindState *to, GetLastFrameUserData *data, gpointer jit_tls)
+{
+       memcpy (&to->ctx, &data->ctx, sizeof (MonoContext));
+
+       to->unwind_data [MONO_UNWIND_DATA_DOMAIN] = data->domain;
+       to->unwind_data [MONO_UNWIND_DATA_LMF] = data->lmf;
+       to->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
+       to->valid = TRUE;
+}
+
 /*
  * thread_interrupt:
  *
  *   Process interruption of a thread. This should be signal safe.
+ *
+ * This always runs in the debugger thread.
  */
 static void
 thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
 {
-       gboolean res;
        gpointer ip;
        MonoNativeThreadId tid;
 
@@ -2556,7 +2570,6 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
                 * tls->suspending flag to avoid races when that happens.
                 */
                if (!tls->suspended && !tls->suspending) {
-                       MonoContext ctx;
                        GetLastFrameUserData data;
 
                        // FIXME: printf is not signal safe, but this is only used during
@@ -2582,15 +2595,12 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
                        data.last_frame_set = FALSE;
                        mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, &data);
                        if (data.last_frame_set) {
+                               gpointer jit_tls = ((MonoThreadInfo*)tls->thread->thread_info)->jit_data;
+
                                memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo));
-                               res = mono_thread_state_init_from_monoctx (&tls->async_state, &ctx);
-                               g_assert (res);
-                               mono_thread_state_init_from_monoctx (&tls->context, &ctx);
-                               g_assert (res);
 
-                               memcpy (&tls->async_state.ctx, &data.ctx, sizeof (MonoContext));
-                               tls->async_state.unwind_data [MONO_UNWIND_DATA_LMF] = data.lmf;
-                               tls->async_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = ((MonoThreadInfo*)tls->thread->thread_info)->jit_data;
+                               copy_unwind_state_from_frame_data (&tls->async_state, &data, jit_tls);
+                               copy_unwind_state_from_frame_data (&tls->context, &data, jit_tls);
                        } else {
                                tls->async_state.valid = FALSE;
                        }
@@ -2658,12 +2668,12 @@ notify_thread (gpointer key, gpointer value, gpointer user_data)
 {
        MonoInternalThread *thread = key;
        DebuggerTlsData *tls = value;
-       gsize tid = thread->tid;
+       MonoNativeThreadId tid = MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid);
 
-       if (GetCurrentThreadId () == tid || tls->terminated)
+       if (mono_native_thread_id_equals (mono_native_thread_id_get (), tid) || tls->terminated)
                return;
 
-       DEBUG_PRINTF (1, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid);
+       DEBUG_PRINTF (1, "[%p] Interrupting %p...\n", (gpointer)mono_native_thread_id_get (), (gpointer)tid);
 
        /* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */
        InterruptData interrupt_data = { 0 };
@@ -2671,7 +2681,7 @@ notify_thread (gpointer key, gpointer value, gpointer user_data)
 
        mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gpointer)(gsize)thread->tid, FALSE, debugger_interrupt_critical, &interrupt_data);
        if (!interrupt_data.valid_info) {
-               DEBUG_PRINTF (1, "[%p] mono_thread_info_suspend_sync () failed for %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid);
+               DEBUG_PRINTF (1, "[%p] mono_thread_info_suspend_sync () failed for %p...\n", (gpointer)mono_native_thread_id_get (), (gpointer)tid);
                /* 
                 * Attached thread which died without detaching.
                 */
@@ -2695,14 +2705,14 @@ process_suspend (DebuggerTlsData *tls, MonoContext *ctx)
                return;
        }
 
-       if (debugger_thread_id == GetCurrentThreadId ())
+       if (is_debugger_thread ())
                return;
 
        /* Prevent races with mono_debugger_agent_thread_interrupt () */
        if (suspend_count - tls->resume_count > 0)
                tls->suspending = TRUE;
 
-       DEBUG_PRINTF (1, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ());
+       DEBUG_PRINTF (1, "[%p] Received single step event for suspending.\n", (gpointer)mono_native_thread_id_get ());
 
        if (suspend_count - tls->resume_count == 0) {
                /* 
@@ -2710,7 +2720,7 @@ process_suspend (DebuggerTlsData *tls, MonoContext *ctx)
                 * suspending is still active.
                 * FIXME: This slows down single threaded invokes.
                 */
-               DEBUG_PRINTF (1, "[%p] Ignored during single threaded invoke.\n", (gpointer)GetCurrentThreadId ());
+               DEBUG_PRINTF (1, "[%p] Ignored during single threaded invoke.\n", (gpointer)mono_native_thread_id_get ());
                return;
        }
 
@@ -2743,7 +2753,7 @@ suspend_vm (void)
 
        suspend_count ++;
 
-       DEBUG_PRINTF (1, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ());
+       DEBUG_PRINTF (1, "[%p] Suspending vm...\n", (gpointer)mono_native_thread_id_get ());
 
        if (suspend_count == 1) {
                // FIXME: Is it safe to call this inside the lock ?
@@ -2773,7 +2783,7 @@ resume_vm (void)
 {
        int err;
 
-       g_assert (debugger_thread_id == GetCurrentThreadId ());
+       g_assert (is_debugger_thread ());
 
        mono_loader_lock ();
 
@@ -2784,7 +2794,7 @@ resume_vm (void)
        g_assert (suspend_count > 0);
        suspend_count --;
 
-       DEBUG_PRINTF (1, "[%p] Resuming vm, suspend count=%d...\n", (gpointer)GetCurrentThreadId (), suspend_count);
+       DEBUG_PRINTF (1, "[%p] Resuming vm, suspend count=%d...\n", (gpointer)mono_native_thread_id_get (), suspend_count);
 
        if (suspend_count == 0) {
                // FIXME: Is it safe to call this inside the lock ?
@@ -2816,7 +2826,7 @@ resume_thread (MonoInternalThread *thread)
        int err;
        DebuggerTlsData *tls;
 
-       g_assert (debugger_thread_id == GetCurrentThreadId ());
+       g_assert (is_debugger_thread ());
 
        mono_loader_lock ();
 
@@ -2887,7 +2897,7 @@ suspend_current (void)
        DebuggerTlsData *tls;
        int err;
 
-       g_assert (debugger_thread_id != GetCurrentThreadId ());
+       g_assert (!is_debugger_thread ());
 
        if (mono_loader_lock_is_owned_by_self ()) {
                /*
@@ -2912,7 +2922,7 @@ suspend_current (void)
                MONO_SEM_POST (&suspend_sem);
        }
 
-       DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ());
+       DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)mono_native_thread_id_get ());
 
        MONO_TRY_BLOCKING;
        while (suspend_count - tls->resume_count > 0) {
@@ -2928,7 +2938,7 @@ suspend_current (void)
 
        mono_mutex_unlock (&suspend_mutex);
 
-       DEBUG_PRINTF (1, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ());
+       DEBUG_PRINTF (1, "[%p] Resumed.\n", (gpointer)mono_native_thread_id_get ());
 
        if (tls->pending_invoke) {
                /* Save the original context */
@@ -3009,12 +3019,12 @@ is_suspended (void)
 }
 
 static void
-no_seq_points_found (MonoMethod *method)
+no_seq_points_found (MonoMethod *method, int offset)
 {
        /*
         * This can happen in full-aot mode with assemblies AOTed without the 'soft-debug' option to save space.
         */
-       printf ("Unable to find seq points for method '%s'.\n", mono_method_full_name (method, TRUE));
+       printf ("Unable to find seq points for method '%s', offset 0x%x.\n", mono_method_full_name (method, TRUE), offset);
 }
 
 typedef struct {
@@ -3243,7 +3253,7 @@ emit_appdomain_load (gpointer key, gpointer value, gpointer user_data)
 static void
 emit_thread_start (gpointer key, gpointer value, gpointer user_data)
 {
-       if (GPOINTER_TO_INT (key) != debugger_thread_id)
+       if (!mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (GPOINTER_TO_UINT (key)), debugger_thread_id))
                process_profiler_event (EVENT_KIND_THREAD_START, value);
 }
 
@@ -3600,14 +3610,14 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
 
                if (agent_config.defer) {
                        /* Make sure the thread id is always set when doing deferred debugging */
-                       if (debugger_thread_id == GetCurrentThreadId ()) {
+                       if (is_debugger_thread ()) {
                                /* Don't suspend on events from the debugger thread */
                                suspend_policy = SUSPEND_POLICY_NONE;
                                thread = mono_thread_get_main ();
                        }
                        else thread = mono_thread_current ();
                } else {
-                       if (debugger_thread_id == GetCurrentThreadId () && event != EVENT_KIND_VM_DEATH)
+                       if (is_debugger_thread () && event != EVENT_KIND_VM_DEATH)
                                // FIXME: Send these with a NULL thread, don't suspend the current thread
                                return;
                }
@@ -3744,7 +3754,7 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
                vm_start_event_sent = TRUE;
        }
 
-       DEBUG_PRINTF (1, "[%p] Sent %d events %s(%d), suspend=%d.\n", (gpointer)GetCurrentThreadId (), nevents, event_to_string (event), ecount, suspend_policy);
+       DEBUG_PRINTF (1, "[%p] Sent %d events %s(%d), suspend=%d.\n", (gpointer)mono_native_thread_id_get (), nevents, event_to_string (event), ecount, suspend_policy);
 
        switch (suspend_policy) {
        case SUSPEND_POLICY_NONE:
@@ -3802,13 +3812,13 @@ thread_startup (MonoProfiler *prof, uintptr_t tid)
        MonoInternalThread *old_thread;
        DebuggerTlsData *tls;
 
-       if (tid == debugger_thread_id)
+       if (mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (tid), debugger_thread_id))
                return;
 
-       g_assert (thread->tid == tid);
+       g_assert (mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (tid), MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid)));
 
        mono_loader_lock ();
-       old_thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
+       old_thread = mono_g_hash_table_lookup (tid_to_thread, GUINT_TO_POINTER (tid));
        mono_loader_unlock ();
        if (old_thread) {
                if (thread == old_thread) {
@@ -3816,18 +3826,18 @@ thread_startup (MonoProfiler *prof, uintptr_t tid)
                         * For some reason, thread_startup () might be called for the same thread
                         * multiple times (attach ?).
                         */
-                       DEBUG_PRINTF (1, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid);
+                       DEBUG_PRINTF (1, "[%p] thread_start () called multiple times for %p, ignored.\n", GUINT_TO_POINTER (tid), GUINT_TO_POINTER (tid));
                        return;
                } else {
                        /*
                         * thread_end () might not be called for some threads, and the tid could
                         * get reused.
                         */
-                       DEBUG_PRINTF (1, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid);
+                       DEBUG_PRINTF (1, "[%p] Removing stale data for tid %p.\n", GUINT_TO_POINTER (tid), GUINT_TO_POINTER (tid));
                        mono_loader_lock ();
                        mono_g_hash_table_remove (thread_to_tls, old_thread);
-                       mono_g_hash_table_remove (tid_to_thread, (gpointer)tid);
-                       mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
+                       mono_g_hash_table_remove (tid_to_thread, GUINT_TO_POINTER (tid));
+                       mono_g_hash_table_remove (tid_to_thread_obj, GUINT_TO_POINTER (tid));
                        mono_loader_unlock ();
                }
        }
@@ -3845,7 +3855,7 @@ thread_startup (MonoProfiler *prof, uintptr_t tid)
        mono_loader_lock ();
        mono_g_hash_table_insert (thread_to_tls, thread, tls);
        mono_g_hash_table_insert (tid_to_thread, (gpointer)tid, thread);
-       mono_g_hash_table_insert (tid_to_thread_obj, (gpointer)tid, mono_thread_current ());
+       mono_g_hash_table_insert (tid_to_thread_obj, GUINT_TO_POINTER (tid), mono_thread_current ());
        mono_loader_unlock ();
 
        process_profiler_event (EVENT_KIND_THREAD_START, thread);
@@ -3863,9 +3873,9 @@ thread_end (MonoProfiler *prof, uintptr_t tid)
        DebuggerTlsData *tls = NULL;
 
        mono_loader_lock ();
-       thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
+       thread = mono_g_hash_table_lookup (tid_to_thread, GUINT_TO_POINTER (tid));
        if (thread) {
-               mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
+               mono_g_hash_table_remove (tid_to_thread_obj, GUINT_TO_POINTER (tid));
                tls = mono_g_hash_table_lookup (thread_to_tls, thread);
                if (tls) {
                        /* FIXME: Maybe we need to free this instead, but some code can't handle that */
@@ -3881,7 +3891,9 @@ thread_end (MonoProfiler *prof, uintptr_t tid)
        if (thread) {
                DEBUG_PRINTF (1, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls);
 
-               if (GetCurrentThreadId () == tid && !mono_native_tls_get_value (debugger_tls_id)) {
+               if (mono_native_thread_id_equals (mono_native_thread_id_get (), MONO_UINT_TO_NATIVE_THREAD_ID (tid))
+                    && !mono_native_tls_get_value (debugger_tls_id)
+               ) {
                        /*
                         * This can happen on darwin since we deregister threads using pthread dtors.
                         * process_profiler_event () and the code it calls cannot handle a null TLS value.
@@ -4518,7 +4530,7 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t
                /*
                 * These seq points are inserted by the JIT after calls, step over needs to skip them.
                 */
-               DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
+               DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping over, continuing single stepping.\n", (gpointer)mono_native_thread_id_get (), sp->il_offset);
                return FALSE;
        }
 
@@ -4528,7 +4540,7 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t
                compute_frame_info (tls->thread, tls);
                if (req->nframes && tls->frame_count && tls->frame_count > req->nframes) {
                        /* Hit the breakpoint in a recursive call */
-                       DEBUG_PRINTF (1, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ());
+                       DEBUG_PRINTF (1, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)mono_native_thread_id_get ());
                        return FALSE;
                }
        }
@@ -4539,7 +4551,7 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t
                        mono_thread_state_init_from_monoctx (&tls->context, ctx);
                compute_frame_info (tls->thread, tls);
                if (ss_req->start_method == method && req->nframes && tls->frame_count == req->nframes) {//Check also frame count(could be recursion)
-                       DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping in, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
+                       DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping in, continuing single stepping.\n", (gpointer)mono_native_thread_id_get (), sp->il_offset);
                        return FALSE;
                }
        }
@@ -4555,11 +4567,11 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t
                loc = mono_debug_symfile_lookup_location (minfo, sp->il_offset);
 
        if (!loc) {
-               DEBUG_PRINTF (1, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
+               DEBUG_PRINTF (1, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)mono_native_thread_id_get (), sp->il_offset);
                ss_req->last_method = method;
                hit = FALSE;
        } else if (loc && method == ss_req->last_method && loc->row == ss_req->last_line) {
-               DEBUG_PRINTF (1, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)GetCurrentThreadId (), loc->row);
+               DEBUG_PRINTF (1, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)mono_native_thread_id_get (), loc->row);
                hit = FALSE;
        }
                                
@@ -4628,11 +4640,11 @@ process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal)
        found_sp = mono_find_prev_seq_point_for_native_offset (mono_domain_get (), method, native_offset, &info, &sp);
 
        if (!found_sp)
-               no_seq_points_found (method);
+               no_seq_points_found (method, native_offset);
 
        g_assert (found_sp);
 
-       DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer)GetCurrentThreadId (), method->name, ip, sp.il_offset, native_offset);
+       DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer)mono_native_thread_id_get (), method->name, ip, sp.il_offset, native_offset);
 
        bp = NULL;
        for (i = 0; i < breakpoints->len; ++i) {
@@ -4739,7 +4751,7 @@ resume_from_signal_handler (void *sigctx, void *func)
        // FIXME: This might not work on an altstack ?
        tls = mono_native_tls_get_value (debugger_tls_id);
        if (!tls)
-               fprintf (stderr, "Thread %p is not attached to the JIT.\n", (gpointer)GetCurrentThreadId ());
+               fprintf (stderr, "Thread %p is not attached to the JIT.\n", (gpointer)mono_native_thread_id_get ());
        g_assert (tls);
 
        // FIXME: MonoContext usually doesn't include the fp registers, so these are 
@@ -4846,6 +4858,9 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
                mono_arch_skip_single_step (ctx);
 
        if (suspend_count > 0) {
+               /* Fastpath during invokes, see in process_suspend () */
+               if (suspend_count - tls->resume_count == 0)
+                       return;
                process_suspend (tls, ctx);
                return;
        }
@@ -4860,7 +4875,7 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
        if (log_level > 0) {
                ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
 
-               DEBUG_PRINTF (1, "[%p] Single step event (depth=%s) at %s (%p)[0x%x], sp %p, last sp %p\n", (gpointer)GetCurrentThreadId (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), (int)((guint8*)MONO_CONTEXT_GET_IP (ctx) - (guint8*)ji->code_start), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp);
+               DEBUG_PRINTF (1, "[%p] Single step event (depth=%s) at %s (%p)[0x%x], sp %p, last sp %p\n", (gpointer)mono_native_thread_id_get (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), (int)((guint8*)MONO_CONTEXT_GET_IP (ctx) - (guint8*)ji->code_start), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp);
        }
 
        ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
@@ -4936,7 +4951,7 @@ mono_debugger_agent_single_step_event (void *sigctx)
        // be as fast as possible. Move the relevant code from process_single_step_inner ()
        // here
 
-       if (GetCurrentThreadId () == debugger_thread_id) {
+       if (is_debugger_thread ()) {
                /* 
                 * This could happen despite our best effors when the runtime calls 
                 * assembly/type resolve hooks.
@@ -4959,10 +4974,14 @@ debugger_agent_single_step_from_context (MonoContext *ctx)
        DebuggerTlsData *tls;
        MonoThreadUnwindState orig_restore_state;
 
-       if (GetCurrentThreadId () == debugger_thread_id)
+       tls = mono_native_tls_get_value (debugger_tls_id);
+       /* Fastpath during invokes, see in process_suspend () */
+       if (tls && suspend_count && suspend_count - tls->resume_count == 0)
+               return;
+
+       if (is_debugger_thread ())
                return;
 
-       tls = mono_native_tls_get_value (debugger_tls_id);
        g_assert (tls);
 
        /* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */
@@ -4983,7 +5002,7 @@ debugger_agent_breakpoint_from_context (MonoContext *ctx)
        MonoThreadUnwindState orig_restore_state;
        guint8 *orig_ip;
 
-       if (GetCurrentThreadId () == debugger_thread_id)
+       if (is_debugger_thread ())
                return;
 
        orig_ip = MONO_CONTEXT_GET_IP (ctx);
@@ -5313,7 +5332,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte
                found_sp = mono_find_next_seq_point_for_native_offset (frame.domain, frame.method, frame.native_offset, &info, &local_sp);
                sp = (found_sp)? &local_sp : NULL;
                if (!sp)
-                       no_seq_points_found (frame.method);
+                       no_seq_points_found (frame.method, frame.native_offset);
                g_assert (sp);
 
                method = frame.method;
@@ -5359,7 +5378,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte
                                found_sp = mono_find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp);
                                sp = (found_sp)? &local_sp : NULL;
                                if (!sp)
-                                       no_seq_points_found (frame->method);
+                                       no_seq_points_found (frame->method, frame->native_offset);
                                g_assert (sp);
                                method = frame->method;
                        }
@@ -5873,7 +5892,7 @@ decode_vtype (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8
        if (t && klass != mono_class_from_mono_type (t)) {
                char *name = mono_type_full_name (t);
                char *name2 = mono_type_full_name (&klass->byval_arg);
-               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got %s.\n", (gpointer)GetCurrentThreadId (), name, name2);
+               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got %s.\n", (gpointer)mono_native_thread_id_get (), name, name2);
                g_free (name);
                g_free (name2);
                return ERR_INVALID_ARGUMENT;
@@ -5909,7 +5928,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
                !(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE) &&
                !(t->type == MONO_TYPE_VALUETYPE && type == MONO_TYPE_OBJECT)) {
                char *name = mono_type_full_name (t);
-               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type);
+               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)mono_native_thread_id_get (), name, type);
                g_free (name);
                return ERR_INVALID_ARGUMENT;
        }
@@ -6053,7 +6072,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
                                g_free (vtype_buf);
                        } else {
                                char *name = mono_type_full_name (t);
-                               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type);
+                               DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)mono_native_thread_id_get (), name, type);
                                g_free (name);
                                return ERR_INVALID_ARGUMENT;
                        }
@@ -6466,7 +6485,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
                 * Invoke this method directly, currently only Environment.Exit () is supported.
                 */
                this_arg = NULL;
-               DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (invoke->method, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
+               DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)mono_native_thread_id_get (), mono_method_full_name (invoke->method, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
                mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
                g_assert_not_reached ();
        }
@@ -6484,7 +6503,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
                /* Should be null */
                int type = decode_byte (p, &p, end);
                if (type != VALUE_TYPE_ID_NULL) {
-                       DEBUG_PRINTF (1, "[%p] Error: Static vtype method invoked with this argument.\n", (gpointer)GetCurrentThreadId ());
+                       DEBUG_PRINTF (1, "[%p] Error: Static vtype method invoked with this argument.\n", (gpointer)mono_native_thread_id_get ());
                        return ERR_INVALID_ARGUMENT;
                }
                memset (this_buf, 0, mono_class_instance_size (m->klass));
@@ -6514,7 +6533,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
 
        if (MONO_CLASS_IS_INTERFACE (m->klass)) {
                if (!this_arg) {
-                       DEBUG_PRINTF (1, "[%p] Error: Interface method invoked without this argument.\n", (gpointer)GetCurrentThreadId ());
+                       DEBUG_PRINTF (1, "[%p] Error: Interface method invoked without this argument.\n", (gpointer)mono_native_thread_id_get ());
                        return ERR_INVALID_ARGUMENT;
                }
                m = mono_object_get_virtual_method (this_arg, m);
@@ -6525,7 +6544,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
                }
        } else if ((m->flags & METHOD_ATTRIBUTE_VIRTUAL) && !m->klass->valuetype && invoke->flags & INVOKE_FLAG_VIRTUAL) {
                if (!this_arg) {
-                       DEBUG_PRINTF (1, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ());
+                       DEBUG_PRINTF (1, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)mono_native_thread_id_get ());
                        return ERR_INVALID_ARGUMENT;
                }
                m = mono_object_get_virtual_method (this_arg, m);
@@ -6535,7 +6554,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
                }
        }
 
-       DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
+       DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)mono_native_thread_id_get (), mono_method_full_name (m, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
 
        if (this_arg && this_arg->vtable->domain != domain)
                NOT_IMPLEMENTED;
@@ -6617,7 +6636,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
        else
                res = mono_runtime_invoke (m, this_arg, args, &exc);
        mono_stopwatch_stop (&watch);
-       DEBUG_PRINTF (1, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer)GetCurrentThreadId (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch));
+       DEBUG_PRINTF (1, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer)mono_native_thread_id_get (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch));
        if (exc) {
                buffer_add_byte (buf, 0);
                buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain);
@@ -6764,7 +6783,7 @@ invoke_method (void)
                tls->resume_count -= invoke->suspend_count;
        }
 
-       DEBUG_PRINTF (1, "[%p] Invoke finished (%d), resume_count = %d.\n", (gpointer)GetCurrentThreadId (), err, tls->resume_count);
+       DEBUG_PRINTF (1, "[%p] Invoke finished (%d), resume_count = %d.\n", (gpointer)mono_native_thread_id_get (), err, tls->resume_count);
 
        /*
         * Take the loader lock to avoid race conditions with CMD_VM_ABORT_INVOKE:
@@ -9573,9 +9592,9 @@ debugger_thread (void *arg)
        gboolean no_reply;
        gboolean attach_failed = FALSE;
 
-       DEBUG_PRINTF (1, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ());
+       DEBUG_PRINTF (1, "[dbg] Agent thread started, pid=%p\n", (gpointer)mono_native_thread_id_get ());
 
-       debugger_thread_id = GetCurrentThreadId ();
+       debugger_thread_id = mono_native_thread_id_get ();
 
        mono_jit_thread_attach (mono_get_root_domain ());