Skip to content

Commit

Permalink
[sdb] Fix step-over with recursive functions. Fixes #5700.
Browse files Browse the repository at this point in the history
  • Loading branch information
vargaz committed Nov 30, 2013
1 parent e21dc7c commit a102401
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
8 changes: 8 additions & 0 deletions mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
Expand Up @@ -360,6 +360,7 @@ public static void wait_one ()
ss_nested ();
ss_regress_654694 ();
ss_step_through ();
ss_recursive (1);
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
Expand Down Expand Up @@ -477,6 +478,13 @@ class StepThroughClass {
public static void step_through_3 () {
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static void ss_recursive (int n) {
if (n == 10)
return;
ss_recursive (n + 1);
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static bool is_even (int i) {
return i % 2 == 0;
Expand Down
12 changes: 12 additions & 0 deletions mcs/class/Mono.Debugger.Soft/Test/dtest.cs
Expand Up @@ -541,6 +541,18 @@ public class DebuggerTests
e = step_into ();
assert_location (e, "step_through_3");
req.Disable ();

// Check that step-over doesn't stop at inner frames with recursive functions
e = run_until ("ss_recursive");
req = create_step (e);
e = step_over ();
e = step_over ();
e = step_over ();
var f = e.Thread.GetFrames () [0];
assert_location (e, "ss_recursive");
AssertValue (1, f.GetValue (f.Method.GetLocal ("n")));

req.Disable ();
}

[Test]
Expand Down
21 changes: 18 additions & 3 deletions mono/mini/debugger-agent.c
Expand Up @@ -559,6 +559,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;

/*
Expand Down Expand Up @@ -4461,7 +4463,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;
Expand All @@ -4476,6 +4478,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;

Expand Down Expand Up @@ -4597,7 +4610,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);

Expand Down Expand Up @@ -4814,7 +4827,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 */
Expand Down Expand Up @@ -5061,6 +5074,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];
Expand Down

0 comments on commit a102401

Please sign in to comment.