Skip to content

Commit

Permalink
implement reverse execution
Browse files Browse the repository at this point in the history
send CapabilitiesEvent after target launch to correctly signal StepBack support
introduce IDebugReversibleEngineProgram160 to properly handle execution direction like VS
  • Loading branch information
Trass3r committed Sep 6, 2020
1 parent 0b9ad84 commit a0c9fb8
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 52 deletions.
29 changes: 20 additions & 9 deletions src/MICore/CommandFactories/MICommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using System.Linq;
using System.Globalization;
using Microsoft.VisualStudio.Debugger.Interop;

namespace MICore
Expand Down Expand Up @@ -216,33 +213,43 @@ public async Task<ValueListValue> StackListVariables(PrintValues printValues, in

#region Program Execution

public async Task ExecStep(int threadId, ResultClass resultClass = ResultClass.running)
public async Task ExecStep(int threadId, bool forward = true, ResultClass resultClass = ResultClass.running)
{
string command = "-exec-step";
if (!forward)
command += " --reverse";
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}

public async Task ExecNext(int threadId, ResultClass resultClass = ResultClass.running)
public async Task ExecNext(int threadId, bool forward = true, ResultClass resultClass = ResultClass.running)
{
string command = "-exec-next";
if (!forward)
command += " --reverse";
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}

public async Task ExecFinish(int threadId, ResultClass resultClass = ResultClass.running)
public async Task ExecFinish(int threadId, bool forward = true, ResultClass resultClass = ResultClass.running)
{
string command = "-exec-finish";
if (!forward)
command += " --reverse";
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}

public async Task ExecStepInstruction(int threadId, ResultClass resultClass = ResultClass.running)
public async Task ExecStepInstruction(int threadId, bool forward = true, ResultClass resultClass = ResultClass.running)
{
string command = "-exec-step-instruction";
if (!forward)
command += " --reverse";
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}

public async Task ExecNextInstruction(int threadId, ResultClass resultClass = ResultClass.running)
public async Task ExecNextInstruction(int threadId, bool forward = true, ResultClass resultClass = ResultClass.running)
{
string command = "-exec-next-instruction";
if (!forward)
command += " --reverse";
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}

Expand All @@ -258,9 +265,11 @@ public virtual async Task ExecRun()
/// <summary>
/// Continues running the target process
/// </summary>
public async Task ExecContinue()
public async Task ExecContinue(bool forward = true)
{
string command = "-exec-continue";
if (!forward)
command += " --reverse";
await _debugger.CmdAsync(command, ResultClass.running);
}

Expand Down Expand Up @@ -661,6 +670,8 @@ public virtual bool CanDetach()
return true;
}

abstract public Task<string[]> GetTargetFeatures();

abstract public Task<List<ulong>> StartAddressesForLine(string file, uint line);

/// <summary>
Expand Down
9 changes: 6 additions & 3 deletions src/MICore/CommandFactories/clrdbg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using System.Linq;
using System.Globalization;
using Microsoft.VisualStudio.Debugger.Interop;

