X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdebugger-agent.c;h=dcecc4dfb05f191a8cd5d187d3d271ff44410c8f;hb=f03a1b538bfb0d9be810688e8713731e122320b5;hp=6e07d05e5da01fc6eda01ddaae9206c4fd6957b7;hpb=670fcaf62a5093bd1f8e0cd4f41a338001df56e6;p=mono.git diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 6e07d05e5da..dcecc4dfb05 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -37,10 +37,6 @@ #include #endif -#ifdef HAVE_UCONTEXT_H -#include -#endif - #ifdef HOST_WIN32 #ifdef _MSC_VER #include @@ -77,8 +73,8 @@ #include "seq-points.h" /* -On iOS we can't use System.Environment.Exit () as it will do the wrong -shutdown sequence. + * On iOS we can't use System.Environment.Exit () as it will do the wrong + * shutdown sequence. */ #if !defined (TARGET_IOS) #define TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT @@ -97,9 +93,6 @@ shutdown sequence. #include -/* Definitions to make backporting to 2.6 easier */ -//#define MonoInternalThread MonoThread -//#define mono_thread_internal_current mono_thread_current #define THREAD_TO_INTERNAL(thread) (thread)->internal_thread typedef struct { @@ -206,9 +199,6 @@ typedef struct { /* Whenever thread_stop () was called for this thread */ gboolean terminated; - /* Number of thread interruptions not yet processed */ - gint32 interrupt_count; - /* Whenever to disable breakpoints (used during invokes) */ gboolean disable_breakpoints; @@ -726,7 +716,12 @@ static gboolean buffer_replies; static ReplyPacket reply_packets [128]; int nreply_packets; -#define dbg_lock() mono_mutex_lock (&debug_mutex) +#define dbg_lock() do { \ + MONO_TRY_BLOCKING \ + mono_mutex_lock (&debug_mutex); \ + MONO_FINISH_TRY_BLOCKING \ +} while (0) + #define dbg_unlock() mono_mutex_unlock (&debug_mutex) static mono_mutex_t debug_mutex; @@ -1093,7 +1088,9 @@ finish_agent_init (gboolean on_startup) } } + MONO_PREPARE_BLOCKING transport_connect (agent_config.address); + MONO_FINISH_BLOCKING if (!on_startup) { /* Do some which is usually done after sending the VMStart () event */ @@ -1325,7 +1322,9 @@ socket_transport_connect (const char *address) } } + MONO_PREPARE_BLOCKING conn_fd = socket_transport_accept (sfd); + MONO_FINISH_BLOCKING if (conn_fd == -1) exit (1); @@ -1544,13 +1543,19 @@ transport_handshake (void) /* Write handshake message */ sprintf (handshake_msg, "DWP-Handshake"); + /* Must use try blocking as this can nest into code that runs blocking */ + MONO_TRY_BLOCKING do { res = transport_send (handshake_msg, strlen (handshake_msg)); } while (res == -1 && get_last_sock_error () == MONO_EINTR); + MONO_FINISH_TRY_BLOCKING + g_assert (res != -1); /* Read answer */ + MONO_TRY_BLOCKING res = transport_recv (buf, strlen (handshake_msg)); + MONO_FINISH_TRY_BLOCKING if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg)) != 0)) { fprintf (stderr, "debugger-agent: DWP handshake failed.\n"); return FALSE; @@ -1593,36 +1598,30 @@ stop_debugger_thread (void) if (!inited) return; + MONO_PREPARE_BLOCKING transport_close1 (); + MONO_FINISH_BLOCKING /* * Wait for the thread to exit. * * 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. - * The WaitForSingleObject infrastructure doesn't seem to work during shutdown, so - * use pthreads. */ - //WaitForSingleObject (debugger_thread_handle, INFINITE); if (GetCurrentThreadId () != debugger_thread_id) { do { + MONO_TRY_BLOCKING mono_mutex_lock (&debugger_thread_exited_mutex); - if (!debugger_thread_exited) { -#ifdef HOST_WIN32 - if (WAIT_TIMEOUT == WaitForSingleObject(debugger_thread_exited_cond, 0)) { - mono_mutex_unlock (&debugger_thread_exited_mutex); - Sleep(1); - mono_mutex_lock (&debugger_thread_exited_mutex); - } -#else + if (!debugger_thread_exited) mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex); -#endif - } mono_mutex_unlock (&debugger_thread_exited_mutex); + MONO_FINISH_TRY_BLOCKING } while (!debugger_thread_exited); } + MONO_PREPARE_BLOCKING transport_close2 (); + MONO_FINISH_BLOCKING } static void @@ -1816,7 +1815,9 @@ send_packet (int command_set, int command, Buffer *data) buffer_add_byte (&buf, command); memcpy (buf.buf + 11, data->buf, data->p - data->buf); + MONO_PREPARE_BLOCKING res = transport_send (buf.buf, len); + MONO_FINISH_BLOCKING buffer_free (&buf); @@ -1842,7 +1843,10 @@ send_reply_packets (int npackets, ReplyPacket *packets) buffer_add_byte (&buf, packets [i].error); buffer_add_buffer (&buf, packets [i].data); } + + MONO_PREPARE_BLOCKING res = transport_send (buf.buf, len); + MONO_FINISH_BLOCKING buffer_free (&buf); @@ -2535,51 +2539,19 @@ get_last_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data) /* * thread_interrupt: * - * Process interruption of a thread. If SIGCTX is set, process the current thread. If - * INFO is set, process the thread described by INFO. - * This should be signal safe. + * Process interruption of a thread. This should be signal safe. */ -static gboolean -thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, MonoJitInfo *ji) +static void +thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji) { gboolean res; gpointer ip; MonoNativeThreadId tid; - /* - * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not - * guarantee the signal handler will be called that many times. Instead of tracking - * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt - * has been requested that hasn't been handled yet, otherwise we can have threads - * refuse to die when VM_EXIT is called - */ -#if defined(__APPLE__) - if (InterlockedCompareExchange (&tls->interrupt_count, 0, 1) == 0) - return FALSE; -#else - /* - * We use interrupt_count to determine whenever this interrupt should be processed - * by us or the normal interrupt processing code in the signal handler. - * There is no race here with notify_thread (), since the signal is sent after - * incrementing interrupt_count. - */ - if (tls->interrupt_count == 0) - return FALSE; - - InterlockedDecrement (&tls->interrupt_count); -#endif - - if (sigctx) - ip = mono_arch_ip_from_context (sigctx); - else if (info) - ip = MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx); - else - ip = NULL; + g_assert (info); - if (info) - tid = mono_thread_info_get_tid (info); - else - tid = (MonoNativeThreadId)GetCurrentThreadId (); + ip = MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx); + tid = mono_thread_info_get_tid (info); // FIXME: Races when the thread leaves managed code before hitting a single step // event. @@ -2587,7 +2559,6 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, Mono if (ji) { /* Running managed code, will be suspended by the single step code */ DEBUG_PRINTF (1, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip); - return TRUE; } else { /* * Running native code, will be suspended when it returns to/enters @@ -2607,7 +2578,7 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, Mono if (!tls->thread) /* Already terminated */ - return TRUE; + return; /* * We are in a difficult position: we want to be able to provide stack @@ -2620,17 +2591,7 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, Mono * remain valid. */ data.last_frame_set = FALSE; - if (sigctx) { - mono_sigctx_to_monoctx (sigctx, &ctx); - /* - * Don't pass MONO_UNWIND_ACTUAL_METHOD, its not signal safe, and - * get_last_frame () doesn't need it, the last frame cannot be a ginst - * since we are not in a JITted method. - */ - mono_walk_stack_with_ctx (get_last_frame, &ctx, MONO_UNWIND_NONE, &data); - } else if (info) { - mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, &data); - } + 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) { memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo)); res = mono_thread_state_init_from_monoctx (&tls->async_state, &ctx); @@ -2650,41 +2611,9 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, Mono tls->suspended = TRUE; MONO_SEM_POST (&suspend_sem); } - return TRUE; - } -} - -/* - * mono_debugger_agent_thread_interrupt: - * - * Called by the abort signal handler. - * Should be signal safe. - */ -gboolean -mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji) -{ - DebuggerTlsData *tls; - - if (!inited) - return FALSE; - - tls = mono_native_tls_get_value (debugger_tls_id); - if (!tls) { - DEBUG_PRINTF (1, "[%p] Received interrupt with no TLS, continuing.\n", (gpointer)GetCurrentThreadId ()); - return FALSE; } - - return thread_interrupt (tls, NULL, sigctx, ji); } -#ifdef HOST_WIN32 -static void CALLBACK notify_thread_apc (ULONG_PTR param) -{ - //DebugBreak (); - mono_debugger_agent_thread_interrupt (NULL, NULL); -} -#endif /* HOST_WIN32 */ - /* * reset_native_thread_suspend_state: * @@ -2721,7 +2650,8 @@ debugger_interrupt_critical (MonoThreadInfo *info, gpointer user_data) data->valid_info = TRUE; ji = mono_jit_info_table_find (mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN], MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx)); - thread_interrupt (data->tls, info, NULL, ji); + /* This is signal safe */ + thread_interrupt (data->tls, info, ji); return MonoResumeThread; } @@ -2736,60 +2666,23 @@ notify_thread (gpointer key, gpointer value, gpointer user_data) MonoInternalThread *thread = key; DebuggerTlsData *tls = value; gsize tid = thread->tid; -#ifndef HOST_WIN32 - int res; -#endif if (GetCurrentThreadId () == tid || tls->terminated) return; DEBUG_PRINTF (1, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid); - /* - * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not - * guarantee the signal handler will be called that many times. Instead of tracking - * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt - * has been requested that hasn't been handled yet, otherwise we can have threads - * refuse to die when VM_EXIT is called - */ -#if defined(__APPLE__) - if (InterlockedCompareExchange (&tls->interrupt_count, 1, 0) == 1) - return; -#else - /* - * Maybe we could use the normal interrupt infrastructure, but that does a lot - * of things like breaking waits etc. which we don't want. - */ - InterlockedIncrement (&tls->interrupt_count); -#endif - /* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */ - if (mono_thread_info_new_interrupt_enabled ()) { - InterruptData interrupt_data = { 0 }; - interrupt_data.tls = tls; + InterruptData interrupt_data = { 0 }; + interrupt_data.tls = tls; - 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); - /* - * Attached thread which died without detaching. - */ - tls->terminated = TRUE; - } - } else { -#ifdef HOST_WIN32 - // FIXME: Remove this since new interrupt is used on win32 now - QueueUserAPC (notify_thread_apc, thread->handle, (ULONG_PTR)NULL); -#else - res = mono_thread_kill (thread, mono_thread_get_abort_signal ()); - if (res) { - DEBUG_PRINTF (1, "[%p] mono_thread_kill () failed for %p: %d...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid, res); - /* - * Attached thread which died without detaching. - */ - tls->terminated = TRUE; - } -#endif + 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); + /* + * Attached thread which died without detaching. + */ + tls->terminated = TRUE; } } @@ -2851,7 +2744,9 @@ suspend_vm (void) { mono_loader_lock (); + MONO_TRY_BLOCKING mono_mutex_lock (&suspend_mutex); + MONO_FINISH_TRY_BLOCKING suspend_count ++; @@ -2889,7 +2784,9 @@ resume_vm (void) mono_loader_lock (); + MONO_TRY_BLOCKING mono_mutex_lock (&suspend_mutex); + MONO_FINISH_TRY_BLOCKING g_assert (suspend_count > 0); suspend_count --; @@ -2933,7 +2830,9 @@ resume_thread (MonoInternalThread *thread) tls = mono_g_hash_table_lookup (thread_to_tls, thread); g_assert (tls); + MONO_TRY_BLOCKING mono_mutex_lock (&suspend_mutex); + MONO_FINISH_TRY_BLOCKING g_assert (suspend_count > 0); @@ -2992,10 +2891,8 @@ invalidate_frames (DebuggerTlsData *tls) static void suspend_current (void) { -#ifndef HOST_WIN32 - int err; -#endif DebuggerTlsData *tls; + int err; g_assert (debugger_thread_id != GetCurrentThreadId ()); @@ -3010,7 +2907,9 @@ suspend_current (void) tls = mono_native_tls_get_value (debugger_tls_id); g_assert (tls); + MONO_TRY_BLOCKING mono_mutex_lock (&suspend_mutex); + MONO_FINISH_TRY_BLOCKING tls->suspending = FALSE; tls->really_suspended = TRUE; @@ -3022,22 +2921,12 @@ suspend_current (void) DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ()); + MONO_TRY_BLOCKING while (suspend_count - tls->resume_count > 0) { -#ifdef HOST_WIN32 - if (WAIT_TIMEOUT == WaitForSingleObject(suspend_cond, 0)) - { - mono_mutex_unlock (&suspend_mutex); - Sleep(1); - mono_mutex_lock (&suspend_mutex); - } - else - { - } -#else err = mono_cond_wait (&suspend_cond, &suspend_mutex); g_assert (err == 0); -#endif } + MONO_FINISH_TRY_BLOCKING tls->suspended = FALSE; tls->really_suspended = FALSE; @@ -3174,7 +3063,7 @@ process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data) if (info->il_offset == -1) { /* mono_debug_il_offset_from_address () doesn't seem to be precise enough (#2092) */ if (ud->frames == NULL) { - if (find_prev_seq_point_for_native_offset (info->domain, method, info->native_offset, NULL, &sp)) + if (mono_find_prev_seq_point_for_native_offset (info->domain, method, info->native_offset, NULL, &sp)) info->il_offset = sp.il_offset; } if (info->il_offset == -1) @@ -3564,7 +3453,7 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method); if (minfo) { - mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + mono_debug_get_seq_points (minfo, &source_file, &source_file_list, NULL, NULL, NULL); for (i = 0; i < source_file_list->len; ++i) { sinfo = g_ptr_array_index (source_file_list, i); /* @@ -4287,8 +4176,8 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo if (error) mono_error_init (error); - seq_point_iterator_init (&it, seq_points); - while (seq_point_iterator_next (&it)) { + mono_seq_point_iterator_init (&it, seq_points); + while (mono_seq_point_iterator_next (&it)) { if (it.seq_point.il_offset == bp->il_offset) { it_has_sp = TRUE; break; @@ -4300,8 +4189,8 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo * The set of IL offsets with seq points doesn't completely match the * info returned by CMD_METHOD_GET_DEBUG_INFO (#407). */ - seq_point_iterator_init (&it, seq_points); - while (seq_point_iterator_next (&it)) { + mono_seq_point_iterator_init (&it, seq_points); + while (mono_seq_point_iterator_next (&it)) { if (it.seq_point.il_offset != METHOD_ENTRY_IL_OFFSET && it.seq_point.il_offset != METHOD_EXIT_IL_OFFSET && it.seq_point.il_offset + 1 == bp->il_offset) { @@ -4314,8 +4203,8 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo if (!it_has_sp) { char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%d", mono_method_full_name (jinfo_get_method (ji), TRUE), bp->il_offset); - seq_point_iterator_init (&it, seq_points); - while (seq_point_iterator_next (&it)) + mono_seq_point_iterator_init (&it, seq_points); + while (mono_seq_point_iterator_next (&it)) DEBUG_PRINTF (1, "%d\n", it.seq_point.il_offset); if (error) { @@ -4773,7 +4662,7 @@ process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal) * The ip points to the instruction causing the breakpoint event, which is after * the offset recorded in the seq point map, so find the prev seq point before ip. */ - found_sp = find_prev_seq_point_for_native_offset (mono_domain_get (), method, native_offset, &info, &sp); + 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); @@ -5031,7 +4920,7 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) * The ip points to the instruction causing the single step event, which is before * the offset recorded in the seq point map, so find the next seq point after ip. */ - if (!find_next_seq_point_for_native_offset (domain, method, (guint8*)ip - (guint8*)ji->code_start, &info, &sp)) + if (!mono_find_next_seq_point_for_native_offset (domain, method, (guint8*)ip - (guint8*)ji->code_start, &info, &sp)) return; il_offset = sp.il_offset; @@ -5107,12 +4996,16 @@ debugger_agent_single_step_from_context (MonoContext *ctx) DebuggerTlsData *tls; MonoThreadUnwindState orig_restore_state; + if (GetCurrentThreadId () == debugger_thread_id) + 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. */ memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoThreadUnwindState)); mono_thread_state_init_from_monoctx (&tls->restore_state, ctx); + memcpy (&tls->handler_ctx, ctx, sizeof (MonoContext)); process_single_step_inner (tls, FALSE); @@ -5125,16 +5018,26 @@ debugger_agent_breakpoint_from_context (MonoContext *ctx) { DebuggerTlsData *tls; MonoThreadUnwindState orig_restore_state; + guint8 *orig_ip; + + if (GetCurrentThreadId () == debugger_thread_id) + return; + + orig_ip = MONO_CONTEXT_GET_IP (ctx); + MONO_CONTEXT_SET_IP (ctx, orig_ip - 1); tls = mono_native_tls_get_value (debugger_tls_id); g_assert (tls); - memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoContext)); + memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoThreadUnwindState)); mono_thread_state_init_from_monoctx (&tls->restore_state, ctx); + memcpy (&tls->handler_ctx, ctx, sizeof (MonoContext)); process_breakpoint_inner (tls, FALSE); memcpy (ctx, &tls->restore_state.ctx, sizeof (MonoContext)); memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState)); + if (MONO_CONTEXT_GET_IP (ctx) == orig_ip - 1) + MONO_CONTEXT_SET_IP (ctx, orig_ip); } /* @@ -5258,7 +5161,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI StackFrame *frame = frames [frame_index]; method = frame->method; - found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp); + 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; frame_index ++; if (sp && sp->next_len != 0) @@ -5273,7 +5176,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI StackFrame *frame = frames [frame_index]; method = frame->method; - found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp); + 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 && sp->next_len != 0) break; @@ -5286,7 +5189,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI StackFrame *frame = frames [frame_index]; parent_sp_method = frame->method; - found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &parent_info, &local_parent_sp); + found_sp = mono_find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &parent_info, &local_parent_sp); parent_sp = found_sp ? &local_parent_sp : NULL; if (found_sp && parent_sp->next_len != 0) break; @@ -5299,7 +5202,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI if (sp && sp->next_len > 0) { SeqPoint* next = g_new(SeqPoint, sp->next_len); - seq_point_init_next (info, *sp, next); + mono_seq_point_init_next (info, *sp, next); for (i = 0; i < sp->next_len; i++) { next_sp = &next[i]; @@ -5312,7 +5215,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI if (parent_sp) { SeqPoint* next = g_new(SeqPoint, parent_sp->next_len); - seq_point_init_next (parent_info, *parent_sp, next); + mono_seq_point_init_next (parent_info, *parent_sp, next); for (i = 0; i < parent_sp->next_len; i++) { next_sp = &next[i]; @@ -5346,7 +5249,7 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI for (j = 0; j < jinfo->num_clauses; ++j) { MonoJitExceptionInfo *ei = &jinfo->clauses [j]; - found_sp = find_next_seq_point_for_native_offset (frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL, &local_sp); + found_sp = mono_find_next_seq_point_for_native_offset (frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL, &local_sp); sp = (found_sp)? &local_sp : NULL; if (sp) { bp = set_breakpoint (frame->method, sp->il_offset, ss_req->req, NULL); @@ -5457,7 +5360,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte * Find the seq point corresponding to the landing site ip, which is the first seq * point after ip. */ - found_sp = find_next_seq_point_for_native_offset (frame.domain, frame.method, frame.native_offset, &info, &local_sp); + 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); @@ -5503,7 +5406,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte if (frame) { if (!method && frame->il_offset != -1) { /* FIXME: Sort the table and use a binary search */ - found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp); + 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); @@ -6632,12 +6535,21 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 return ERR_INVALID_ARGUMENT; } m = mono_object_get_virtual_method (this, m); + /* Transform this to the format the rest of the code expects it to be */ + if (m->klass->valuetype) { + this_buf = g_alloca (mono_class_instance_size (m->klass)); + memcpy (this_buf, mono_object_unbox (this), mono_class_instance_size (m->klass)); + } } else if ((m->flags & METHOD_ATTRIBUTE_VIRTUAL) && !m->klass->valuetype && invoke->flags & INVOKE_FLAG_VIRTUAL) { if (!this) { DEBUG_PRINTF (1, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ()); return ERR_INVALID_ARGUMENT; } m = mono_object_get_virtual_method (this, m); + if (m->klass->valuetype) { + this_buf = g_alloca (mono_class_instance_size (m->klass)); + memcpy (this_buf, mono_object_unbox (this), mono_class_instance_size (m->klass)); + } } DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this ? this->vtable->klass->name : ""); @@ -6919,7 +6831,7 @@ get_source_files_for_type (MonoClass *klass) GPtrArray *source_file_list; if (minfo) { - mono_debug_symfile_get_line_numbers_full (minfo, NULL, &source_file_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + mono_debug_get_seq_points (minfo, NULL, &source_file_list, NULL, NULL, NULL); for (j = 0; j < source_file_list->len; ++j) { sinfo = g_ptr_array_index (source_file_list, j); for (i = 0; i < files->len; ++i) @@ -8415,13 +8327,9 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g MonoDebugMethodInfo *minfo; char *source_file; int i, j, n_il_offsets; - int *il_offsets; - int *line_numbers; - int *column_numbers; - int *end_line_numbers; - int *end_column_numbers; int *source_files; GPtrArray *source_file_list; + MonoSymSeqPoint *sym_seq_points; header = mono_method_get_header (method); if (!header) { @@ -8440,7 +8348,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g break; } - mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, &n_il_offsets, &il_offsets, &line_numbers, &column_numbers, &source_files, &end_line_numbers, &end_column_numbers); + mono_debug_get_seq_points (minfo, &source_file, &source_file_list, &source_files, &sym_seq_points, &n_il_offsets); buffer_add_int (buf, header->code_size); if (CHECK_PROTOCOL_VERSION (2, 13)) { buffer_add_int (buf, source_file_list->len); @@ -8458,31 +8366,28 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g buffer_add_int (buf, n_il_offsets); DEBUG_PRINTF (10, "Line number table for method %s:\n", mono_method_full_name (method, TRUE)); for (i = 0; i < n_il_offsets; ++i) { + MonoSymSeqPoint *sp = &sym_seq_points [i]; const char *srcfile = ""; if (source_files [i] != -1) { MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, source_files [i]); srcfile = sinfo->source_file; } - DEBUG_PRINTF (10, "IL%x -> %s:%d %d %d %d\n", il_offsets [i], srcfile, line_numbers [i], column_numbers ? column_numbers [i] : -1, end_line_numbers ? end_line_numbers [i] : -1, end_column_numbers ? end_column_numbers [i] : -1); - buffer_add_int (buf, il_offsets [i]); - buffer_add_int (buf, line_numbers [i]); + DEBUG_PRINTF (10, "IL%x -> %s:%d %d %d %d\n", sp->il_offset, srcfile, sp->line, sp->column, sp->end_line, sp->end_column); + buffer_add_int (buf, sp->il_offset); + buffer_add_int (buf, sp->line); if (CHECK_PROTOCOL_VERSION (2, 13)) buffer_add_int (buf, source_files [i]); if (CHECK_PROTOCOL_VERSION (2, 19)) - buffer_add_int (buf, column_numbers ? column_numbers [i] : -1); + buffer_add_int (buf, sp->column); if (CHECK_PROTOCOL_VERSION (2, 32)) { - buffer_add_int (buf, end_line_numbers ? end_line_numbers [i] : -1); - buffer_add_int (buf, end_column_numbers ? end_column_numbers [i] : -1); + buffer_add_int (buf, sp->end_line); + buffer_add_int (buf, sp->end_column); } } g_free (source_file); - g_free (il_offsets); - g_free (line_numbers); - g_free (column_numbers); - g_free (end_line_numbers); - g_free (end_column_numbers); g_free (source_files); + g_free (sym_seq_points); g_ptr_array_free (source_file_list, TRUE); mono_metadata_free_mh (header); break; @@ -8516,50 +8421,73 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g case CMD_METHOD_GET_LOCALS_INFO: { int i, j, num_locals; MonoDebugLocalsInfo *locals; + int *locals_map = NULL; header = mono_method_get_header (method); if (!header) return ERR_INVALID_ARGUMENT; - buffer_add_int (buf, header->num_locals); - - /* Types */ - for (i = 0; i < header->num_locals; ++i) - buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i])); - - /* Names */ locals = mono_debug_lookup_locals (method); - if (locals) - num_locals = locals->num_locals; - else - num_locals = 0; - for (i = 0; i < header->num_locals; ++i) { - for (j = 0; j < num_locals; ++j) - if (locals->locals [j].index == i) - break; - if (j < num_locals) - buffer_add_string (buf, locals->locals [j].name); - else - buffer_add_string (buf, ""); - } - - /* Scopes */ - for (i = 0; i < header->num_locals; ++i) { - for (j = 0; j < num_locals; ++j) - if (locals->locals [j].index == i) - break; - if (j < num_locals && 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 { + if (!locals) { + buffer_add_int (buf, header->num_locals); + /* Types */ + for (i = 0; i < header->num_locals; ++i) { + buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i])); + } + /* Names */ + for (i = 0; i < header->num_locals; ++i) { + char lname [128]; + sprintf (lname, "V_%d", i); + buffer_add_string (buf, lname); + } + /* Scopes */ + for (i = 0; i < header->num_locals; ++i) { buffer_add_int (buf, 0); 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])); + } + + /* Names */ + for (i = 0; i < header->num_locals; ++i) { + if (locals_map [i] != -1) + buffer_add_string (buf, locals->locals [locals_map [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); + } + } + } } mono_metadata_free_mh (header); if (locals) - mono_debug_symfile_free_locals (locals); + mono_debug_free_locals (locals); + g_free (locals_map); break; } @@ -8935,7 +8863,7 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (tls->frame_count == 0 || tls->frames [0]->actual_method != method) return ERR_INVALID_ARGUMENT; - found_sp = find_seq_point (domain, method, il_offset, &seq_points, &sp); + found_sp = mono_find_seq_point (domain, method, il_offset, &seq_points, &sp); g_assert (seq_points); @@ -9022,7 +8950,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) sig = mono_method_signature (frame->actual_method); - if (!get_seq_points (frame->domain, frame->actual_method)) + if (!mono_get_seq_points (frame->domain, frame->actual_method)) /* * The method is probably from an aot image compiled without soft-debug, variables might be dead, etc. */ @@ -9039,12 +8967,24 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (pos < 0) { pos = - pos - 1; + DEBUG_PRINTF (4, "[dbg] send arg %d.\n", pos); + g_assert (pos >= 0 && pos < jit->num_params); add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE); } else { + MonoDebugLocalsInfo *locals; + + locals = mono_debug_lookup_locals (frame->method); + if (locals) { + g_assert (pos < locals->num_locals); + pos = locals->locals [pos].index; + mono_debug_free_locals (locals); + } g_assert (pos >= 0 && pos < jit->num_locals); + DEBUG_PRINTF (4, "[dbg] send local %d.\n", pos); + add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE); } } @@ -9088,6 +9028,14 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) t = sig->params [pos]; var = &jit->params [pos]; } else { + MonoDebugLocalsInfo *locals; + + locals = mono_debug_lookup_locals (frame->method); + if (locals) { + g_assert (pos < locals->num_locals); + pos = locals->locals [pos].index; + mono_debug_free_locals (locals); + } g_assert (pos >= 0 && pos < jit->num_locals); t = header->locals [pos]; @@ -9588,7 +9536,10 @@ wait_for_attach (void) } /* Block and wait for client connection */ + MONO_PREPARE_BLOCKING conn_fd = socket_transport_accept (listen_fd); + MONO_FINISH_BLOCKING + DEBUG_PRINTF (1, "Accepted connection on %d\n", conn_fd); if (conn_fd == -1) { DEBUG_PRINTF (1, "[dbg] Bad client connection\n"); @@ -9646,7 +9597,9 @@ debugger_thread (void *arg) } while (!attach_failed) { + MONO_PREPARE_BLOCKING res = transport_recv (header, HEADER_LENGTH); + MONO_FINISH_BLOCKING /* This will break if the socket is closed during shutdown too */ if (res != HEADER_LENGTH) { @@ -9681,7 +9634,9 @@ debugger_thread (void *arg) data = g_malloc (len - HEADER_LENGTH); if (len - HEADER_LENGTH > 0) { + MONO_PREPARE_BLOCKING res = transport_recv (data, len - HEADER_LENGTH); + MONO_FINISH_BLOCKING if (res != len - HEADER_LENGTH) { DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH); break; @@ -9771,10 +9726,12 @@ debugger_thread (void *arg) mono_set_is_debugger_attached (FALSE); + MONO_TRY_BLOCKING mono_mutex_lock (&debugger_thread_exited_mutex); debugger_thread_exited = TRUE; mono_cond_signal (&debugger_thread_exited_cond); mono_mutex_unlock (&debugger_thread_exited_mutex); + MONO_FINISH_TRY_BLOCKING DEBUG_PRINTF (1, "[dbg] Debugger thread exited.\n"); @@ -9814,12 +9771,6 @@ mono_debugger_agent_free_domain_info (MonoDomain *domain) { } -gboolean -mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji) -{ - return FALSE; -} - void mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *throw_ctx, MonoContext *catch_ctx)