diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs index 928b15a683..8ec6a7108d 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs @@ -319,12 +319,19 @@ namespace ICSharpCode.SharpDevelop.Services public void JumpToCurrentLine() { + //StatusBarService.SetMessage("Source code not aviable!"); try { if (selectedFunction == null) { return; } SourcecodeSegment nextStatement = selectedFunction.NextStatement; DebuggerService.JumpToCurrentLine(nextStatement.SourceFullFilename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn); + + string stepRanges = ""; + foreach (int i in nextStatement.StepRanges) { + stepRanges += i.ToString("X") + " "; + } + //StatusBarService.SetMessage("IL:" + nextStatement.ILOffset.ToString("X") + " StepRange:" + stepRanges + " "); } catch (NextStatementNotAviableException) { System.Diagnostics.Debug.Fail("Source code not aviable!"); } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs index cff3da796e..a8dcee980d 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs @@ -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 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(); } - + /// + /// 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) + /// public SourcecodeSegment NextStatement { get { - SourcecodeSegment retVal = new SourcecodeSegment(); - ISymbolMethod symMethod; try { symMethod = this.symMethod; @@ -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 stepRanges = new List(); + 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(); diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/SourcecodeSegment.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/SourcecodeSegment.cs index 72f9db0863..7be1ca224b 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/SourcecodeSegment.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/SourcecodeSegment.cs @@ -15,6 +15,10 @@ namespace DebuggerLibrary int startColumn; int endLine; int endColumn; + int ilOffset; + int ilStart; + int ilEnd; + int[] stepRanges; ISymbolDocument symUnmanagedDocument; public string ModuleFilename { @@ -85,5 +89,41 @@ namespace DebuggerLibrary symUnmanagedDocument = value; } } + + public int[] StepRanges { + get { + return stepRanges; + } + set { + stepRanges = value; + } + } + + public int ILOffset { + get { + return ilOffset; + } + set { + ilOffset = value; + } + } + + public int ILStart { + get { + return ilStart; + } + set { + ilStart = value; + } + } + + public int ILEnd { + get { + return ilEnd; + } + set { + ilEnd = value; + } + } } }