/// <summary> /// Perform a single step on the given thread. /// </summary> public Task StepAsync(StepRequest request) { // Set event lastStepRequest = request; var thread = request.Thread; var setTask = debugger.EventRequest.SetAsync(Jdwp.EventKind.SingleStep, Jdwp.SuspendPolicy.All, new EventStepModifier(thread.Id, Jdwp.StepSize.Line, request.StepDepth)); return(setTask.ContinueWith(t => { t.ForwardException(); // Record step StepManager.Add(new DalvikStep(thread, t.Result)); // Resume execution return debugger.VirtualMachine.ResumeAsync().ContinueWith(x => OnResumed()); }).Unwrap()); }
/// <summary> /// Perform the last step request again. /// </summary> private Task StepOutLastRequestAsync(StepRequest request) { if (request == null) return null; return StepAsync(new StepRequest(request.Thread, Jdwp.StepDepth.Out)); }
/// <summary> /// Perform a single step on the given thread. /// </summary> public Task StepAsync(StepRequest request) { var thread = request.Thread; var stepSize = request.StepMode == StepMode.SingleInstruction ? Jdwp.StepSize.Minimum : Jdwp.StepSize.Line; var setTask = debugger.EventRequest.SetAsync(Jdwp.EventKind.SingleStep, Jdwp.SuspendPolicy.All, new EventStepModifier(thread.Id, stepSize, request.StepDepth)); return setTask.ContinueWith(t => { t.ForwardException(); // Record step StepManager.Add(new DalvikStep(thread, t.Result, request)); // Resume execution return debugger.VirtualMachine.ResumeAsync().ContinueWith(x => OnResumed()); }).Unwrap(); }
/// <summary> /// Notify listeners that we're suspended. /// </summary> /// <param name="reason">The reason the VM is suspended</param> /// <param name="thread">The thread involved in the suspend. This can be null depending on the reason.</param> /// <param name="request">A step request, if any.</param> /// <returns>True if the suspend is performed, false if execution is continued.</returns> protected internal virtual bool OnSuspended(SuspendReason reason, DalvikThread thread, StepRequest request = null) { if (reason == SuspendReason.SingleStep && thread != null && request != null && request.Thread != null) { // Make sure we're are a location where we have a source. thread.OnProcessSuspended(reason, true); var topFrame = thread.GetCallStack().FirstOrDefault(); if (topFrame != null) { var location = topFrame.GetDocumentLocationAsync().Await(VmTimeout); if (location.SourceCode == null) { // Not my code StepOutLastRequestAsync(request); return false; } // check if we have a valid source code position, or if this is // compiler generated code (in which case dalvik will perform single stepping) if (request.StepMode != StepMode.SingleInstruction) { if (location.SourceCode == null || location.SourceCode.IsSpecial || location.Location.Index < (ulong)location.SourceCode.Position.MethodOffset) { var stepDepth = request.StepDepth == Jdwp.StepDepth.Out ? Jdwp.StepDepth.Over : request.StepDepth; StepAsync(new StepRequest(request.Thread, stepDepth, request.StepMode)); return false; } } } } ThreadManager.OnProcessSuspended(reason, thread); ReferenceTypeManager.OnProcessSuspended(reason); isSuspended = true; IsSuspendedChanged.Fire(this); return true; }
/// <summary> /// Notify listeners that we're suspended. /// </summary> protected override bool OnSuspended(SuspendReason reason, DalvikThread thread, StepRequest stepRequest) { var rc = base.OnSuspended(reason, thread, stepRequest); if (rc) { if (reason == SuspendReason.ProcessSuspend) { foreach (var threadx in ThreadManager.Threads) { eventCallback.Send(threadx, new ASyncBreakCompleteEvent()); } } if (reason == SuspendReason.SingleStep) { eventCallback.Send((DebugThread) thread, new StepCompleteEvent()); } } return rc; }