/// <summary> /// Called when receiving a report about a method /// </summary> /// <param name="methodName"></param> /// <param name="methodSig"></param> /// <param name="bodySize"></param> /// <param name="flags"></param> /// <param name="implFlags"></param> /// <param name="symbolFileId"></param> /// <param name="methodDef"></param> public void EnterMethod(string methodName, string methodSig, int bodySize, uint flags, uint implFlags, int symbolFileId, int methodDef) { currentTypedef.Methods.Add(currentMethod = new MethodEntry { Type = currentTypedef, Name = methodName, Signature = methodSig, BodySize = bodySize, MethodDef = methodDef, Flags = (MethodAttributes)flags, ImplFlags = (MethodImplAttributes)implFlags }); if (_symbolReader != null) { var token = new SymbolToken(methodDef); ISymbolMethod method; try { method = _symbolReader.GetMethod(token); var count = method.SequencePointCount; int[] offsets = new int[count]; int[] sls = new int[count]; int[] scs = new int[count]; int[] els = new int[count]; int[] ecs = new int[count]; ISymbolDocument[] docs = new ISymbolDocument[count]; method.GetSequencePoints(offsets, docs, sls, scs, els, ecs); for (int i = 0; i < count; i++) { MethodBlock block = new MethodBlock(); block.Offset = offsets[i]; var fileId = GetFileIdentifier(docs[i].URL); if (fileId > 0 && sls[i] != 0xFEEFEE) { block.Start = new Position { Column = scs[i], Line = sls[i] }; block.End = new Position { Column = ecs[i], Line = els[i] }; block.File = fileId; } currentMethod.Blocks.Add(block); } docs = null; } catch (Exception ex) { } finally { method = null; } } }
// Write the sequence points for the given method // Sequence points are the map between IL offsets and source lines. // A single method could span multiple files (use C#'s #line directive to see for yourself). private SequencePoint[] ReadSequencePoints(ISymbolMethod method) { int count = method.SequencePointCount; // Get the sequence points from the symbol store. // We could cache these arrays and reuse them. int[] offsets = new int[count]; ISymbolDocument[] docs = new ISymbolDocument[count]; int[] startColumn = new int[count]; int[] endColumn = new int[count]; int[] startRow = new int[count]; int[] endRow = new int[count]; method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn); // Store them into the list var sequencePoints = new List <SequencePoint>(count); for (int i = 0; i < count; i++) { var sp = new SequencePoint(offsets[i], docs[i].URL, startRow[i], endRow[i], startColumn[i], endColumn[i]); sequencePoints.Add(sp); } return(sequencePoints.OrderBy(sp => sp.SourcePath).ThenBy(sp => sp.StartLine).ToArray()); }
/// <summary> /// Returns the name of the file for the given method using the given symbol reader /// </summary> /// <param name="reader">The reader to use</param> /// <param name="methodBase">The method to lookup</param> /// <returns>The file containing the method or null.</returns> private static string GetFileForMethod(ISymbolReader reader, MethodBase methodBase) { int token = methodBase.MetadataToken; ISymbolMethod methodSymbol = reader == null ? null : reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { int count = methodSymbol.SequencePointCount; // Get the sequence points from the symbol store. // We could cache these arrays and reuse them. int[] offsets = new int[count]; ISymbolDocument[] docs = new ISymbolDocument[count]; int[] startColumn = new int[count]; int[] endColumn = new int[count]; int[] startRow = new int[count]; int[] endRow = new int[count]; methodSymbol.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn); foreach (ISymbolDocument doc in docs) { string file = doc.URL.ToString(); return(file); } } return(null); }
void AddSequencePoints(CilBody body, ISymbolMethod method) { int numSeqs = method.SequencePointCount; var offsets = new int[numSeqs]; var documents = new ISymbolDocument[numSeqs]; var lines = new int[numSeqs]; var columns = new int[numSeqs]; var endLines = new int[numSeqs]; var endColumns = new int[numSeqs]; method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns); int instrIndex = 0; for (int i = 0; i < numSeqs; i++) { var instr = GetInstruction(body.Instructions, offsets[i], ref instrIndex); if (instr == null) { continue; } var seqPoint = new SequencePoint() { Document = Add_NoLock(new PdbDocument(documents[i])), StartLine = lines[i], StartColumn = columns[i], EndLine = endLines[i], EndColumn = endColumns[i], }; instr.SequencePoint = seqPoint; } }
//private string[] GetCombinedSource(IEnumerable<SequencePoint> points) { // var lines = new List<string>(); // foreach (var point in points) { // var contentLines = documentCache.Get(point.Document, () => File.ReadAllLines(point.Document.URL)); // var start = point.Start.Row - 1; // var end = point.End.Row - 1; // if (start >= contentLines.Length || end >= contentLines.Length) // continue; // for (var i = start; i <= end; i++) { // var line = contentLines[i]; // if (i == start) // line = line.Substring(point.Start.Column - 1); // else if (i == end) // line = line.Substring(0, point.End.Column - 1); // lines.Add(line); // } // } // return lines.ToArray(); //} private IEnumerable <SequencePoint> GetSequencePoints(ISymbolMethod method) { var count = method.SequencePointCount; var offsets = new int[count]; var docs = new ISymbolDocument[count]; var startColumns = new int[count]; var endColumns = new int[count]; var startRows = new int[count]; var endRows = new int[count]; method.GetSequencePoints(offsets, docs, startRows, startColumns, endRows, endColumns); for (int i = 0; i < count; i++) { if (startRows[i] == SequencePointHiddenLine || endRows[i] == SequencePointHiddenLine) { continue; } yield return(new SequencePoint { Document = this.GetOrLoadContent(docs[i]), Start = new SourcePosition(startRows[i], startColumns[i]), End = new SourcePosition(endRows[i], endColumns[i]) }); } }
public ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument document, int line, int column) { ISymUnmanagedMethod unmanagedMethod; unmanagedReader.GetMethodFromDocumentPosition(((SymbolDocument)document).InternalDocument, line, column, out unmanagedMethod); return(new SymbolMethod(unmanagedMethod)); }
public int GetDocumentVersion(ISymbolDocument document, out bool isCurrent) { int version; unmanagedReader.GetDocumentVersion(((SymbolDocument)document).InternalDocument, out version, out isCurrent); return(version); }
public void GetSequencePoints(int[] offsets, ISymbolDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns) { // Any array can be null, and the documentation says we must verify the sizes. int arySize = -1; if (offsets != null) arySize = offsets.Length; else if (documents != null) arySize = documents.Length; else if (lines != null) arySize = lines.Length; else if (columns != null) arySize = columns.Length; else if (endLines != null) arySize = endLines.Length; else if (endColumns != null)arySize = endColumns.Length; if (offsets != null && offsets.Length != arySize) throw new ArgumentException("Invalid array length: offsets"); if (documents != null && documents.Length != arySize) throw new ArgumentException("Invalid array length: documents"); if (lines != null && lines.Length != arySize) throw new ArgumentException("Invalid array length: lines"); if (columns != null && columns.Length != arySize) throw new ArgumentException("Invalid array length: columns"); if (endLines != null && endLines.Length != arySize) throw new ArgumentException("Invalid array length: endLines"); if (endColumns != null && endColumns.Length != arySize) throw new ArgumentException("Invalid array length: endColumns"); if (arySize <= 0) return; var unDocs = documents == null ? null : new ISymUnmanagedDocument[documents.Length]; uint size; method.GetSequencePoints((uint)arySize, out size, offsets, unDocs, lines, columns, endLines, endColumns); if (unDocs != null) { for (int i = 0; i < unDocs.Length; i++) documents[i] = unDocs[i] == null ? null : new SymbolDocument(unDocs[i]); } }
//�Public�Methods�(1)� /// <summary> /// Gets the method source from PDB. /// </summary> /// <param name="methodInfo">The method info.</param> /// <returns></returns> public PDBMethodSourceData GetMethodSourceFromPDB(MethodInfo methodInfo) { ISymbolMethod met = _symbolReader.GetMethod(new SymbolToken(methodInfo.MetadataToken)); int count = met.SequencePointCount; ISymbolDocument[] docs = new ISymbolDocument[count]; int[] offsets = new int[count]; int[] lines = new int[count]; int[] columns = new int[count]; int[] endlines = new int[count]; int[] endcolumns = new int[count]; met.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns); return(new PDBMethodSourceData() { symbolDocs = docs, sourceCodeLines = lines, ilOpcodeOffsets = offsets, souceCodeColumns = columns, sourceCodeEndColumns = endcolumns, sourceCodeEndLines = endlines }); }
public static IEnumerable <SequencePoint> GetSequencePoints(this ISymbolMethod met) { int sc = met.SequencePointCount; int[] offsets = new int[sc]; int[] lines = new int[sc]; int[] endLines = new int[sc]; int[] columns = new int[sc]; int[] endColumns = new int[sc]; ISymbolDocument[] docs = new ISymbolDocument[sc]; met.GetSequencePoints(offsets, docs, lines, columns, endLines, endColumns); for (int n = 0; n < sc; n++) { if (columns[n] == 0) { continue; } SequencePoint sp = new SequencePoint(); sp.Document = docs[n]; sp.Line = lines[n]; sp.Offset = offsets[n]; yield return(sp); } }
void ISymbolMethod.GetSequencePoints(int[] offsets, ISymbolDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns) { int count = Lines == null ? 0 : Lines.Count; if (offsets != null && offsets.Length != count) throw new ArgumentException("Invalid array length: offsets"); if (documents != null && documents.Length != count) throw new ArgumentException("Invalid array length: documents"); if (lines != null && lines.Length != count) throw new ArgumentException("Invalid array length: lines"); if (columns != null && columns.Length != count) throw new ArgumentException("Invalid array length: columns"); if (endLines != null && endLines.Length != count) throw new ArgumentException("Invalid array length: endLines"); if (endColumns != null && endColumns.Length != count) throw new ArgumentException("Invalid array length: endColumns"); if (count <= 0) return; int i = 0; foreach (var line in Lines) { offsets[i] = (int)line.Offset; documents[i] = line.Document; lines[i] = (int)line.LineBegin; columns[i] = (int)line.ColumnBegin; endLines[i] = (int)line.LineEnd; endColumns[i] = (int)line.ColumnEnd; i++; } }
// note: sadly it's not possible to cache all the [count] allocations and reuse them. // a NRE is throw if the size of the arrays does not match SequencePointCount :( void ReadSequencePoints(ISymbolMethod method, IDictionary instructions) { int count = method.SequencePointCount; int [] offsets = new int [count]; ISymbolDocument [] docs = new ISymbolDocument [count]; int [] startColumn = new int [count]; int [] endColumn = new int [count]; int [] startRow = new int [count]; int [] endRow = new int [count]; method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn); for (int i = 0; i < offsets.Length; i++) { Cil.Instruction instr = (Cil.Instruction)instructions [offsets [i]]; Cil.SequencePoint sp = new Cil.SequencePoint(GetDocument(docs [i])); sp.StartLine = startRow [i]; sp.StartColumn = startColumn [i]; sp.EndLine = endRow [i]; sp.EndColumn = endColumn [i]; instr.SequencePoint = sp; } }
public MethodDebugInfo(MethodBody body, ISymbolMethod pdb) { Body = body; // todo. support multiple locals sharing the same local slot // (but having different Start::End offsets, of course) // so far we just silently ignore them taking into account only the first one var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals()); LocalNames = locals.Select(lv => new { Index = lv.AddressField1, Name = lv.Name }) .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly(); var count = pdb.SequencePointCount; var offsets = new int[count]; var documents = new ISymbolDocument[count]; var lines = new int[count]; var columns = new int[count]; var endLines = new int[count]; var endColumns = new int[count]; pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns); SequencePoints = 0.UpTo(count - 1).Select(i => new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i]) ).ToReadOnly(); }
public SequencePoint[] Generate(ISymbolMethod method) { var sequencePoints = new List<SequencePoint>(); var sp_count = method.SequencePointCount; var spOffsets = new int[sp_count]; // Array.CreateInstance(int, sp_count) var spDocs = new ISymbolDocument[sp_count]; // Array.CreateInstance(ISymbolDocument, sp_count) var spStartLines = new int[sp_count]; // Array.CreateInstance(int, sp_count) var spEndLines = new int[sp_count]; // Array.CreateInstance(int, sp_count) var spStartCol = new int[sp_count]; // Array.CreateInstance(int, sp_count) var spEndCol = new int[sp_count]; // Array.CreateInstance(int, sp_count) method.GetSequencePoints(spOffsets, spDocs, spStartLines, spStartCol, spEndLines, spEndCol); for (int i = 0; i < sp_count; i++) // (var i in range(sp_count)) { if (spStartLines[i] != 0xfeefee) // if spStartLines[i] != 0xfeefee: { sequencePoints.Add(new SequencePoint(spOffsets[i], spDocs[i], spStartLines[i], spStartCol[i], spEndLines[i], spEndCol[i])); } } return sequencePoints.ToArray(); }
static void Main(string[] args) { Assembly ass = Assembly.GetExecutingAssembly(); ISymbolReader symreader = SymUtil.GetSymbolReaderForFile(ass.Location, null); MethodInfo m = ass.GetType("PdbTest.TestClass").GetMethod("GetStringRepresentation"); ISymbolMethod met = symreader.GetMethod(new SymbolToken(m.MetadataToken)); int count = met.SequencePointCount; ISymbolDocument[] docs = new ISymbolDocument[count]; int[] offsets = new int[count]; int[] lines = new int[count]; int[] columns = new int[count]; int[] endlines = new int[count]; int[] endcolumns = new int[count]; met.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns); StreamReader reader = new StreamReader(docs[0].URL); string[] linesOfCode = reader.ReadToEnd().Split('n'); reader.Close(); Console.WriteLine("The content of method PdbTest.TestClass.GetStringRepresentation"); for (int i = lines[0]; i < endlines[count - 1] - 1; i++) { Console.WriteLine(linesOfCode[i]); } }
public int GetOffset( ISymbolDocument document, int line, int column) { throw new NotImplementedException("No QUT.SymbolMethod.GetOffset"); }
public int GetOffset(ISymbolDocument document, int line, int column) { int retVal; unmanagedMethod.GetOffset(((SymbolDocument)document).InternalDocument, line, column, out retVal); return(retVal); }
////////////////////////////////////////////////////////////////////////////////// // // Initialization & locals // ////////////////////////////////////////////////////////////////////////////////// private void EnsureIsUpToDate() { Debug.Assert(m_module != null); Debug.Assert(m_module.EditsCounter >= CorFunction.Version - 1); // version cannot be greater then # of edits; versions are 1 based if (m_isInitialized) { return; // no need to do any refresh } // perform refresh m_isInitialized = true; m_haveSymbols = m_module.SymReader != null; if (m_haveSymbols) { ISymbolMethod sm = null; sm = m_module.SymReader.GetMethod(new SymbolToken((int)m_function.Token), CorFunction.Version); if (sm == null) { m_haveSymbols = false; return; } m_symMethod = sm; m_SPcount = m_symMethod.SequencePointCount; m_SPoffsets = new int[m_SPcount]; m_SPdocuments = new ISymbolDocument[m_SPcount]; m_SPstartLines = new int[m_SPcount]; m_SPendLines = new int[m_SPcount]; m_SPstartColumns = new int[m_SPcount]; m_SPendColumns = new int[m_SPcount]; m_symMethod.GetSequencePoints(m_SPoffsets, m_SPdocuments, m_SPstartLines, m_SPstartColumns, m_SPendLines, m_SPendColumns); } }
public int GetOffset(ISymbolDocument document, int line, int column) { var symDoc = document as SymbolDocument; if (symDoc == null) throw new ArgumentException("document is not a non-null SymbolDocument instance"); uint result; method.GetOffset(symDoc.SymUnmanagedDocument, (uint)line, (uint)column, out result); return (int)result; }
/// <summary> /// Gets the method that contains a specified position of the document /// </summary> /// <param name="document">The document object</param> /// <param name="line">Source line number</param> /// <param name="column">Source column number</param> /// <returns>The chosen method</returns> public ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument doc, int line, int column) { ISymUnmanagedMethod unMeth; private_reader.GetMethodFromDocumentPosition( ((SymbolDocument)doc).WrappedDoc, line, column, out unMeth); return(new SymbolMethod(unMeth)); }
public int GetDocumentVersion(ISymbolDocument document, out Boolean isCurrent) { int version = 0; m_reader.GetDocumentVersion(((SymbolDocument)document).InternalDocument, out version, out isCurrent); return(version); }
// Constructor. public SequencePoint(int offset, ISymbolDocument document, int line, int column) { this.offset = offset; this.document = document; this.line = line; this.column = column; }
public int[] GetRanges(ISymbolDocument document, int line, int column) { int cRanges; unmanagedMethod.GetRanges(((SymbolDocument)document).InternalDocument, line, column, 0, out cRanges, null); int[] ranges = new int[cRanges]; unmanagedMethod.GetRanges(((SymbolDocument)document).InternalDocument, line, column, cRanges, out cRanges, ranges); return(ranges); }
internal SourceDocument(string[] lines, string location, ISymbolDocument symbols) { this.Lines = lines; this.Content = string.Join(Environment.NewLine, lines); this.Location = location; this.Symbols = symbols; }
public SequencePoint(int offset, ISymbolDocument document, int lineStart, int lineStartColumn, int lineEnd, int lineEndColumn) { Offset = offset; Document = document; LineStart = lineStart; LineStartColumn = lineStartColumn; LineEnd = lineEnd; LineEndColumn = lineEndColumn; }
public SequencePoint(int offset, ISymbolDocument document, int startLine, int startColumn, int endLine, int endColumn) { this.offset = offset; this.document = document; this.startLine = startLine; this.startColumn = startColumn; this.endLine = endLine; this.endColumn = endColumn; }
/// <summary> /// Constructor /// </summary> /// <param name="symDoc">A <see cref="ISymbolDocument"/> instance</param> public PdbDocument(ISymbolDocument symDoc) { if (symDoc == null) throw new ArgumentNullException("symDoc"); this.Url = symDoc.URL; this.Language = symDoc.Language; this.LanguageVendor = symDoc.LanguageVendor; this.DocumentType = symDoc.DocumentType; this.CheckSumAlgorithmId = symDoc.CheckSumAlgorithmId; this.CheckSum = symDoc.GetCheckSum(); }
private SourceDocument GetOrLoadContent(ISymbolDocument symbols) { var location = symbols.URL; if (!File.Exists(location)) return null; return documentCache.Get( location, () => new SourceDocument(File.ReadAllLines(location), location, symbols) ); }
public ISymbolDocument[] GetDocuments() { uint numDocs; reader.GetDocuments(0, out numDocs, null); var unDocs = new ISymUnmanagedDocument[numDocs]; reader.GetDocuments((uint)unDocs.Length, out numDocs, unDocs); var docs = new ISymbolDocument[numDocs]; for (uint i = 0; i < numDocs; i++) docs[i] = new SymbolDocument(unDocs[i]); return docs; }
public int[] GetRanges(ISymbolDocument document, int line, int column) { var symDoc = document as SymbolDocument; if (symDoc == null) throw new ArgumentException("document is not a non-null SymbolDocument instance"); uint arySize; method.GetRanges(symDoc.SymUnmanagedDocument, (uint)line, (uint)column, 0, out arySize, null); var ary = new int[arySize]; method.GetRanges(symDoc.SymUnmanagedDocument, (uint)line, (uint)column, (uint)ary.Length, out arySize, ary); return ary; }
ISymbolDocument[] ISymbolReader.GetDocuments() { var docs = new ISymbolDocument[documents.Count]; int i = 0; foreach (var doc in documents.Values) { docs[i++] = doc; } return(docs); }
public ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument document, int line, int column) { var symDoc = document as SymbolDocument; if (symDoc == null) throw new ArgumentException("document is not a non-null SymbolDocument instance"); ISymUnmanagedMethod unMethod; int hr = reader.GetMethodFromDocumentPosition(symDoc.SymUnmanagedDocument, (uint)line, (uint)column, out unMethod); if (hr == E_FAIL) return null; Marshal.ThrowExceptionForHR(hr); return unMethod == null ? null : new SymbolMethod(unMethod); }
public static void GetLocalVariables(Assembly asm, MethodInfo m) { // Assembly asm = Assembly.GetExecutingAssembly(); ISymbolReader symreader = SymUtil.GetSymbolReaderForFile(asm.Location, null); if (symreader == null) { Console.WriteLine(" ERROR: no symreader was created. Aborting GetLocalVariables..."); return; } ISymbolMethod symMethod = symreader.GetMethod(new SymbolToken(m.MetadataToken)); int sequencePointCount = symMethod.SequencePointCount; ISymbolDocument[] docs = new ISymbolDocument[sequencePointCount]; int[] offsets = new int[sequencePointCount]; int[] lines = new int[sequencePointCount]; int[] columns = new int[sequencePointCount]; int[] endlines = new int[sequencePointCount]; int[] endcolumns = new int[sequencePointCount]; symMethod.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns); Console.WriteLine(); Console.WriteLine("The source code for method: " + m.Name + "; found in " + docs[0].URL); Console.WriteLine(new String('*', 60)); // although there's an array of docs, they seem to all have the same value (?) so we'll only use the first one StreamReader reader = new StreamReader(docs[0].URL); // URL is typically a fully path-qualified filename string[] linesOfCode = reader.ReadToEnd().Split('\r'); string PrintableLineNumber = "0000"; Console.WriteLine(linesOfCode[lines[0] - 2].Replace('\n', ' ')); // the preceding line (assumes declaration is only one line long, and found on immediately precediting line! // foreach (int LineNumber in lines) // print the source code (comments omitted) for (int LineNumber = lines[0]; LineNumber < lines[sequencePointCount - 1] + 1; LineNumber++) // print the source code (including comments) { PrintableLineNumber = new String(' ', 4 - LineNumber.ToString().Length) // padding + LineNumber.ToString(); Console.WriteLine(PrintableLineNumber + ": " + linesOfCode[LineNumber - 1].Replace('\n', ' ')); } // Console.WriteLine(linesOfCode[lines[sequencePointCount -1] + 1].Replace('\n', ' ')); // the trailing line //Console.WriteLine(linesOfCode); reader.Close(); Console.WriteLine(new String('*', 60)); Console.WriteLine(); linesOfCode = null; }
/// <summary> /// Constructor /// </summary> /// <param name="symDoc">A <see cref="ISymbolDocument"/> instance</param> public PdbDocument(ISymbolDocument symDoc) { if (symDoc == null) { throw new ArgumentNullException("symDoc"); } this.Url = symDoc.URL; this.Language = symDoc.Language; this.LanguageVendor = symDoc.LanguageVendor; this.DocumentType = symDoc.DocumentType; this.CheckSumAlgorithmId = symDoc.CheckSumAlgorithmId; this.CheckSum = symDoc.GetCheckSum(); }
public int GetOffset(ISymbolDocument document, int line, int column) { var symDoc = document as SymbolDocument; if (symDoc == null) { throw new ArgumentException("document is not a non-null SymbolDocument instance"); } uint result; method.GetOffset(symDoc.SymUnmanagedDocument, (uint)line, (uint)column, out result); return((int)result); }
private SourceDocument GetOrLoadContent(ISymbolDocument symbols) { var location = symbols.URL; if (!File.Exists(location)) { return(null); } return(documentCache.Get( location, () => new SourceDocument(File.ReadAllLines(location), location, symbols) )); }
private bool attemptSetBreakpoint(ISymbolReader reader, ISymbolDocument doc, CorModule module) { if (!doc.URL.Equals(_breakpoint.File)) return false; var line = doc.FindClosestLine(_breakpoint.Line); var method = reader.GetMethodFromDocumentPosition(doc, line, _breakpoint.Column); var function = module.GetFunctionFromToken(method.Token.GetToken()); var wasSet = attemptToSetBreakpointThroughSequencePoints(doc, line, method, function); if (!wasSet) setBreakpointThroughFunction(function); return true; }
internal int GetIPFromPosition(ISymbolDocument document, int lineNumber) { EnsureIsUpToDate(); for (int i = 0; i < m_SPcount; i++) { if (document.URL.Equals(m_SPdocuments[i].URL) && lineNumber == m_SPstartLines[i]) { return(m_SPoffsets[i]); } } return(-1); }
public ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument document, int line, int column) { var symDocument = document as SymbolDocument; if (symDocument == null) { throw new InvalidOperationException(); } ISymUnmanagedMethod unmanagedMethod; HRESULT.ThrowOnFailure(_unmanaged.GetMethodFromDocumentPosition(symDocument.Unmanaged, line, column, out unmanagedMethod)); return(new SymbolMethod(unmanagedMethod)); }
public int GetOffset(ISymbolDocument document, int line, int column) { var symDocument = document as SymbolDocument; if (symDocument == null) { throw new InvalidOperationException(); } int value; HRESULT.ThrowOnFailure(_unmanaged.GetOffset(symDocument.Unmanaged, line, column, out value)); return(value); }
private bool attemptToSetBreakpointThroughSequencePoints(ISymbolDocument doc, int line, ISymbolMethod method, CorFunction function) { bool found = false; foreach (var sp in getSequencePoints(method)) { if (sp.Document.URL.Equals(doc.URL) && sp.LineStart.Equals(line)) { var bp = function.ILCode.CreateBreakpoint(sp.Offset); bp.Activate(true); found = true; break; } } return found; }
public static SequencePoint[] GetSequencePoints(this ISymbolMethod method) { var offsets = new int[method.SequencePointCount]; var documents = new ISymbolDocument[method.SequencePointCount]; var lines = new int[method.SequencePointCount]; var columns = new int[method.SequencePointCount]; var endLines = new int[method.SequencePointCount]; var endColumns = new int[method.SequencePointCount]; var sequencePoints = new SequencePoint[method.SequencePointCount]; method.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns); for (int i = 0; i < method.SequencePointCount; i++) { var location = new SourceLocation(documents[i].URL, lines[i], columns[i], endLines[i], endColumns[i]); sequencePoints[i] = new SequencePoint(offsets[i], location); } return sequencePoints; }
//private string[] GetCombinedSource(IEnumerable<SequencePoint> points) { // var lines = new List<string>(); // foreach (var point in points) { // var contentLines = documentCache.Get(point.Document, () => File.ReadAllLines(point.Document.URL)); // var start = point.Start.Row - 1; // var end = point.End.Row - 1; // if (start >= contentLines.Length || end >= contentLines.Length) // continue; // for (var i = start; i <= end; i++) { // var line = contentLines[i]; // if (i == start) // line = line.Substring(point.Start.Column - 1); // else if (i == end) // line = line.Substring(0, point.End.Column - 1); // lines.Add(line); // } // } // return lines.ToArray(); //} private IEnumerable<SequencePoint> GetSequencePoints(ISymbolMethod method) { var count = method.SequencePointCount; var offsets = new int[count]; var docs = new ISymbolDocument[count]; var startColumns = new int[count]; var endColumns = new int[count]; var startRows = new int[count]; var endRows = new int[count]; method.GetSequencePoints(offsets, docs, startRows, startColumns, endRows, endColumns); for (int i = 0; i < count; i++) { if (startRows[i] == SequencePointHiddenLine || endRows[i] == SequencePointHiddenLine) continue; yield return new SequencePoint { Document = this.GetOrLoadContent(docs[i]), Start = new SourcePosition(startRows[i], startColumns[i]), End = new SourcePosition(endRows[i], endColumns[i]) }; } }
public MethodDebugInfo(MethodBody body, ISymbolMethod pdb) { Body = body; // todo. support multiple locals sharing the same local slot // (but having different Start::End offsets, of course) // so far we just silently ignore them taking into account only the first one var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals()); LocalNames = locals.Select(lv => new {Index = lv.AddressField1, Name = lv.Name}) .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly(); var count = pdb.SequencePointCount; var offsets = new int[count]; var documents = new ISymbolDocument[count]; var lines = new int[count]; var columns = new int[count]; var endLines = new int[count]; var endColumns = new int[count]; pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns); SequencePoints = 0.UpTo(count - 1).Select(i => new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i]) ).ToReadOnly(); }
public int GetOffset(ISymbolDocument document, int line, int column) { int retVal = 0; m_unmanagedMethod.GetOffset(((SymbolDocument) document).InternalDocument, line, column, out retVal); return retVal; }
// parent - main containing window that this source window lives inside of. // function - function for which we're building virtual source around. // Get the IL from the given frame. // Called on UI thread. internal VirtualSourceViewerForm(MainForm parent, MDbgFunction function) { m_function = function; Debug.Assert(function != null); // Now actually right in text. do this first so that we can get the current font. BeginInit(parent); // Get fonts FontCache cache; { Font fontCurrent = this.richText.Font; Font emphasis = new Font( fontCurrent.FontFamily, fontCurrent.Size, FontStyle.Bold ); cache = new FontCache(emphasis); } // Underlying writer to the window. RawWriter rawWriter = new RawWriter(cache); // Il2Native mapping can be used to find out what IL offsets we can actually stop on. Il2NativeIterator il2nativeIterator = null; // Actual IL disassembly in string form. ILDasmIterator ilDasm = null; // Iterator through sequence points and source files. SequencePointIterator seqIterator = null; string fullName = "?"; int token = 0; ulong nativeStartAddress = 0; CorDebugJITCompilerFlags codeFlags = CorDebugJITCompilerFlags.CORDEBUG_JIT_DEFAULT; // Make cross-thread call to worker thread to collect raw information. // This needs to access MDbg and so can't be done on our UI thread. parent.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); Debug.Assert(function.Module.Process == proc); // Get some properties about this function to display. token = function.CorFunction.Token; nativeStartAddress = function.CorFunction.NativeCode.Address; codeFlags = function.CorFunction.NativeCode.CompilerFlags; CorCode ilCode = function.CorFunction.ILCode; Debug.Assert(true == ilCode.IsIL); byte[] code = ilCode.GetCode(); fullName = function.FullName; // This does the real disassembly work. string[] lines = null; // strings of IL. ILDisassembler.Disassemble(code, function.Module.Importer, out lines, out m_il2RowMapping); ilDasm = new ILDasmIterator(rawWriter, m_il2RowMapping, lines); IL2NativeMap[] il2nativeMapping = function.CorFunction.NativeCode.GetILToNativeMapping(); il2nativeIterator = new Il2NativeIterator(rawWriter, il2nativeMapping, code); // Get sequence points ISymbolMethod symMethod = function.SymMethod; // Sequence point information int[] seqIlOffsets = null; string[] seqPaths = null; int[] seqStartLines = null, seqEndLines = null, seqStartColumns = null, seqEndColumns = null; int seqCount = 0; if (symMethod != null) { seqCount = symMethod.SequencePointCount; seqIlOffsets = new int[seqCount]; ISymbolDocument[] seqDocuments = new ISymbolDocument[seqCount]; seqPaths = new string[seqCount]; seqStartLines = new int[seqCount]; seqEndLines = new int[seqCount]; seqStartColumns = new int[seqCount]; seqEndColumns = new int[seqCount]; symMethod.GetSequencePoints(seqIlOffsets, seqDocuments, seqStartLines, seqStartColumns, seqEndLines, seqEndColumns); for (int i = 0; i < seqCount; i++) { seqPaths[i] = seqDocuments[i].URL; } } seqIterator = new SequencePointIterator(rawWriter, parent, seqIlOffsets, seqPaths, seqStartLines, seqStartColumns, seqEndLines, seqEndColumns); } ); // end worker call // We assume sequence points are sorted by IL offset. We assert that in the iterators below. // Now we need to go through and stitch the IL + Source together. // This also works even if we have no source (since that's just the degenerate case of 0 sequence points) // Print out header information Debug.Assert(token != 0); rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture, "> Function name:{0} (token={1:x})", fullName, token)); rawWriter.WriteLine(String.Format(CultureInfo.InvariantCulture, "> Native Code Address =0x{0:x}, flags={1}", nativeStartAddress, codeFlags)); // Walk through the IL in order and write out interleaved IL and Sequence Points. while (!seqIterator.IsDone) { // Add IL snippets that occur before this sequence point. WriteIlAndNative(ilDasm, il2nativeIterator, seqIterator.IlOffset); seqIterator.WriteSource(); seqIterator.Next(); } // Write the IL that's after the last sequence point WriteIlAndNative(ilDasm, il2nativeIterator, ilDasm.IlLength); // Set the text. InitLines(null, rawWriter.Lines, rawWriter.FormatList); EndInit(fullName); }
public virtual int GetOffset (ISymbolDocument document, int line, int column) { // Load the sequence point information. LoadSequencePoints(); // Search for an applicable block, based on the line number. int index; SequencePoint seq1; SequencePoint seq2; for(index = 0; index < sequencePoints.Count; ++index) { seq1 = (SequencePoint)(sequencePoints[index]); if(line >= seq1.line) { if(index < sequencePoints.Count - 1) { seq2 = (SequencePoint)(sequencePoints[index + 1]); if(line < seq2.line) { if(document == null || seq1.document == null || document.URL == seq1.document.URL) { return seq1.offset; } } } else { if(document == null || seq1.document == null || document.URL == seq1.document.URL) { return seq1.offset; } } } } // Could not find the offset, so assume offset zero. return 0; }
public virtual bool GetSourceStartEnd (ISymbolDocument[] docs, int[] lines, int[] columns) { throw new NotSupportedException(); }
public virtual void GetSequencePoints (int[] offsets, ISymbolDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns) { int index; LoadSequencePoints(); for(index = 0; index < sequencePoints.Count; ++index) { if(offsets != null && index < offsets.Length) { offsets[index] = ((SequencePoint)(sequencePoints[index])).offset; } if(documents != null && index < documents.Length) { documents[index] = ((SequencePoint)(sequencePoints[index])).document; } if(lines != null && index < lines.Length) { lines[index] = ((SequencePoint)(sequencePoints[index])).line; } if(columns != null && index < columns.Length) { columns[index] = ((SequencePoint)(sequencePoints[index])).column; } if(endLines != null && index < endLines.Length) { // This information is not available. endLines[index] = 0; } if(endColumns != null && index < endColumns.Length) { // This information is not available. endColumns[index] = 0; } } }
public virtual int[] GetRanges (ISymbolDocument document, int line, int column) { // Not used in this implementation. return new int [0]; }
public static IEnumerable<SequencePoint> GetSequencePoints (this ISymbolMethod met) { int sc = met.SequencePointCount; int[] offsets = new int[sc]; int[] lines = new int[sc]; int[] endLines = new int[sc]; int[] columns = new int[sc]; int[] endColumns = new int[sc]; ISymbolDocument[] docs = new ISymbolDocument[sc]; met.GetSequencePoints (offsets, docs, lines, columns, endLines, endColumns); for (int n = 0; n < sc; n++) { if (columns[n] == 0) continue; SequencePoint sp = new SequencePoint (); sp.Document = docs[n]; sp.Line = lines[n]; sp.Offset = offsets[n]; yield return sp; } }
internal int GetIPFromPosition(ISymbolDocument document, int lineNumber) { EnsureIsUpToDate(); for (int i = 0; i < m_SPcount; i++) { if (document.URL.Equals(m_SPdocuments[i].URL) && lineNumber == m_SPstartLines[i]) return m_SPoffsets[i]; } return -1; }
// Write the sequence points for the given method // Sequence points are the map between IL offsets and source lines. // A single method could span multiple files (use C#'s #line directive to see for yourself). private List<SequencePoint> ReadSequencePoints(ISymbolMethod method) { int count = method.SequencePointCount; // Get the sequence points from the symbol store. // We could cache these arrays and reuse them. int[] offsets = new int[count]; ISymbolDocument[] docs = new ISymbolDocument[count]; int[] startColumn = new int[count]; int[] endColumn = new int[count]; int[] startRow = new int[count]; int[] endRow = new int[count]; method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn); // Store them into the list List<SequencePoint> sequencePoints = new List<SequencePoint>(count); for (int i = 0; i < count; i++) { SequencePoint sp = new SequencePoint(); sp.ilOffset = offsets[i]; // If it's a special 0xFeeFee sequence point (eg, "hidden"), // place an attribute on it to make it very easy for tools to recognize. // See http://blogs.msdn.com/jmstall/archive/2005/06/19/FeeFee_SequencePoints.aspx if (startRow[i] == 0xFeeFee) { sp.hidden = true; } sp.sourceId = this.m_fileMapping[docs[i].URL]; sp.startRow = startRow[i]; sp.startColumn = startColumn[i]; sp.endRow = endRow[i]; sp.endColumn = endColumn[i]; sequencePoints.Add(sp); } return sequencePoints; }
public void GetSequencePoints(int[] offsets, ISymbolDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns) { int spCount = 0; if (offsets != null) spCount = offsets.Length; else if (documents != null) spCount = documents.Length; else if (lines != null) spCount = lines.Length; else if (columns != null) spCount = columns.Length; else if (endLines != null) spCount = endLines.Length; else if (endColumns != null) spCount = endColumns.Length; // Don't do anything if they're not really asking for anything. if (spCount == 0) return; // Make sure all arrays are the same length. if ((offsets != null) && (spCount != offsets.Length)) throw new ArgumentException(); if ((lines != null) && (spCount != lines.Length)) throw new ArgumentException(); if ((columns != null) && (spCount != columns.Length)) throw new ArgumentException(); if ((endLines != null) && (spCount != endLines.Length)) throw new ArgumentException(); if ((endColumns != null) && (spCount != endColumns.Length)) throw new ArgumentException(); var unmanagedDocuments = new ISymUnmanagedDocument[documents.Length]; int cPoints = 0; uint i; m_unmanagedMethod.GetSequencePoints(documents.Length, out cPoints, offsets, unmanagedDocuments, lines, columns, endLines, endColumns); // Create the SymbolDocument form the IntPtr's for (i = 0; i < documents.Length; i++) { documents[i] = new SymbolDocument(unmanagedDocuments[i]); } return; }
public bool GetSourceStartEnd(ISymbolDocument[] docs, int[] lines, int[] columns) { uint i; bool pRetVal = false; int spCount = 0; if (docs != null) spCount = docs.Length; else if (lines != null) spCount = lines.Length; else if (columns != null) spCount = columns.Length; // If we don't have at least 2 entries then return an error if (spCount < 2) throw new ArgumentException(); // Make sure all arrays are the same length. if ((docs != null) && (spCount != docs.Length)) throw new ArgumentException(); if ((lines != null) && (spCount != lines.Length)) throw new ArgumentException(); if ((columns != null) && (spCount != columns.Length)) throw new ArgumentException(); var unmanagedDocuments = new ISymUnmanagedDocument[docs.Length]; m_unmanagedMethod.GetSourceStartEnd(unmanagedDocuments, lines, columns, out pRetVal); if (pRetVal) { for (i = 0; i < docs.Length; i++) { docs[i] = new SymbolDocument(unmanagedDocuments[i]); } } return pRetVal; }
public int[] GetRanges(ISymbolDocument document, int line, int column) { int cRanges = 0; m_unmanagedMethod.GetRanges(((SymbolDocument) document).InternalDocument, line, column, 0, out cRanges, null); var Ranges = new int[cRanges]; m_unmanagedMethod.GetRanges(((SymbolDocument) document).InternalDocument, line, column, cRanges, out cRanges, Ranges); return Ranges; }