Skip to content

Commit

Permalink
Steping into, steping over, steping out implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
liiir1985 committed Oct 28, 2016
1 parent bee6b66 commit 1fcae59
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 59 deletions.
20 changes: 19 additions & 1 deletion Debugging/ILRuntimeDebugEngine/AD7/AD7Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Microsoft.VisualStudio.Debugger.Interop;
using System.Runtime.InteropServices;

using ILRuntime.Runtime.Debugger;

namespace ILRuntimeDebugEngine.AD7
{
[ComVisible(true)]
Expand Down Expand Up @@ -134,7 +136,23 @@ public int GetProgramId(out Guid pguidProgramId)

public int Step(IDebugThread2 pThread, enum_STEPKIND sk, enum_STEPUNIT Step)
{
throw new NotImplementedException();
uint threadHash;
pThread.GetThreadId(out threadHash);
StepTypes type = StepTypes.None;
switch (sk)
{
case enum_STEPKIND.STEP_INTO:
type = StepTypes.Into;
break;
case enum_STEPKIND.STEP_OVER:
type = StepTypes.Over;
break;
case enum_STEPKIND.STEP_OUT:
type = StepTypes.Out;
break;
}
debugged.SendStep((int)threadHash, type);
return Constants.S_OK;
}

public int Terminate()
Expand Down
4 changes: 4 additions & 0 deletions Debugging/ILRuntimeDebugEngine/AD7/AD7Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

namespace ILRuntimeDebugEngine.AD7
{
internal sealed class AD7StepCompleteEvent : AD7StoppingEvent, IDebugStepCompleteEvent2
{
public const string IID = "0f7f24c1-74d9-4ea6-a3ea-7edb2d81441d";
}
// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread is created in a program being debugged.
internal sealed class AD7ThreadCreateEvent : AD7AsynchronousEvent, IDebugThreadCreateEvent2
{
Expand Down
117 changes: 79 additions & 38 deletions Debugging/ILRuntimeDebugEngine/AD7/DebuggedProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,47 +113,20 @@ void OnReceiveMessage(DebugMessageType type, byte[] buffer)
SCBreakpointHit msg = new SCBreakpointHit();
msg.BreakpointHashCode = br.ReadInt32();
msg.ThreadHashCode = br.ReadInt32();
int len = br.ReadInt32();
msg.StackFrame = new KeyValuePair<int, StackFrameInfo[]>[len];
for (int i = 0; i < len; i++)
{
int key = br.ReadInt32();
int cnt = br.ReadInt32();
StackFrameInfo[] arr = new StackFrameInfo[cnt + 1];
for (int j = 0; j < cnt; j++)
{
StackFrameInfo info = new StackFrameInfo();
info.MethodName = br.ReadString();
info.DocumentName = br.ReadString();
info.StartLine = br.ReadInt32();
info.StartColumn = br.ReadInt32();
info.EndLine = br.ReadInt32();
info.EndColumn = br.ReadInt32();
int vcnt = br.ReadInt32();
info.LocalVariables = new VariableInfo[vcnt];
for(int k = 0; k < vcnt; k++)
{
VariableInfo vinfo = new VariableInfo();
vinfo.Address = br.ReadInt64();
vinfo.Type = (VariableTypes)br.ReadByte();
vinfo.Offset = br.ReadInt32();
vinfo.Name = br.ReadString();
vinfo.Value = br.ReadString();
vinfo.TypeName = br.ReadString();
vinfo.Expandable = br.ReadBoolean();
info.LocalVariables[k] = vinfo;
}
arr[j] = info;
}
arr[cnt] = new StackFrameInfo()
{
MethodName = "Transition to Native methods"
};
msg.StackFrame[i] = new KeyValuePair<int, StackFrameInfo[]>(key, arr);
}
msg.StackFrame = ReadStackFrames(br);

OnReceiveSCBreakpointHit(msg);
}
break;

case DebugMessageType.SCStepComplete:
{
SCStepComplete msg = new SCStepComplete();
msg.ThreadHashCode = br.ReadInt32();
msg.StackFrame = ReadStackFrames(br);
OnReceiveSCStepComplete(msg);
}
break;
case DebugMessageType.SCThreadStarted:
{
SCThreadStarted msg = new SCThreadStarted();
Expand Down Expand Up @@ -181,6 +154,49 @@ void OnReceiveMessage(DebugMessageType type, byte[] buffer)
}
}

KeyValuePair<int, StackFrameInfo[]>[] ReadStackFrames(System.IO.BinaryReader br)
{
int len = br.ReadInt32();
KeyValuePair<int, StackFrameInfo[]>[] res = new KeyValuePair<int, StackFrameInfo[]>[len];
for (int i = 0; i < len; i++)
{
int key = br.ReadInt32();
int cnt = br.ReadInt32();
StackFrameInfo[] arr = new StackFrameInfo[cnt + 1];
for (int j = 0; j < cnt; j++)
{
StackFrameInfo info = new StackFrameInfo();
info.MethodName = br.ReadString();
info.DocumentName = br.ReadString();
info.StartLine = br.ReadInt32();
info.StartColumn = br.ReadInt32();
info.EndLine = br.ReadInt32();
info.EndColumn = br.ReadInt32();
int vcnt = br.ReadInt32();
info.LocalVariables = new VariableInfo[vcnt];
for (int k = 0; k < vcnt; k++)
{
VariableInfo vinfo = new VariableInfo();
vinfo.Address = br.ReadInt64();
vinfo.Type = (VariableTypes)br.ReadByte();
vinfo.Offset = br.ReadInt32();
vinfo.Name = br.ReadString();
vinfo.Value = br.ReadString();
vinfo.TypeName = br.ReadString();
vinfo.Expandable = br.ReadBoolean();
info.LocalVariables[k] = vinfo;
}
arr[j] = info;
}
arr[cnt] = new StackFrameInfo()
{
MethodName = "Transition to Native methods"
};
res[i] = new KeyValuePair<int, StackFrameInfo[]>(key, arr);
}

return res;
}
public void AddPendingBreakpoint(AD7PendingBreakPoint bp)
{
breakpoints[bp.GetHashCode()] = bp;
Expand Down Expand Up @@ -211,6 +227,14 @@ public void SendExecute(int threadHash)
socket.Send(DebugMessageType.CSExecute, sendStream.GetBuffer(), (int)sendStream.Position);
}

public void SendStep(int threadHash, StepTypes type)
{
sendStream.Position = 0;
bw.Write(threadHash);
bw.Write((byte)type);
socket.Send(DebugMessageType.CSStep, sendStream.GetBuffer(), (int)sendStream.Position);
}

void OnReceivSendSCBindBreakpointResult(SCBindBreakpointResult msg)
{
AD7PendingBreakPoint bp;
Expand Down Expand Up @@ -253,6 +277,23 @@ void OnReceiveSCBreakpointHit(SCBreakpointHit msg)
}
}

