internal Exception(Thread thread) { creationTime = DateTime.Now; this.process = thread.Process; this.thread = thread; corValue = thread.CorThread.CurrentException; exceptionType = thread.CurrentExceptionType; Value runtimeValue = new Value(process, new IExpirable[] { process.PauseSession }, new IMutable[] {}, delegate { return(corValue); }); NamedValue nv = runtimeValue.GetMember("_message"); if (!nv.IsNull) { message = nv.AsString; } else { message = runtimeValue.Type.FullName; } if (thread.LastFunctionWithLoadedSymbols != null) { location = thread.LastFunctionWithLoadedSymbols.NextStatement; } callstack = ""; int callstackItems = 0; if (!nv.IsNull) { foreach (Function function in thread.Callstack) { if (callstackItems >= 100) { callstack += "...\n"; break; } SourcecodeSegment loc = function.NextStatement; callstack += function.Name + "()"; if (loc != null) { callstack += " - " + loc.SourceFullFilename + ":" + loc.StartLine + "," + loc.StartColumn; } callstack += "\n"; callstackItems++; } } type = runtimeValue.Type.FullName; }
SourcecodeSegment SetIP(bool simulate, string filename, int line, int column) { process.AssertPaused(); SourcecodeSegment suggestion = new SourcecodeSegment(filename, line, column, column); ICorDebugFunction corFunction; int ilOffset; if (!suggestion.GetFunctionAndOffset(this.Module, false, out corFunction, out ilOffset)) { return(null); } else { if (corFunction.Token != methodProps.Token) { return(null); } else { try { if (simulate) { CorILFrame.CanSetIP((uint)ilOffset); } else { // invalidates all frames and chains for the current thread CorILFrame.SetIP((uint)ilOffset); process.NotifyPaused(new PauseSession(PausedReason.SetIP)); process.Pause(false); } } catch { return(null); } return(GetSegmentForOffet((uint)ilOffset)); } } }
/// <summary> /// Returns null 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 GetSegmentForOffet(uint offset) { ISymUnmanagedMethod symMethod; symMethod = this.symMethod; if (symMethod == null) { return(null); } uint sequencePointCount = symMethod.SequencePointCount; SequencePoint[] sequencePoints = symMethod.SequencePoints; SourcecodeSegment retVal = new SourcecodeSegment(); // 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 (sequencePoints[i].Offset <= offset || i == 0) { // Set inforamtion about current IL range int codeSize = (int)corFunction.ILCode.Size; retVal.ILOffset = (int)offset; retVal.ILStart = (int)sequencePoints[i].Offset; retVal.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 int k = i; // Look ahead for 'real' sequence while (i + 1 < sequencePointCount && sequencePoints[i].Line == 0xFeeFee) { i++; retVal.ILEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i + 1].Offset : codeSize; } // Look back for 'real' sequence while (i - 1 >= 0 && sequencePoints[i].Line == 0xFeeFee) { i--; retVal.ILStart = (int)sequencePoints[i].Offset; } // Wow, there are no 'real' sequences if (sequencePoints[i].Line == 0xFeeFee) { return(null); } retVal.ModuleFilename = module.FullPath; retVal.SourceFullFilename = sequencePoints[i].Document.URL; /*if (retVal.SourceFullFilename != null && Path.GetFileName(retVal.SourceFullFilename).StartsWith("_temp$")) * { * retVal.SourceFullFilename = Path.Combine(Path.GetDirectoryName(retVal.SourceFullFilename),Path.GetFileName(retVal.SourceFullFilename).Substring(6)); * System.Diagnostics.Debug.WriteLine(retVal.SourceFullFilename); * }*/ retVal.StartLine = (int)sequencePoints[i].Line; retVal.StartColumn = (int)sequencePoints[i].Column; retVal.EndLine = (int)sequencePoints[i].EndLine; retVal.EndColumn = (int)sequencePoints[i].EndColumn; 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 || (j > i && (sequencePoints[j].Line == sequencePoints[i].Line && sequencePoints[i].Document.URL == sequencePoints[j].Document.URL))) // line + document must be same // 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); } } } retVal.StepRanges = stepRanges.ToArray(); return(retVal); } } return(null); }