gboolean embedding;
gboolean defer;
int keepalive;
+ gboolean setpgid;
} AgentConfig;
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;
/*
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");
}
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);
*/
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);
}
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);
}
* 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;
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;
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);
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 */
}
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];
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;
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 */