void OnReceiveSCStepComplete(SCStepComplete msg)
{
AD7Thread t, bpThread = null;

foreach (var i in msg.StackFrame)
{
if (threads.TryGetValue(i.Key, out t))
{
t.StackFrames = i.Value;
if (i.Key == msg.ThreadHashCode)
bpThread = t;
}
}
if (bpThread != null)
engine.Callback.StepCompleted(bpThread);

}
void OnReceiveSCThreadStarted(SCThreadStarted msg)
{
AD7Thread t = new AD7Thread(engine, msg.ThreadHashCode);
Expand Down
8 changes: 4 additions & 4 deletions Debugging/ILRuntimeDebugEngine/AD7/EngineCallback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ internal void ThreadEnded(AD7Thread thread)
AD7AsynchronousEvent.Attributes);
}

/*internal void StepCompleted(AD7Thread thread)
internal void StepCompleted(AD7Thread thread)
{
var iid = new Guid(Microsoft.MIDebugEngine.AD7StepCompleteEvent.IID);
_eventCallback.Event(_engine, _engine.RemoteProcess, _engine, thread, new Microsoft.MIDebugEngine.AD7StepCompleteEvent(), ref iid,
var iid = new Guid(AD7StepCompleteEvent.IID);
_eventCallback.Event(_engine, _engine.RemoteProcess, _engine, thread, new AD7StepCompleteEvent(), ref iid,
AD7StoppingEvent.Attributes);
}

public void OnError(string message)
/*public void OnError(string message)
{
SendMessage(message, OutputMessage.Severity.Error, isAsync: true);
}
Expand Down
3 changes: 3 additions & 0 deletions ILRuntime/ILRuntime.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@
<Compile Include="Runtime\Debugger\DebuggerServer\DebuggerServer.cs" />
<Compile Include="Runtime\Debugger\DebugMessageType.cs" />
<Compile Include="Runtime\Debugger\DebugSocket.cs" />
<Compile Include="Runtime\Debugger\Protocol\CSStep.cs" />
<Compile Include="Runtime\Debugger\Protocol\CSExecute.cs" />
<Compile Include="Runtime\Debugger\Protocol\CSDeleteBreakpoint.cs" />
<Compile Include="Runtime\Debugger\Protocol\CSBindBreakpoint.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCStepComplete.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCThreadStarted.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCBreakpointHit.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCModuleLoaded.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCBindBreakpointResult.cs" />
<Compile Include="Runtime\Debugger\Protocol\SCAttachResult.cs" />
<Compile Include="Runtime\Debugger\StepTypes.cs" />
<Compile Include="Runtime\Debugger\VariableInfo.cs" />
<Compile Include="Runtime\Debugger\StackFrameInfo.cs" />
<Compile Include="Runtime\Enviorment\CrossBindingAdaptor.cs" />
Expand Down
2 changes: 2 additions & 0 deletions ILRuntime/Runtime/Debugger/DebugMessageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ public enum DebugMessageType
SCBreakpointHit,
CSDeleteBreakpoint,
CSExecute,
CSStep,
SCStepComplete,
}
}
84 changes: 71 additions & 13 deletions ILRuntime/Runtime/Debugger/DebugService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,20 +235,39 @@ internal void ExecuteThread(int threadHash)
foreach(var i in AppDomain.Intepreters)
{
//We should resume all threads on execute
i.Value.ShouldBreak = false;
i.Value.ClearDebugState();
i.Value.Resume();
}
}
}

internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip)
internal unsafe void StepThread(int threadHash, StepTypes type)
{
lock (AppDomain.FreeIntepreters)
{
ILIntepreter intp;
if(AppDomain.Intepreters.TryGetValue(threadHash, out intp))
{
intp.ClearDebugState();
intp.CurrentStepType = type;
intp.LastStepFrameBase = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().BasePointer : (StackObject*)0;
intp.LastStepInstructionIndex = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().Address.Value : 0;

intp.Resume();
}
}
}

unsafe internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip)
{
if (server != null && server.IsAttached)
{
int methodHash = method.GetHashCode();
lock (activeBreakpoints)
{
LinkedList<BreakpointInfo> lst;
bool bpHit = false;

if (activeBreakpoints.TryGetValue(methodHash, out lst))
{
var sp = method.Definition.Body.Instructions[ip].SequencePoint;
Expand All @@ -258,28 +277,66 @@ internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip)
{
if ((i.StartLine + 1) == sp.StartLine)
{
KeyValuePair<int, StackFrameInfo[]>[] frames = new KeyValuePair<int, StackFrameInfo[]>[AppDomain.Intepreters.Count];
frames[0] = new KeyValuePair<int, StackFrameInfo[]>(intp.GetHashCode(), GetStackFrameInfo(intp));
int idx = 1;
foreach(var j in AppDomain.Intepreters)
DoBreak(intp, i.BreakpointHashCode, false);
bpHit = true;
break;
}
}
}
}

if (!bpHit)
{
var sp = method.Definition.Body.Instructions[ip].SequencePoint;
if (sp != null)
{
switch (intp.CurrentStepType)
{
case StepTypes.Into:
DoBreak(intp, 0, true);
break;
case StepTypes.Over:
if (intp.Stack.Frames.Peek().BasePointer == intp.LastStepFrameBase && ip != intp.LastStepInstructionIndex)
{
if(j.Value != intp)
DoBreak(intp, 0, true);
}
break;
case StepTypes.Out:
{
if (intp.Stack.Frames.Count > 0 && intp.Stack.Frames.Peek().BasePointer < intp.LastStepFrameBase)
{
j.Value.ShouldBreak = true;
frames[idx++] = new KeyValuePair<int, Debugger.StackFrameInfo[]>(j.Value.GetHashCode(), GetStackFrameInfo(j.Value));
DoBreak(intp, 0, true);
}
}
server.SendSCBreakpointHit(intp.GetHashCode(), i.BreakpointHashCode, frames);
//Breakpoint hit
intp.Break();
}
break;
}
}
}
}
}
}

void DoBreak(ILIntepreter intp, int bpHash, bool isStep)
{
KeyValuePair<int, StackFrameInfo[]>[] frames = new KeyValuePair<int, StackFrameInfo[]>[AppDomain.Intepreters.Count];
frames[0] = new KeyValuePair<int, StackFrameInfo[]>(intp.GetHashCode(), GetStackFrameInfo(intp));
int idx = 1;
foreach (var j in AppDomain.Intepreters)
{
if (j.Value != intp)
{
j.Value.ShouldBreak = true;
frames[idx++] = new KeyValuePair<int, Debugger.StackFrameInfo[]>(j.Value.GetHashCode(), GetStackFrameInfo(j.Value));
}
}
if (!isStep)
server.SendSCBreakpointHit(intp.GetHashCode(), bpHash, frames);
else
server.SendSCStepComplete(intp.GetHashCode(), frames);
//Breakpoint hit
intp.Break();
}

unsafe StackFrameInfo[] GetStackFrameInfo(ILIntepreter intp)
{
StackFrame[] frames = intp.Stack.Frames.ToArray();
Expand Down Expand Up @@ -410,6 +467,7 @@ internal void Detach()
breakpointMapping.Clear();
foreach (var j in AppDomain.Intepreters)
{
j.Value.ClearDebugState();
j.Value.Resume();
}
}
Expand Down
Loading

0 comments on commit 1fcae59

Please sign in to comment.