private void OnStepTargetBreakpoint(DkmThread thread) { if (_stepper == null) { Debug.Fail("OnStepTargetBreakpoint called but no step operation is in progress."); throw new InvalidOperationException(); } if (_stepper.StepKind == DkmStepKind.Into) { StepDone(thread).OnStepArbitration(DkmStepArbitrationReason.ExitRuntime, _process.GetPythonRuntimeInstance()); } else { // Just because we hit the return breakpoint doesn't mean that we've actually returned - it could be // a recursive call. Check stack depth to distinguish this from an actual return. var beginState = _stepper.GetDataItem <StepBeginState>(); if (beginState != null) { thread.GetCurrentFrameInfo(out global::System.UInt64 retAddr, out global::System.UInt64 frameBase, out global::System.UInt64 vframe); if (frameBase > beginState.FrameBase) { OnStepComplete(thread); } } } }
public void Step(DkmStepper stepper, DkmStepArbitrationReason reason) { var thread = stepper.Thread; var process = thread.Process; if (stepper.StepKind == DkmStepKind.StepIntoSpecific) { throw new NotSupportedException(); } else if (_stepper != null) { _stepper.CancelStepper(process.GetPythonRuntimeInstance()); _stepper = null; } // Check if this was a step out (or step over/in that fell through) from native to Python. // If so, we consider the step done, since we can report the correct callstack at this point. if (reason == DkmStepArbitrationReason.TransitionModule) { var beginState = stepper.GetDataItem <StepBeginState>(); if (beginState != null) { thread.GetCurrentFrameInfo(out global::System.UInt64 retAddr, out global::System.UInt64 frameBase, out global::System.UInt64 vframe); if (frameBase >= beginState.FrameBase) { stepper.OnStepComplete(thread, false); return; } } } if (stepper.StepKind == DkmStepKind.Into) { new LocalComponent.BeginStepInNotification { ThreadId = thread.UniqueId }.SendHigher(process); } _stepper = stepper; _stepKind.Write((int)stepper.StepKind + 1); _stepThreadId.Write((uint)thread.SystemPart.Id); _steppingStackDepth.Write(0); }