private SourcecodeSegment SetIP(bool simulate, string filename, int line, int column) { process.AssertPaused(); SourcecodeSegment segment = SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, filename, null, line, column); if (segment != null && segment.CorFunction.GetToken() == this.MethodInfo.MetadataToken) { try { if (simulate) { CorILFrame.CanSetIP((uint)segment.ILStart); } else { // Invalidates all frames and chains for the current thread CorILFrame.SetIP((uint)segment.ILStart); process.NotifyResumed(DebuggeeStateAction.Keep); process.NotifyPaused(PausedReason.SetIP); process.RaisePausedEvents(); } } catch { return(null); } return(segment); } return(null); }
private void AsyncStep(bool stepIn) { if (this.MethodInfo.DebugModule.HasSymbols == false) { throw new DebuggerException("Unable to step. No symbols loaded."); } SourcecodeSegment nextSt = NextStatement; if (nextSt == null) { throw new DebuggerException("Unable to step. Next statement not aviable"); } if (stepIn) { Stepper stepInStepper = Stepper.StepIn(this, nextSt.StepRanges, "normal"); this.Thread.CurrentStepIn = stepInStepper; Stepper clearCurrentStepIn = Stepper.StepOut(this, "clear current step in"); clearCurrentStepIn.StepComplete += delegate { if (this.Thread.CurrentStepIn == stepInStepper) { this.Thread.CurrentStepIn = null; } }; clearCurrentStepIn.Ignore = true; } else { Stepper.StepOver(this, nextSt.StepRanges, "normal"); } AsyncContinue(); }
public string GetStackTrace(string formatSymbols, string formatNoSymbols) { StringBuilder stackTrace = new StringBuilder(); foreach (StackFrame stackFrame in this.GetCallstack(100)) { SourcecodeSegment loc = stackFrame.NextStatement; stackTrace.Append(" "); if (loc != null) { stackTrace.AppendFormat(formatSymbols, stackFrame.MethodInfo.FullName, loc.Filename, loc.StartLine); } else { stackTrace.AppendFormat(formatNoSymbols, stackFrame.MethodInfo.FullName); } stackTrace.AppendLine(); } return(stackTrace.ToString()); }
internal bool SetBreakpoint(Module module) { SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column); if (segment == null) { return(false); } originalLocation = segment; ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(_enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); OnSet(new BreakpointEventArgs(this)); return(true); }
/// <summary> /// 'ILStart <= ILOffset <= ILEnd' and this range includes at least /// the returned area of source code. (May incude some extra compiler generated IL too) /// </summary> internal static SourcecodeSegment Resolve(Module module, ICorDebugFunction corFunction, int offset) { ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) { return(null); // No symbols } ISymUnmanagedMethod symMethod; try { symMethod = symReader.GetMethod(corFunction.GetToken()); } catch (COMException) { // Can not find the method // eg. Compiler generated constructors are not in symbol store return(null); } if (symMethod == null) { return(null); } uint sequencePointCount = symMethod.GetSequencePointCount(); SequencePoint[] sequencePoints = symMethod.GetSequencePoints(); // Get i for which: offsets[i] <= offset < offsets[i + 1] // or fallback to first element if offset < offsets[0] for (int i = (int)sequencePointCount - 1; i >= 0; i--) { // backwards if ((int)sequencePoints[i].Offset <= offset || i == 0) { // Set inforamtion about current IL range int codeSize = (int)corFunction.GetILCode().GetSize(); int ilStart = (int)sequencePoints[i].Offset; int ilEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i + 1].Offset : codeSize; // 0xFeeFee means "code generated by compiler" // If we are in generated sequence use to closest real one instead, // extend the ILStart and ILEnd to include the 'real' sequence // Look ahead for 'real' sequence while (i + 1 < sequencePointCount && sequencePoints[i].Line == 0xFeeFee) { i++; ilEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i + 1].Offset : codeSize; } // Look back for 'real' sequence while (i - 1 >= 0 && sequencePoints[i].Line == 0xFeeFee) { i--; ilStart = (int)sequencePoints[i].Offset; } // Wow, there are no 'real' sequences if (sequencePoints[i].Line == 0xFeeFee) { return(null); } 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 (sequencePoints[j].Line == 0xFeeFee || j == i) { // Add start offset or remove last end (to connect two ranges into one) if (stepRanges.Count > 0 && stepRanges[stepRanges.Count - 1] == sequencePoints[j].Offset) { stepRanges.RemoveAt(stepRanges.Count - 1); } else { stepRanges.Add((int)sequencePoints[j].Offset); } // Add end offset | handle last sequence point if (j + 1 < sequencePointCount) { stepRanges.Add((int)sequencePoints[j + 1].Offset); } else { stepRanges.Add(codeSize); } } } SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); segment.checkSum = sequencePoints[i].Document.GetCheckSum(); segment.startLine = (int)sequencePoints[i].Line; segment.startColumn = (int)sequencePoints[i].Column; segment.endLine = (int)sequencePoints[i].EndLine; segment.endColumn = (int)sequencePoints[i].EndColumn; segment.corFunction = corFunction; segment.ilStart = ilStart; segment.ilEnd = ilEnd; segment.stepRanges = stepRanges.ToArray(); // VB.NET sometimes produces temporary files which it then deletes // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb) string filename = Path.GetFileName(segment.filename); if (filename.Length == 40 && filename.EndsWith(".vb")) { bool guidName = true; foreach (char c in filename.Substring(0, filename.Length - 3)) { if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-')) { guidName = true; } else { guidName = false; break; } } if (guidName) { return(null); } } return(segment); } } return(null); }
public static SourcecodeSegment Resolve(Module module, string fileName, byte[] checkSum, int line, int column) { // Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name // Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) { return(null); // No symbols } ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName, checkSum); if (symDoc == null) { return(null); // Document not found } ISymUnmanagedMethod symMethod; try { uint validLine = symDoc.FindClosestLine((uint)line); symMethod = symReader.GetMethodFromDocumentPosition(symDoc, (uint)validLine, (uint)column); } catch { return(null); //Not found } SequencePoint[] seqPoints = symMethod.GetSequencePoints(); Array.Sort(seqPoints); if (seqPoints.Length == 0) { return(null); } if (line < seqPoints[0].Line) { return(null); } foreach (SequencePoint sqPoint in seqPoints) { if (sqPoint.Line == 0xFEEFEE) { continue; } // If the desired breakpoint position is before the end of the sequence point if (line < sqPoint.EndLine || (line == sqPoint.EndLine && column < sqPoint.EndColumn)) { SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.filename = symDoc.GetURL(); segment.checkSum = symDoc.GetCheckSum(); segment.startLine = (int)sqPoint.Line; segment.startColumn = (int)sqPoint.Column; segment.endLine = (int)sqPoint.EndLine; segment.endColumn = (int)sqPoint.EndColumn; segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); segment.ilStart = (int)sqPoint.Offset; segment.ilEnd = (int)sqPoint.Offset; segment.stepRanges = null; return(segment); } } return(null); }
private SourcecodeSegment GetSegmentForOffet(int offset) { return(SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, corFunction, offset)); }