namespace MICore
{
internal class ClrdbgMICommandFactory : MICommandFactory
internal sealed class ClrdbgMICommandFactory : MICommandFactory
{
private readonly static Guid s_exceptionCategory_CLR = new Guid("449EC4CC-30D2-4032-9256-EE18EB41B62B");
private readonly static Guid s_exceptionCategory_MDA = new Guid("6ECE07A9-0EDE-45C4-8296-818D8FC401D4");
Expand Down Expand Up @@ -89,6 +87,11 @@ public override Task<List<ulong>> StartAddressesForLine(string file, uint line)
return Task.FromResult<List<ulong>>(null);
}

public override Task<string[]> GetTargetFeatures()
{
throw new NotImplementedException();
}

public override Task EnableTargetAsyncOption()
{
// clrdbg is always in target-async mode
Expand Down
12 changes: 7 additions & 5 deletions src/MICore/CommandFactories/gdb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using System.Linq;
using System.Globalization;

namespace MICore
{
internal class GdbMICommandFactory : MICommandFactory
internal sealed class GdbMICommandFactory : MICommandFactory
{
private int _currentThreadId = 0;
private uint _currentFrameLevel = 0;
Expand Down Expand Up @@ -183,6 +179,12 @@ public override async Task<List<ulong>> StartAddressesForLine(string file, uint
return addresses;
}

public override async Task<string[]> GetTargetFeatures()
{
Results results = await _debugger.CmdAsync("-list-target-features", ResultClass.done);
return results.Find<ValueListValue>("features").AsStrings;
}

public override Task EnableTargetAsyncOption()
{
// Linux attach TODO: GDB will fail this command when attaching. This is worked around
Expand Down
10 changes: 6 additions & 4 deletions src/MICore/CommandFactories/lldb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using System.Linq;
using System.Globalization;
using Microsoft.VisualStudio.Debugger.Interop;

namespace MICore
{
internal class LlldbMICommandFactory : MICommandFactory
internal sealed class LlldbMICommandFactory : MICommandFactory
{
public override string Name
{
Expand Down Expand Up @@ -119,6 +116,11 @@ public override Task EnableTargetAsyncOption()
return Task.FromResult((object)null);
}

public override Task<string[]> GetTargetFeatures()
{
throw new NotImplementedException();
}

public override string GetTargetArchitectureCommand()
{
return "platform status";
Expand Down
24 changes: 18 additions & 6 deletions src/MIDebugEngine/AD7.Impl/AD7Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.ExceptionServices;
using Microsoft.VisualStudio.Debugger.Interop;
using Microsoft.VisualStudio.Debugger.Interop.UnixPortSupplier;
using System.Diagnostics;
Expand Down Expand Up @@ -35,7 +33,7 @@ namespace Microsoft.MIDebugEngine

[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.Guid("0fc2f352-2fc1-4f80-8736-51cd1ab28f16")]
sealed public class AD7Engine : IDebugEngine2, IDebugEngineLaunch2, IDebugEngine3, IDebugProgram3, IDebugEngineProgram2, IDebugMemoryBytes2, IDebugEngine110, IDebugProgramDAP, IDebugMemoryBytesDAP, IDisposable
sealed public class AD7Engine : IDebugEngine2, IDebugEngineLaunch2, IDebugEngine3, IDebugProgram3, IDebugEngineProgram2, IDebugReversibleEngineProgram160, IDebugMemoryBytes2, IDebugEngine110, IDebugProgramDAP, IDebugMemoryBytesDAP, IDisposable
{
// used to send events to the debugger. Some examples of these events are thread create, exception thrown, module load.
private EngineCallback _engineCallback;
Expand Down Expand Up @@ -176,6 +174,7 @@ internal bool ProgramCreateEventSent
get;
private set;
}
public ExecuteDirection ExecutionDirection { get; private set; }

public string GetAddressDescription(ulong ip)
{
Expand Down Expand Up @@ -800,11 +799,11 @@ public int Continue(IDebugThread2 pThread)
{
if (_pollThread.IsPollThread())
{
_debuggedProcess.Continue(thread?.GetDebuggedThread());
_debuggedProcess.Continue(thread?.GetDebuggedThread(), ExecutionDirection);
}
else
{
_pollThread.RunOperation(() => _debuggedProcess.Continue(thread?.GetDebuggedThread()));
_pollThread.RunOperation(() => _debuggedProcess.Continue(thread?.GetDebuggedThread(), ExecutionDirection));
}
}
catch (InvalidCoreDumpOperationException)
Expand Down Expand Up @@ -995,7 +994,7 @@ public int Step(IDebugThread2 pThread, enum_STEPKIND kind, enum_STEPUNIT unit)
return Constants.E_FAIL;
}

_debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Step(thread.GetDebuggedThread().Id, kind, unit));
_debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Step(thread.GetDebuggedThread().Id, kind, unit, ExecutionDirection));
}
catch (InvalidCoreDumpOperationException)
{
Expand Down Expand Up @@ -1083,6 +1082,19 @@ public int WatchForThreadStep(IDebugProgram2 pOriginatingProgram, uint dwTid, in

#endregion

#region IDebugEngineProgram2 Members
int IDebugReversibleEngineProgram160.CanReverse()
{
return DebuggedProcess.TargetFeatures.Contains("reverse") ? Constants.S_OK : Constants.S_FALSE;
}

int IDebugReversibleEngineProgram160.SetExecuteDirection(ExecuteDirection ExecuteDirection)
{
ExecutionDirection = ExecuteDirection;
return Constants.S_OK;
}
#endregion

#region IDebugMemoryBytes2 Members

public int GetSize(out ulong pqwSize)
Expand Down
32 changes: 21 additions & 11 deletions src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -31,6 +30,7 @@ internal class DebuggedProcess : MICore.Debugger
public Disassembly Disassembly { get; private set; }
public ExceptionManager ExceptionManager { get; private set; }
public CygwinFilePathMapper CygwinFilePathMapper { get; private set; }
public string[] TargetFeatures { get; private set; }

private List<DebuggedModule> _moduleList;
private ISampleEngineCallback _callback;
Expand Down Expand Up @@ -618,6 +618,8 @@ public async Task Initialize(HostWaitLoop waitLoop, CancellationToken token)
}
}
}
// now the exe is loaded and we can check target features
TargetFeatures = await MICommandFactory.GetTargetFeatures();

success = true;
}
Expand Down Expand Up @@ -1597,10 +1599,16 @@ protected override void ScheduleResultProcessing(Action func)
_worker.PostOperation(() => { func(); });
}

public async Task Execute(DebuggedThread thread)
public async Task Execute(DebuggedThread thread, ExecuteDirection executionDirection = ExecuteDirection.ExecuteDirection_Forward)
{
await ExceptionManager.EnsureSettingsUpdated();

if (executionDirection == ExecuteDirection.ExecuteDirection_Reverse)
{
await MICommandFactory.ExecContinue(false);
return;
}

// Should clear stepping state
if (_worker.IsPollThread())
{
Expand All @@ -1612,30 +1620,32 @@ public async Task Execute(DebuggedThread thread)
}
}

public Task Continue(DebuggedThread thread)
public Task Continue(DebuggedThread thread, ExecuteDirection executionDirection = ExecuteDirection.ExecuteDirection_Forward)
{
// Called after Stopping event
return Execute(thread);
return Execute(thread, executionDirection);
}

public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit)
public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit, ExecuteDirection direction = ExecuteDirection.ExecuteDirection_Forward)
{
this.VerifyNotDebuggingCoreDump();

await ExceptionManager.EnsureSettingsUpdated();

// STEP_BACKWARDS is deprecated, use direction
bool isForwardStep = direction == ExecuteDirection.ExecuteDirection_Forward;
if ((unit == enum_STEPUNIT.STEP_LINE) || (unit == enum_STEPUNIT.STEP_STATEMENT))
{
switch (kind)
{
case enum_STEPKIND.STEP_INTO:
await MICommandFactory.ExecStep(threadId);
await MICommandFactory.ExecStep(threadId, isForwardStep);
break;
case enum_STEPKIND.STEP_OVER:
await MICommandFactory.ExecNext(threadId);
await MICommandFactory.ExecNext(threadId, isForwardStep);
break;
case enum_STEPKIND.STEP_OUT:
await MICommandFactory.ExecFinish(threadId);
await MICommandFactory.ExecFinish(threadId, isForwardStep);
break;
default:
throw new NotImplementedException();
Expand All @@ -1646,13 +1656,13 @@ public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit)
switch (kind)
{
case enum_STEPKIND.STEP_INTO:
await MICommandFactory.ExecStepInstruction(threadId);
await MICommandFactory.ExecStepInstruction(threadId, isForwardStep);
break;
case enum_STEPKIND.STEP_OVER:
await MICommandFactory.ExecNextInstruction(threadId);
await MICommandFactory.ExecNextInstruction(threadId, isForwardStep);
break;
case enum_STEPKIND.STEP_OUT:
await MICommandFactory.ExecFinish(threadId);
await MICommandFactory.ExecFinish(threadId, isForwardStep);
break;
default:
throw new NotImplementedException();
Expand Down
3 changes: 3 additions & 0 deletions src/MIDebugEngine/MIDebugEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
<Reference Include="Microsoft.VisualStudio.Debugger.Interop.15.0">
<HintPath>$(NuGetPackagesDirectory)/Microsoft.VisualStudio.Debugger.Interop.15.0.15.8.28010/lib/net20/Microsoft.VisualStudio.Debugger.Interop.15.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Debugger.Interop.16.0">
<HintPath>$(NuGetPackagesDirectory)/Microsoft.VisualStudio.Debugger.Interop.16.0.16.7.30328.139/lib/net20/Microsoft.VisualStudio.Debugger.Interop.16.0.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AD7.Definitions\AD7Guids.cs" />
Expand Down
4 changes: 4 additions & 0 deletions src/MakePIAPortable/MakePIAPortable.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
<Reference Include="Microsoft.VisualStudio.Debugger.Interop.15.0">
<HintPath>$(NuGetPackagesDirectory)/Microsoft.VisualStudio.Debugger.Interop.15.0.15.8.28010/lib/net20/Microsoft.VisualStudio.Debugger.Interop.15.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Debugger.Interop.16.0">
<HintPath>$(NuGetPackagesDirectory)/Microsoft.VisualStudio.Debugger.Interop.16.0.16.7.30328.139/lib/net20/Microsoft.VisualStudio.Debugger.Interop.16.0.dll</HintPath>
</Reference>
</ItemGroup>
<UsingTask TaskName="FindILDAsm" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
Expand Down Expand Up @@ -85,6 +88,7 @@
<DropSignedFile Include="$(PIAOutput)\Microsoft.VisualStudio.Debugger.Interop.11.0.dll" />
<DropSignedFile Include="$(PIAOutput)\Microsoft.VisualStudio.Debugger.Interop.12.0.dll" />
<DropSignedFile Include="$(PIAOutput)\Microsoft.VisualStudio.Debugger.Interop.15.0.dll" />
<DropSignedFile Include="$(PIAOutput)\Microsoft.VisualStudio.Debugger.Interop.16.0.dll" />
</ItemGroup>
<Target Name="CopyToVSCodeFolder" AfterTargets="DropFiles">
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions src/MakePIAPortable/MakePortableLegacyPIAs.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set pias=%pias% Microsoft.VisualStudio.Debugger.Interop.10.0.dll
set pias=%pias% Microsoft.VisualStudio.Debugger.Interop.11.0.dll
set pias=%pias% Microsoft.VisualStudio.Debugger.Interop.12.0.dll
set pias=%pias% Microsoft.VisualStudio.Debugger.Interop.15.0.dll
set pias=%pias% Microsoft.VisualStudio.Debugger.Interop.16.0.dll

set PIAERROR=
for %%i in (%pias%) do call :ProcessPIA %%i
Expand Down
Loading

0 comments on commit a0c9fb8

Please sign in to comment.