Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mono / mini / debugger-agent.c
old mode 100755 (executable)
new mode 100644 (file)
index 01ea5eb..e5c40fd
@@ -125,6 +125,7 @@ typedef struct {
        gboolean embedding;
        gboolean defer;
        int keepalive;
+       gboolean setpgid;
 } AgentConfig;
 
 typedef struct
@@ -559,6 +560,8 @@ typedef struct {
        gboolean global;
        /* The list of breakpoints used to implement step-over */
        GSList *bps;
+       /* The number of frames at the start of a step-over */
+       int nframes;
 } SingleStepReq;
 
 /*
@@ -799,6 +802,7 @@ print_usage (void)
        fprintf (stderr, "  timeout=<n>\t\t\tTimeout for connecting in milliseconds.\n");
        fprintf (stderr, "  server=y/n\t\t\tWhether to listen for a client connection.\n");
        fprintf (stderr, "  keepalive=<n>\t\t\tSend keepalive events every n milliseconds.\n");
+       fprintf (stderr, "  setpgid=y/n\t\t\tWhether to call setpid(0, 0) after startup.\n");
        fprintf (stderr, "  help\t\t\t\tPrint this help.\n");
 }
 
@@ -873,6 +877,8 @@ mono_debugger_agent_parse_options (char *options)
                        agent_config.embedding = atoi (arg + 10) == 1;
                } else if (strncmp (arg, "keepalive=", 10) == 0) {
                        agent_config.keepalive = atoi (arg + 10);
+               } else if (strncmp (arg, "setpgid=", 8) == 0) {
+                       agent_config.setpgid = parse_flag ("setpgid", arg + 8);
                } else {
                        print_usage ();
                        exit (1);
@@ -986,6 +992,11 @@ mono_debugger_agent_init (void)
         */
        mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE;
 
+#ifdef HAVE_SETPGID
+       if (agent_config.setpgid)
+               setpgid (0, 0);
+#endif
+
        if (!agent_config.onuncaught && !agent_config.onthrow)
                finish_agent_init (TRUE);
 }
@@ -1565,9 +1576,7 @@ stop_debugger_thread (void)
 static void
 start_debugger_thread (void)
 {
-       gsize tid;
-
-       debugger_thread_handle = mono_create_thread (NULL, 0, debugger_thread, NULL, 0, &tid);
+       debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, 0, 0, NULL);
        g_assert (debugger_thread_handle);
 }
 
@@ -4461,7 +4470,7 @@ clear_breakpoints_for_domain (MonoDomain *domain)
  * Return FALSE if single stepping needs to continue.
  */
 static gboolean
-ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp)
+ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *tls, MonoContext *ctx)
 {
        MonoDebugMethodInfo *minfo;
        MonoDebugSourceLocation *loc = NULL;
@@ -4476,6 +4485,17 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp)
                return FALSE;
        }
 
+       if (req->depth == STEP_DEPTH_OVER && hit) {
+               if (!tls->context.valid)
+                       mono_thread_state_init_from_monoctx (&tls->context, ctx);
+               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 (1, fprintf (log_file, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ()));
+                       return FALSE;
+               }
+       }
+
        if (req->size != STEP_SIZE_LINE)
                return TRUE;
 
@@ -4597,7 +4617,7 @@ process_breakpoint_inner (DebuggerTlsData *tls)
                if (mono_thread_internal_current () != ss_req->thread)
                        continue;
 
-               hit = ss_update (ss_req, ji, sp);
+               hit = ss_update (ss_req, ji, sp, tls, ctx);
                if (hit)
                        g_ptr_array_add (ss_reqs, req);
 
@@ -4814,7 +4834,7 @@ process_single_step_inner (DebuggerTlsData *tls)
                return;
        il_offset = sp->il_offset;
 
-       if (!ss_update (ss_req, ji, sp))
+       if (!ss_update (ss_req, ji, sp, tls, ctx))
                return;
 
        /* Start single stepping again from the current sequence point */
@@ -5061,6 +5081,8 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointI
                }
 
                if (ss_req->depth == STEP_DEPTH_OVER) {
+                       if (ss_req->nframes == 0)
+                               ss_req->nframes = tls->frame_count;
                        /* Need to stop in catch clauses as well */
                        for (i = 0; i < tls->frame_count; ++i) {
                                StackFrame *frame = tls->frames [i];
@@ -5996,6 +6018,16 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                mgreg_t v;
                gboolean is_signed = FALSE;
 
+               if (t->byref) {
+                       addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+
+                       if (addr) {
+                               // FIXME: Write barriers
+                               mono_gc_memmove (addr, val, size);
+                       }
+                       break;
+               }
+
                if (!t->byref && (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2 || t->type == MONO_TYPE_I4 || t->type == MONO_TYPE_I8))
                        is_signed = TRUE;
 
@@ -6016,9 +6048,6 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                        g_assert_not_reached ();
                }
 
-               if (t->byref)
-                       NOT_IMPLEMENTED;
-
                /* Set value on the stack or in the return ctx */
                if (reg_locations [reg]) {
                        /* Saved on the stack */