|
|
|
@ -9,6 +9,7 @@ using System.Threading;
@@ -9,6 +9,7 @@ using System.Threading;
|
|
|
|
|
|
|
|
|
|
using DebuggerInterop.Core; |
|
|
|
|
using DebuggerInterop.MetaData; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DebuggerLibrary |
|
|
|
@ -146,30 +147,23 @@ namespace DebuggerLibrary
@@ -146,30 +147,23 @@ namespace DebuggerLibrary
|
|
|
|
|
ICorDebugStepper stepper; |
|
|
|
|
corFrame.CreateStepper(out stepper); |
|
|
|
|
|
|
|
|
|
//uint rangeCount;
|
|
|
|
|
//symMethod.GetRanges(nextSt.SymbolDocument, nextSt.StartLine, 0, 0, out rangeCount, IntPtr.Zero);
|
|
|
|
|
//IntPtr pRanges = Marshal.AllocHGlobal(4*(int)rangeCount);
|
|
|
|
|
//symMethod.GetRanges(nextSt.SymbolDocument, nextSt.StartLine, 0, rangeCount, out rangeCount, pRanges);
|
|
|
|
|
|
|
|
|
|
int[] ranges = symMethod.GetRanges(nextSt.SymbolDocument, nextSt.StartLine, 0); |
|
|
|
|
IntPtr pRanges = Marshal.AllocHGlobal(4*ranges.Length); |
|
|
|
|
for (int i = 0; i < ranges.Length; i++) { |
|
|
|
|
((int*)pRanges.ToPointer())[i] = ranges[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stepper.StepRange(stepIn?1:0, pRanges, (uint)ranges.Length); |
|
|
|
|
Marshal.FreeHGlobal(pRanges); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fixed (int* ranges = nextSt.StepRanges) { |
|
|
|
|
stepper.StepRange(stepIn?1:0, (IntPtr)ranges, (uint)nextSt.StepRanges.Length / 2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
NDebugger.Continue(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get the information about the next statement to be executed.
|
|
|
|
|
///
|
|
|
|
|
/// Throws NextStatementNotAviableException on error.
|
|
|
|
|
///
|
|
|
|
|
/// 'ILStart <= ILOffset <= ILEnd' and this range includes at least
|
|
|
|
|
/// the returned area of source code. (May incude some extra compiler generated IL too)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public SourcecodeSegment NextStatement { |
|
|
|
|
get { |
|
|
|
|
SourcecodeSegment retVal = new SourcecodeSegment(); |
|
|
|
|
|
|
|
|
|
ISymbolMethod symMethod; |
|
|
|
|
try { |
|
|
|
|
symMethod = this.symMethod; |
|
|
|
@ -201,23 +195,74 @@ namespace DebuggerLibrary
@@ -201,23 +195,74 @@ namespace DebuggerLibrary
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
uint corInstructionPtr = this.corInstructionPtr; // cache
|
|
|
|
|
SourcecodeSegment retVal = new SourcecodeSegment(); |
|
|
|
|
|
|
|
|
|
// Get i for which: offsets[i] <= corInstructionPtr < offsets[i + 1]
|
|
|
|
|
for (int i = sequencePointCount - 1; i >= 0; i--) // backwards
|
|
|
|
|
if (offsets[i] <= corInstructionPtr) |
|
|
|
|
{ |
|
|
|
|
// Set inforamtion about current IL range
|
|
|
|
|
ICorDebugCode code; |
|
|
|
|
corFunction.GetILCode(out code); |
|
|
|
|
uint codeSize; |
|
|
|
|
code.GetSize(out codeSize); |
|
|
|
|
|
|
|
|
|
retVal.ILOffset = (int)corInstructionPtr; |
|
|
|
|
retVal.ILStart = offsets[i]; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? offsets[i + 1] : (int)codeSize; |
|
|
|
|
|
|
|
|
|
// 0xFeeFee means "code generated by compiler"
|
|
|
|
|
if (startLine[i] == 0xFeeFee) throw new NextStatementNotAviableException(); |
|
|
|
|
// If we are in generated sequence use to closest real one instead,
|
|
|
|
|
// extend the ILStart and ILEnd to include the 'real' sequence
|
|
|
|
|
|
|
|
|
|
retVal.SymbolDocument = Doc[i]; |
|
|
|
|
// Look ahead for 'real' sequence
|
|
|
|
|
while (i + 1 < sequencePointCount && startLine[i] == 0xFeeFee) { |
|
|
|
|
i++; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? offsets[i + 1] : (int)codeSize; |
|
|
|
|
} |
|
|
|
|
// Look back for 'real' sequence
|
|
|
|
|
while (i - 1 >= 0 && startLine[i] == 0xFeeFee) { |
|
|
|
|
i--; |
|
|
|
|
retVal.ILStart = offsets[i]; |
|
|
|
|
} |
|
|
|
|
// Wow, there are no 'real' sequences
|
|
|
|
|
if (startLine[i] == 0xFeeFee) { |
|
|
|
|
throw new NextStatementNotAviableException(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
retVal.SourceFullFilename = retVal.SymbolDocument.URL; |
|
|
|
|
|
|
|
|
|
retVal.ModuleFilename = module.FullPath; |
|
|
|
|
|
|
|
|
|
retVal.StartLine = startLine[i]; |
|
|
|
|
retVal.SymbolDocument = Doc[i]; |
|
|
|
|
retVal.SourceFullFilename = Doc[i].URL; |
|
|
|
|
|
|
|
|
|
retVal.StartLine = startLine[i]; |
|
|
|
|
retVal.StartColumn = startColumn[i]; |
|
|
|
|
retVal.EndLine = endLine[i]; |
|
|
|
|
retVal.EndColumn = endColumn[i]; |
|
|
|
|
retVal.EndLine = endLine[i]; |
|
|
|
|
retVal.EndColumn = endColumn[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> stepRanges = new List<int>(); |
|
|
|
|
for (int j = 0; j < sequencePointCount; j++) { |
|
|
|
|
// Step over compiler generated sequences and current statement
|
|
|
|
|
// 0xFeeFee means "code generated by compiler"
|
|
|
|
|
if (startLine[j] == 0xFeeFee || j == i) { |
|
|
|
|
// Add start offset or remove last end (to connect two ranges into one)
|
|
|
|
|
if (stepRanges.Count > 0 && stepRanges[stepRanges.Count - 1] == offsets[j]) { |
|
|
|
|
stepRanges.RemoveAt(stepRanges.Count - 1); |
|
|
|
|
} else { |
|
|
|
|
stepRanges.Add(offsets[j]); |
|
|
|
|
} |
|
|
|
|
// Add end offset | handle last sequence point
|
|
|
|
|
if (j + 1 < sequencePointCount) { |
|
|
|
|
stepRanges.Add(offsets[j + 1]); |
|
|
|
|
} else { |
|
|
|
|
stepRanges.Add((int)codeSize); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
retVal.StepRanges = stepRanges.ToArray(); |
|
|
|
|
|
|
|
|
|
return retVal; |
|
|
|
|
} |
|
|
|
|
throw new NextStatementNotAviableException(); |
|
|
|
|