/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Threading.Tasks; using dnSpy.Contracts.Debugger.DotNet.Code; namespace dnSpy.Contracts.Debugger.DotNet.Steppers.Engine { /// /// .NET stepper /// public abstract class DbgDotNetEngineStepper { /// /// Max number of return values to save /// protected static readonly int maxReturnValues = 100; /// /// Session /// public abstract class SessionBase { /// /// Gets the tag /// public object? Tag { get; } /// /// Constructor /// /// Tag protected SessionBase(object? tag) => Tag = tag; } /// /// Gets/sets the session. It's null if there's no step operation in progress. /// public abstract SessionBase? Session { get; set; } /// /// Creates a new /// /// Tag /// public abstract SessionBase CreateSession(object? tag); /// /// true if the runtime is paused /// public abstract bool IsRuntimePaused { get; } /// /// Gets the countinue counter. It's incremented each time the process is continued. /// public abstract uint ContinueCounter { get; } /// /// Gets frame info or null if none is available /// /// Thread /// public abstract DbgDotNetEngineStepperFrameInfo? TryGetFrameInfo(DbgThread thread); /// /// Lets the process run /// public abstract void Continue(); /// /// Steps out /// /// Frame info /// public abstract Task StepOutAsync(DbgDotNetEngineStepperFrameInfo frame); /// /// Steps into /// /// Frame info /// Statement ranges /// public abstract Task StepIntoAsync(DbgDotNetEngineStepperFrameInfo frame, DbgCodeRange[] ranges); /// /// Steps over /// /// Frame info /// Statement ranges /// public abstract Task StepOverAsync(DbgDotNetEngineStepperFrameInfo frame, DbgCodeRange[] ranges); /// /// Cancels last step operation /// public abstract void CancelLastStep(); /// /// Prepares collecting return values /// /// Frame info /// Statement instructions public abstract void CollectReturnValues(DbgDotNetEngineStepperFrameInfo frame, DbgILInstruction[][] statementInstructions); /// /// Clears all return values /// public abstract void ClearReturnValues(); /// /// Creates a breakpoint /// /// Thread or null to match any thread /// Module /// Method token /// IL offset /// public abstract DbgDotNetStepperBreakpoint CreateBreakpoint(DbgThread? thread, DbgModule module, uint token, uint offset); /// /// Removes breakpoints /// /// Breakpoints to remove public abstract void RemoveBreakpoints(DbgDotNetStepperBreakpoint[] breakpoints); /// /// Called when the step is complete /// public abstract void OnStepComplete(); /// /// Called when it gets canceled /// /// Session public abstract void OnCanceled(SessionBase session); /// /// Returns true if the exception should be ignored eg. because the process has exited /// /// Thrown exception /// public abstract bool IgnoreException(Exception exception); /// /// Cleans up /// /// Dispatcher public abstract void Close(DbgDispatcher dispatcher); } /// /// A code breakpoint used by the .NET stepper /// public abstract class DbgDotNetStepperBreakpoint { /// /// Raised when the breakpoint is hit /// public abstract event EventHandler? Hit; } /// /// Stepper breakpoint event args /// public sealed class DbgDotNetStepperBreakpointEventArgs { /// /// Gets the thread /// public DbgThread Thread { get; } /// /// Set to true by the event handler to pause the process /// public bool Pause { get; set; } /// /// Constructor /// /// Current thread public DbgDotNetStepperBreakpointEventArgs(DbgThread thread) => Thread = thread ?? throw new ArgumentNullException(nameof(thread)); } }