void Step_CorDebug(object tag, DbgEngineStepKind step) { engine.VerifyCorDebugThread(); if (stepData != null) { Debug.Fail("The previous step hasn't been canceled"); // No need to localize it, if we're here it's a bug RaiseStepComplete(thread, tag, "The previous step hasn't been canceled"); return; } var dbg = dnThread.Debugger; if (dbg.ProcessState != DebuggerProcessState.Paused) { Debug.Fail("Process is not paused"); // No need to localize it, if we're here it's a bug RaiseStepComplete(thread, tag, "Process is not paused"); return; } var frame = GetILFrame(); if (frame == null) { // No frame? Just let the process run. engine.Continue_CorDebug(); return; } CorStepper newCorStepper = null; switch (step) { case DbgEngineStepKind.StepInto: GetStepRanges(frame, tag, isStepInto: true); return; case DbgEngineStepKind.StepOver: GetStepRanges(frame, tag, isStepInto: false); return; case DbgEngineStepKind.StepOut: newCorStepper = dbg.StepOut(frame, (_, e) => StepCompleted(e, newCorStepper, tag, null)); break; default: RaiseStepComplete(thread, tag, $"Unsupported step kind: {step}"); return; } SaveStepper(newCorStepper, tag); }
void Step_MonoDebug(object tag, DbgEngineStepKind step) { engine.VerifyMonoDebugThread(); try { StepCore_MonoDebug(tag, step); } catch (VMDisconnectedException) { } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { RaiseStepComplete(thread, tag, $"Exception: {ex.GetType().FullName}: {ex.Message}"); } }
void StepCore_MonoDebug(object tag, DbgEngineStepKind step) { engine.VerifyMonoDebugThread(); if (stepData != null) { Debug.Fail("The previous step hasn't been canceled"); // No need to localize it, if we're here it's a bug RaiseStepComplete(thread, tag, "The previous step hasn't been canceled"); return; } if (!engine.IsPaused) { Debug.Fail("Process is not paused"); // No need to localize it, if we're here it's a bug RaiseStepComplete(thread, tag, "Process is not paused"); return; } switch (step) { case DbgEngineStepKind.StepInto: GetStepRanges(tag, isStepInto: true); return; case DbgEngineStepKind.StepOver: GetStepRanges(tag, isStepInto: false); return; case DbgEngineStepKind.StepOut: var stepReq = engine.CreateStepRequest(monoThread, e => OnStepOutCompleted(e, tag)); stepReq.Depth = StepDepth.Out; stepReq.Size = StepSize.Min; stepReq.Filter = GetStepFilterFlags(); stepReq.Enable(); SaveStepper(stepReq, tag, callRunCore: true); return; default: RaiseStepComplete(thread, tag, $"Unsupported step kind: {step}"); return; } }
void Step_DbgThread(DbgStepperImpl stepper, object stepperTag, DbgEngineStepKind step, bool singleProcess) { Dispatcher.VerifyAccess(); var infos = new List <EngineInfo>(); EngineInfo stepperEngineInfo = null; lock (lockObj) { var process = stepper.Process; var runtime = stepper.Runtime; foreach (var info in engines) { if (info.Runtime == runtime) { stepperEngineInfo = info; } if (info.Process == process || !singleProcess) { infos.Add(info); } } } if (stepperEngineInfo?.Process?.State != DbgProcessState.Paused) { RaiseStepperError_DbgThread(stepper, dnSpy_Debugger_Resources.ProcessIsNotPaused); return; } Debug.Assert(infos.Contains(stepperEngineInfo)); RunEngines_DbgThread(infos.ToArray(), info => { if (info == stepperEngineInfo) { stepper.EngineStepper.Step(stepperTag, step); } else { info.Engine.Run(); } }); }
/// <summary> /// Steps once. This method can be called again once <see cref="StepComplete"/> is raised. /// This method is only called if the engine is paused. /// </summary> /// <param name="tag">This value must be used when raising <see cref="StepComplete"/></param> /// <param name="step">Step kind</param> public abstract void Step(object tag, DbgEngineStepKind step);
internal void Step(DbgStepperImpl stepper, object stepperTag, DbgEngineStepKind step, bool singleProcess) => DbgThread(() => Step_DbgThread(stepper, stepperTag, step, singleProcess));
public override void Step(object tag, DbgEngineStepKind step) => engine.CorDebugThread(() => Step_CorDebug(tag, step));