#include <mono/metadata/mono-debug.h>
#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/debug-mono-symfile.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/threadpool-ms.h>
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 41
+#define MINOR_VERSION 42
typedef enum {
CMD_SET_VM = 1,
ERR_NO_INVOCATION = 104,
ERR_ABSENT_INFORMATION = 105,
ERR_NO_SEQ_POINT_AT_IL_OFFSET = 106,
+ ERR_INVOKE_ABORTED = 107,
ERR_LOADER_ERROR = 200, /*XXX extend the protocol to pass this information down the pipe */
} ErrorCode;
/* 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;
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
event_requests = g_ptr_array_new ();
mono_mutex_init (&debugger_thread_exited_mutex);
- mono_cond_init (&debugger_thread_exited_cond, NULL);
+ mono_cond_init (&debugger_thread_exited_cond, 0);
mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
mono_profiler_set_events (MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS);
/* Needed by the hash_table_new_type () call below */
mono_gc_base_init ();
- thread_to_tls = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
- MONO_GC_REGISTER_ROOT_FIXED (thread_to_tls);
+ thread_to_tls = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_DEBUGGER, "thread-to-tls table");
+ MONO_GC_REGISTER_ROOT_FIXED (thread_to_tls, MONO_ROOT_SOURCE_DEBUGGER, "thread-to-tls table");
- tid_to_thread = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
- MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread);
+ tid_to_thread = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DEBUGGER, "tid-to-thread table");
+ MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread, MONO_ROOT_SOURCE_DEBUGGER, "tid-to-thread table");
- tid_to_thread_obj = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
- MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread_obj);
+ tid_to_thread_obj = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DEBUGGER, "tid-to-thread object table");
+ MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread_obj, MONO_ROOT_SOURCE_DEBUGGER, "tid-to-thread object table");
pending_assembly_loads = g_ptr_array_new ();
domains = g_hash_table_new (mono_aligned_addr_hash, NULL);
* 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);
{
objrefs = g_hash_table_new_full (NULL, NULL, NULL, free_objref);
obj_to_objref = g_hash_table_new (NULL, NULL);
- suspended_objs = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
- MONO_GC_REGISTER_ROOT_FIXED (suspended_objs);
+ suspended_objs = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_DEBUGGER, "suspended objects table");
+ MONO_GC_REGISTER_ROOT_FIXED (suspended_objs, MONO_ROOT_SOURCE_DEBUGGER, "suspended objects table");
}
static void
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);
}
}
suspend_init (void)
{
mono_mutex_init (&suspend_mutex);
- mono_cond_init (&suspend_cond, NULL);
+ mono_cond_init (&suspend_cond, 0);
MONO_SEM_INIT (&suspend_sem, 0);
}
gboolean last_frame_set;
MonoContext ctx;
gpointer lmf;
+ MonoDomain *domain;
} GetLastFrameUserData;
static gboolean
/* 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;
* 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
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;
}
{
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 };
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.
*/
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) {
/*
* 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;
}
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 ?
{
int err;
- g_assert (debugger_thread_id == GetCurrentThreadId ());
+ g_assert (is_debugger_thread ());
mono_loader_lock ();
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 ?
int err;
DebuggerTlsData *tls;
- g_assert (debugger_thread_id == GetCurrentThreadId ());
+ g_assert (is_debugger_thread ());
mono_loader_lock ();
DebuggerTlsData *tls;
int err;
- g_assert (debugger_thread_id != GetCurrentThreadId ());
+ g_assert (!is_debugger_thread ());
if (mono_loader_lock_is_owned_by_self ()) {
/*
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) {
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 */
}
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 {
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);
}
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;
}
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:
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) {
* 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 ();
}
}
g_assert (!tls);
// FIXME: Free this somewhere
tls = g_new0 (DebuggerTlsData, 1);
- MONO_GC_REGISTER_ROOT_SINGLE (tls->thread);
+ MONO_GC_REGISTER_ROOT_SINGLE (tls->thread, MONO_ROOT_SOURCE_DEBUGGER, "debugger thread reference");
tls->thread = thread;
mono_native_tls_set_value (debugger_tls_id, tls);
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);
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 */
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.
/*
* 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;
}
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;
}
}
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;
}
}
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;
}
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) {
// 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
mono_loader_unlock ();
process_event (EVENT_KIND_USER_BREAK, NULL, 0, &ctx, events, suspend_policy);
- } else {
+ } else if (debug_options.native_debugger_break) {
G_BREAKPOINT ();
}
}
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;
}
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);
// 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.
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. */
MonoThreadUnwindState orig_restore_state;
guint8 *orig_ip;
- if (GetCurrentThreadId () == debugger_thread_id)
+ if (is_debugger_thread ())
return;
orig_ip = MONO_CONTEXT_GET_IP (ctx);
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;
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;
}
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;
!(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;
}
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;
}
* 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 ();
}
/* 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));
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);
}
} 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);
}
}
- 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;
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);
err = do_invoke_method (tls, &buf, invoke, p, &p);
}
+ if (tls->abort_requested) {
+ if (CHECK_PROTOCOL_VERSION (2, 42))
+ err = ERR_INVOKE_ABORTED;
+ }
+
/* Start suspending before sending the reply */
if (mindex == invoke->nmethods - 1) {
if (!(invoke->flags & INVOKE_FLAG_SINGLE_THREADED)) {
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:
* Store the invoke data into tls, the thread will execute it after it is
* resumed.
*/
- if (tls->pending_invoke || tls->invoke)
+ if (tls->pending_invoke)
return ERR_NOT_SUSPENDED;
tls->pending_invoke = g_new0 (InvokeData, 1);
tls->pending_invoke->id = id;
g_assert (tls);
if (tls->abort_requested) {
+ DEBUG_PRINTF (1, "Abort already requested.\n");
mono_loader_unlock ();
break;
}
break;
}
case CMD_METHOD_GET_LOCALS_INFO: {
- int i, j, num_locals;
+ int i, num_locals;
MonoDebugLocalsInfo *locals;
int *locals_map = NULL;
buffer_add_int (buf, header->code_size);
}
} else {
- /* Maps between the IL locals index and the index in locals->locals */
- locals_map = g_new0 (int, header->num_locals);
- for (i = 0; i < header->num_locals; ++i)
- locals_map [i] = -1;
num_locals = locals->num_locals;
- for (i = 0; i < num_locals; ++i) {
- g_assert (locals->locals [i].index < header->num_locals);
- locals_map [locals->locals [i].index] = i;
- }
buffer_add_int (buf, num_locals);
/* Types */
- for (i = 0; i < header->num_locals; ++i) {
- if (locals_map [i] != -1)
- buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i]));
+ for (i = 0; i < num_locals; ++i) {
+ g_assert (locals->locals [i].index < header->num_locals);
+ buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [locals->locals [i].index]));
}
-
/* Names */
- for (i = 0; i < header->num_locals; ++i) {
- if (locals_map [i] != -1)
- buffer_add_string (buf, locals->locals [locals_map [i]].name);
- }
-
+ for (i = 0; i < num_locals; ++i)
+ buffer_add_string (buf, locals->locals [i].name);
/* Scopes */
- for (i = 0; i < header->num_locals; ++i) {
- if (locals_map [i] != -1) {
- j = locals_map [i];
- if (locals->locals [j].block) {
- buffer_add_int (buf, locals->locals [j].block->start_offset);
- buffer_add_int (buf, locals->locals [j].block->end_offset);
- } else {
- buffer_add_int (buf, 0);
- buffer_add_int (buf, header->code_size);
- }
+ for (i = 0; i < num_locals; ++i) {
+ if (locals->locals [i].block) {
+ buffer_add_int (buf, locals->locals [i].block->start_offset);
+ buffer_add_int (buf, locals->locals [i].block->end_offset);
+ } else {
+ buffer_add_int (buf, 0);
+ buffer_add_int (buf, header->code_size);
}
}
}
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 ());