2010-01-16 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / debugger-agent.c
index 3982519e7b96075c4626ea39038665f6ffc3471b..3d544f8b1c15d8f7bc33fb5581feffcf053563d4 100644 (file)
@@ -572,7 +572,7 @@ static void ids_cleanup (void);
 
 static void suspend_init (void);
 
-static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info);
+static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls);
 static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req);
 static void ss_destroy (SingleStepReq *req);
 
@@ -662,6 +662,8 @@ mono_debugger_agent_parse_options (char *options)
                } else if (strncmp (arg, "onthrow=", 8) == 0) {
                        /* We support multiple onthrow= options */
                        agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (arg + 8));
+               } else if (strncmp (arg, "onthrow", 7) == 0) {
+                       agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (""));
                } else if (strncmp (arg, "help", 4) == 0) {
                        print_usage ();
                        exit (0);
@@ -950,7 +952,15 @@ transport_connect (const char *host, int port)
                                break;
                        }
 
+#ifndef PLATFORM_WIN32
+                       /*
+                        * this function is not present on win2000 which we still support, and the
+                        * workaround described here:
+                        * http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx
+                        * only works with MSVC.
+                        */
                        freeaddrinfo (result);
+#endif
                }
 
                DEBUG (1, fprintf (log_file, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout));
@@ -994,7 +1004,10 @@ transport_connect (const char *host, int port)
 
                conn_fd = sfd;
 
+#ifndef PLATFORM_WIN32
+               /* See the comment above */
                freeaddrinfo (result);
+#endif
 
                if (rp == 0) {
                        fprintf (stderr, "debugger-agent: Unable to connect to %s:%d\n", host, port);
@@ -3323,7 +3336,7 @@ process_breakpoint_inner (DebuggerTlsData *tls, MonoContext *ctx)
                        g_ptr_array_add (ss_reqs, req);
 
                /* Start single stepping again from the current sequence point */
-               ss_start (ss_req, ji->method, sp, info);
+               ss_start (ss_req, ji->method, sp, info, ctx, NULL);
        }
        
        if (ss_reqs->len > 0)
@@ -3685,10 +3698,10 @@ ss_stop (SingleStepReq *ss_req)
  *   Start the single stepping operation given by SS_REQ from the sequence point SP.
  */
 static void
-ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info)
+ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls)
 {
        gboolean use_bp = FALSE;
-       int i;
+       int i, frame_index;
        SeqPoint *next_sp;
        MonoBreakpoint *bp;
 
@@ -3699,7 +3712,25 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointI
         * Implement single stepping using breakpoints if possible.
         */
        if (ss_req->depth == STEP_DEPTH_OVER) {
-               if (sp->next_len > 0) {
+               frame_index = 1;
+               /*
+                * Find the first sequence point in the current or in a previous frame which
+                * is not the last in its method.
+                */
+               while (sp && sp->next_len == 0) {
+                       sp = NULL;
+                       if (tls && frame_index < tls->frame_count) {
+                               StackFrame *frame = tls->frames [frame_index];
+
+                               method = frame->method;
+                               if (frame->il_offset != -1) {
+                                       sp = find_seq_point (frame->domain, frame->method, frame->il_offset, &info);
+                               }
+                               frame_index ++;
+                       }
+               }
+
+               if (sp && sp->next_len > 0) {
                        use_bp = TRUE;
                        for (i = 0; i < sp->next_len; ++i) {
                                next_sp = &info->seq_points [sp->next [i]];
@@ -3794,7 +3825,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequ
                }
        }
 
-       ss_start (ss_req, method, sp, info);
+       ss_start (ss_req, method, sp, info, NULL, tls);
 
        return 0;
 }
@@ -3827,7 +3858,7 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *ctx)
                        char *ex_type = l->data;
                        char *f = mono_type_full_name (&exc->object.vtable->klass->byval_arg);
 
-                       if (!strcmp (ex_type, f))
+                       if (!strcmp (ex_type, "") || !strcmp (ex_type, f))
                                found = TRUE;
 
                        g_free (f);
@@ -4036,8 +4067,11 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8
        int err;
        int type = decode_byte (buf, &buf, limit);
 
-       if (type != t->type && !MONO_TYPE_IS_REFERENCE (t)) {
-               DEBUG(1, fprintf (log_file, "Expected value of type %d, got %d.\n", t->type, type));
+       if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
+               !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
+               !(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) &&
+               !(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8)) {
+               DEBUG(1, fprintf (log_file, "[%p] Expected value of type 0x%0x, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), t->type, type));
                return ERR_INVALID_ARGUMENT;
        }
 
@@ -4078,6 +4112,16 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8
        case MONO_TYPE_R8:
                *(guint64*)addr = decode_long (buf, &buf, limit);
                break;
+       case MONO_TYPE_PTR:
+               /* We send these as I8, so we get them back as such */
+               g_assert (type == MONO_TYPE_I8);
+               *(gssize*)addr = decode_long (buf, &buf, limit);
+               break;
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+               /* We send these as vtypes, so we get them back as such */
+               g_assert (type == MONO_TYPE_VALUETYPE);
+               /* Fall through */
        case MONO_TYPE_VALUETYPE: {
                gboolean is_enum = decode_byte (buf, &buf, limit);
                MonoClass *klass;