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(); }
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; } }
public LocalVariableNameReader(MethodInfo m) { ISymbolReader symReader = SymUtil.GetSymbolReaderForFile(m.DeclaringType.Assembly.Location, null); ISymbolMethod met = symReader.GetMethod(new SymbolToken(m.MetadataToken)); VisitLocals(met.RootScope); }
//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 int GetMethodVersion(ISymbolMethod method) { int version; unmanagedReader.GetMethodVersion(((SymbolMethod)method).InternalMethod, out version); return(version); }
//�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 }); }
// Write out a reference to the entry point method (if one exists) void WriteEntryPoint(ISymbolReader reader) { try { // If there is no entry point token (such as in a dll), this will throw. SymbolToken token = reader.UserEntryPoint; ISymbolMethod m = reader.GetMethod(token); Debug.Assert(m != null); // would have thrown by now. // Should not throw past this point m_writer.WriteComment( "This is the token for the 'entry point' method, which is the method that will be called when the assembly is loaded." + " This usually corresponds to 'Main'"); m_writer.WriteStartElement("EntryPoint"); WriteMethod(m); m_writer.WriteEndElement(); } catch (System.Runtime.InteropServices.COMException) { // If the Symbol APIs fail when looking for an entry point token, there is no entry point. m_writer.WriteComment( "There is no entry point token such as a 'Main' method. This module is probably a '.dll'"); } }
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(); }
public int GetMethodVersion(ISymbolMethod method) { int version = 0; m_reader.GetMethodVersion(((SymMethod)method).InternalMethod, out version); return(version); }
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]); } }
// 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; } }
// Initializes all private symbol variables private void SetupSymbolInformation() { if (p_symbolsInitialized) { return; } p_symbolsInitialized = true; CorModule module = GetModule(); ISymbolReader symreader = module.GetSymbolReader(); p_hasSymbols = symreader != null; if (p_hasSymbols) { ISymbolMethod sm = null; sm = symreader.GetMethod(new SymbolToken((Int32)GetToken())); // FIXME add version if (sm == null) { p_hasSymbols = false; return; } p_symMethod = sm; p_SPcount = p_symMethod.SequencePointCount; p_SPoffsets = new Int32[p_SPcount]; p_SPdocuments = new ISymbolDocument[p_SPcount]; p_SPstartLines = new Int32[p_SPcount]; p_SPendLines = new Int32[p_SPcount]; p_SPstartColumns = new Int32[p_SPcount]; p_SPendColumns = new Int32[p_SPcount]; p_symMethod.GetSequencePoints(p_SPoffsets, p_SPdocuments, p_SPstartLines, p_SPstartColumns, p_SPendLines, p_SPendColumns); } }
/// <summary> /// Gets information about the source if it is available. /// </summary> private bool GetSourceReference() { try { ISymbolReader sr = SymUtil.GetSymbolReaderForFile(_method.Module.Assembly.Location, null); ISymbolMethod sm = sr.GetMethod(new SymbolToken(_method.MetadataToken)); _count = sm.SequencePointCount; _offsets = new int[_count]; _documents = new ISymbolDocument[_count]; _startColumns = new int[_count]; _endColumns = new int[_count]; _startRows = new int[_count]; _endRows = new int[_count]; sm.GetSequencePoints(_offsets, _documents, _startRows, _startColumns, _endRows, _endColumns); return(true); } catch { _count = 0; _offsets = null; _documents = null; _startColumns = null; _endColumns = null; _startRows = null; _endRows = null; return(false); } }
private List <SymAttribute> ReadSymAttributes(ISymbolReader reader, ISymbolMethod method, bool haveCSharpCDI) { List <SymAttribute> attrs = new List <SymAttribute>(); foreach (string name in AttributeNamesToSearch()) { // If this attirubte represents C# CDI data, and we were able to expand it, then indicate that // the attribute here is redundant (as a raw view) and shouldn't be included again. if (name == k_cSharpCDIAttrName && haveCSharpCDI) { continue; } // Note that despite being defined on ISymbolReader instead of ISymbolMethod, custom // attributes are permitted only on method metadata tokens. byte[] attrVal = reader.GetSymAttribute(method.Token, name); if (attrVal != null) { SymAttribute attr = new SymAttribute(); attr.name = name; attr.value = Util.ToHexString(attrVal); attrs.Add(attr); } } return(attrs); }
// 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()); }
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); } }
////////////////////////////////////////////////////////////////////////////////// // // 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); } }
/// <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); }
public SymbolScope(ISymbolMethod method, ISymbolScope parent, int startOffset, int endOffset) { _children = new List <ISymbolScope>(); _locals = new List <ISymbolVariable>(); _startOffset = startOffset; _endOffset = endOffset; _parent = parent; }
protected override BreakEventInfo OnInsertBreakEvent(BreakEvent be) { BreakEventInfo binfo = new BreakEventInfo(); lock (documents) { Breakpoint bp = be as Breakpoint; if (bp != null) { DocInfo doc; if (!documents.TryGetValue(System.IO.Path.GetFullPath(bp.FileName), out doc)) { binfo.SetStatus(BreakEventStatus.NotBound, null); return(binfo); } int line; try { line = doc.Document.FindClosestLine(bp.Line); } catch { // Invalid line binfo.SetStatus(BreakEventStatus.Invalid, null); return(binfo); } ISymbolMethod met = doc.Reader.GetMethodFromDocumentPosition(doc.Document, line, 0); if (met == null) { binfo.SetStatus(BreakEventStatus.Invalid, null); return(binfo); } int offset = -1; foreach (SequencePoint sp in met.GetSequencePoints()) { if (sp.Line == line && sp.Document.URL == doc.Document.URL) { offset = sp.Offset; break; } } if (offset == -1) { binfo.SetStatus(BreakEventStatus.Invalid, null); return(binfo); } CorFunction func = doc.Module.GetFunctionFromToken(met.Token.GetToken()); CorFunctionBreakpoint corBp = func.ILCode.CreateBreakpoint(offset); corBp.Activate(bp.Enabled); breakpoints[corBp] = binfo; binfo.Handle = corBp; binfo.SetStatus(BreakEventStatus.Bound, null); return(binfo); } } return(null); }
// Write all the locals in the given method out to an XML file. // Since the symbol store represents the locals in a recursive scope structure, we need to walk a tree. // Although the locals are technically a hierarchy (based off nested scopes), it's easiest for clients // if we present them as a linear list. We will provide the range for each local's scope so that somebody // could reconstruct an approximation of the scope tree. The reconstruction may not be exact. // (Note this would still break down if you had an empty scope nested in another scope. void WriteLocals(ISymbolMethod method) { m_writer.WriteStartElement("locals"); { // If there are no locals, then this element will just be empty. WriteLocalsHelper(method.RootScope); } m_writer.WriteEndElement(); }
public void Read(Cil.MethodBody body, IDictionary instructions) { try { ISymbolMethod method = m_reader.GetMethod(new SymbolToken((int)body.Method.MetadataToken.ToUInt())); ReadSequencePoints(method, instructions); ReadScopeAndLocals(method.RootScope, null, body, instructions); } catch (COMException) {} }
// Dump all of the methods in the given ISymbolReader to the SymbolData provided private List <Method> ReadAllMethods(ISymbolReader reader) { List <Method> methods = new List <Method>(); // Use reflection to enumerate all methods foreach (MethodBase methodReflection in GetAllMethods(assembly)) { int token = methodReflection.MetadataToken; ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { Method methodData = new Method(); methodData.token = Util.AsToken(token); methodData.name = methodReflection.DeclaringType.FullName + "::" + methodReflection.Name; // This localSigMetadataToken information actually comes from the metadata in the assembly because the symbol reading API does not provide it. try { MethodBody body = methodReflection.GetMethodBody(); int lSMT = body.LocalSignatureMetadataToken; if (lSMT != 0) { methodData.localSigMetadataToken = Util.AsToken(lSMT); } } catch (System.Security.VerificationException) { // Work around a CLR or C# compiler bug with Void& types in signatures // <strip>See DevDiv Bugs 146662</strip> methodData.hasInvalidMethodBody = true; } methodData.sequencePoints = ReadSequencePoints(methodSymbol); methodData.rootScope = ReadScope(methodSymbol.RootScope); // Read symbol attributes, except on ILDB where it isn't supported if (symFormat != SymbolFormat.ILDB) { if (expandAttributes) { methodData.csharpCDI = ReadCSharpCDI(reader, methodSymbol); } methodData.symAttributes = ReadSymAttributes(reader, methodSymbol, methodData.csharpCDI != null); } if (symFormat == SymbolFormat.PDB) { WorkAroundDiasymreaderScopeBug(methodData.rootScope); } methods.Add(methodData); } } return(methods); }
IEnumerable <ValueReference> GetLocals(CorEvaluationContext ctx, ISymbolScope scope, int offset, bool showHidden) { if (ctx.Frame.FrameType != CorFrameType.ILFrame) { yield break; } if (scope == null) { ISymbolMethod met = ctx.Frame.Function.GetSymbolMethod(ctx.Session); if (met != null) { scope = met.RootScope; } else { int count = ctx.Frame.GetLocalVariablesCount(); for (int n = 0; n < count; n++) { int locn = n; CorValRef vref = new CorValRef(delegate { return(ctx.Frame.GetLocalVariable(locn)); }); yield return(new VariableReference(ctx, vref, "local_" + (n + 1), ObjectValueFlags.Variable)); } yield break; } } foreach (ISymbolVariable var in scope.GetLocals()) { if (var.Name == "$site") { continue; } if (var.Name.IndexOfAny(new char[] { '$', '<', '>' }) == -1 || showHidden) { int addr = var.AddressField1; CorValRef vref = new CorValRef(delegate { return(ctx.Frame.GetLocalVariable(addr)); }); yield return(new VariableReference(ctx, vref, var.Name, ObjectValueFlags.Variable)); } } foreach (ISymbolScope cs in scope.GetChildren()) { if (cs.StartOffset <= offset && cs.EndOffset >= offset) { foreach (VariableReference var in GetLocals(ctx, cs, offset, showHidden)) { yield return(var); } } } }
internal SymScope(ISymbolMethod method) { // Create the root scope for a method. this.method = method; this.parent = null; this.children = new ISymbolScope [0]; this.locals = new ISymbolVariable [0]; this.endOffset = Int32.MaxValue; this.startOffset = 0; }
private SymScope(SymScope parent, int endOffset, int startOffset) { // Create a new child scope. this.method = parent.method; this.parent = parent; this.children = new ISymbolScope [0]; this.locals = new ISymbolVariable [0]; this.endOffset = endOffset; this.startOffset = startOffset; }
public void Read(Cil.MethodBody body) { try { ISymbolMethod method = m_reader.GetMethod(new SymbolToken((int)body.Method.MetadataToken.ToUInt())); Hashtable instructions = GetInstructions(body); ReadSequencePoints(method, instructions); ReadScopeAndLocals(method.RootScope, null, body, instructions); } catch {} }
private string GetLocalVariableName(ulong instructionPointer, uint localIndex) { ClrMethod method = _context.Runtime.GetMethodByAddress(instructionPointer); ClrModule module = method.Type.Module; string pdbLocation = module.TryDownloadPdb(null); IntPtr iunkMetadataImport = Marshal.GetIUnknownForObject(module.MetadataImport); ISymbolReader reader = null; ISymbolMethod symMethod = null; try { using (var binder = new SymBinder()) { reader = binder.GetReader( iunkMetadataImport, module.FileName, Path.GetDirectoryName(pdbLocation)); symMethod = reader.GetMethod(new SymbolToken((int)method.MetadataToken)); return(GetLocalVariableName(symMethod.RootScope, localIndex)); } } catch (COMException comEx) { // E_FAIL occasionally occurs in ISymbolReader.GetMethod. Nothing we can do about it. if ((uint)comEx.HResult == 0x80004005) { return(""); } // 0x806D0005 occurs when the PDB cannot be found or doesn't contain the necessary // information to create a symbol reader. It's OK to ignore. if ((uint)comEx.HResult == 0x806D0005) { return(""); } throw; } finally { // These interfaces aren't IDisposable, but the underlying objects are. And it is // important to dispose of them properly, because if their finalizer runs on exit, // it crashes with an access violation. if (reader != null) { ((IDisposable)reader).Dispose(); } if (symMethod != null) { ((IDisposable)symMethod).Dispose(); } Marshal.Release(iunkMetadataImport); } }
/// <summary> /// Function tries to resolve the breakpoint from breakpoint description. /// </summary> /// <param name="functionBreakpoint">A breakpoint object.</param> /// <param name="managedModule">A module that the breakpoint should be resolved at.</param> /// <param name="managedFunction">A function that is resolved from the breakpoint description.</param> /// <param name="ILoffset">An il offset within a function resolved from the breakpoint description.</param> /// <returns>true if breakpoint was successfully resolved</returns> /// <remarks> /// Resolved is usually called for every loaded module. /// </remarks> public bool ResolveLocation(MDbgFunctionBreakpoint functionBreakpoint, MDbgModule managedModule, out List <MDbgFunction> managedFunction, out int ILoffset) { Debug.Assert(m_lineNo > 0 && m_file.Length > 0); managedFunction = null; ILoffset = 0; if (managedModule.SymReader == null) { // no symbols for current module, skip it. return(false); } foreach (ISymbolDocument doc in managedModule.SymReader.GetDocuments()) { if (String.Compare(doc.URL, m_file, true, CultureInfo.InvariantCulture) == 0 || String.Compare(System.IO.Path.GetFileName(doc.URL), m_file, true, CultureInfo.InvariantCulture) == 0) { int lineNo = 0; try { lineNo = doc.FindClosestLine(m_lineNo); } catch (System.Runtime.InteropServices.COMException e) { if (e.ErrorCode == (int)HResult.E_FAIL) { // we continue, because this location is not in this file, let's // keep trying to search for next file. continue; } } ISymbolMethod symMethod = managedModule.SymReader.GetMethodFromDocumentPosition(doc, lineNo, 0); managedFunction = new List <MDbgFunction>(); var func = managedModule.GetFunction(symMethod.Token.GetToken()); managedFunction.Add(func); ILoffset = func.GetIPFromPosition(doc, lineNo); // If this IL if (ILoffset == -1) { return(false); } Debug.Assert(ILoffset != -1); return(true); } } managedFunction = null; ILoffset = -1; return(false); }
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; }
public LocalVariableNameReader(MethodInfo m) { try { ISymbolReader symReader = SymUtil.GetSymbolReaderForFile(m.DeclaringType.Assembly.Location, null); ISymbolMethod met = symReader.GetMethod(new SymbolToken(m.MetadataToken)); VisitLocals(met.RootScope); } catch { Console.WriteLine(" ERROR: Failed LocalVariableNameReader() - perhaps this app needs to be compiled in x86?"); return; } }
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 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(); }
//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]) }; } }
private CSharpCDI ReadCSharpCDI(ISymbolReader reader, ISymbolMethod methodSymbol) { // See if the C# CDI attribute exists byte[] attrVal = reader.GetSymAttribute(methodSymbol.Token, k_cSharpCDIAttrName); if (attrVal == null) return null; // No such attribute try { return CDIReader.ParseCDI(attrVal); } catch (System.FormatException e) { Console.WriteLine("WARNING: Error parsing CSharp CDI for method {0}: {1}", Util.AsToken(methodSymbol.Token.GetToken()), e.Message); return null; } }
/// <summary> /// Create a new PDB method object from an ISymbolMethod object. /// </summary> /// <param name="meth">The ISymbolMethod object to wrap.</param> internal PDBMethod(ISymbolMethod meth) { Contract.Requires(meth != null); _meth = meth; }
private void InitSymbolInformation() { if (p_symbolsInitialized) return; p_symbolsInitialized = true; ISymbolReader symreader = Module.GetSymReader(); p_hasSymbols = symreader != null; if (p_hasSymbols) { ISymbolMethod sm = null; sm = symreader.GetMethod(new SymbolToken((Int32)Token)); if (sm == null) { p_hasSymbols = false; return; } p_symMethod = sm; p_SPcount = p_symMethod.SequencePointCount; p_SPoffsets = new Int32[p_SPcount]; p_SPdocuments = new ISymbolDocument[p_SPcount]; p_SPstartLines = new Int32[p_SPcount]; p_SPendLines = new Int32[p_SPcount]; p_SPstartColumns = new Int32[p_SPcount]; p_SPendColumns = new Int32[p_SPcount]; p_symMethod.GetSequencePoints(p_SPoffsets, p_SPdocuments, p_SPstartLines, p_SPstartColumns, p_SPendLines, p_SPendColumns); } }
private void Populate(ISymbolMethod method) { method.GetSequencePoints(Offsets, Documents, Lines, Columns, EndLines, EndColumns); for (int i = 0; i < Count; i++) { this.indexByOffsets.Add(Offsets[i], i); } }
private SequencePoint[] getSequencePoints(ISymbolMethod method) { var factory = new SequencePointFactory(); return factory.Generate(method); }
// 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 void WriteSequencePoints(ISymbolMethod method) { writer.WriteStartElement("sequencepoints"); int count = method.SequencePointCount; writer.WriteAttributeString("total", CultureInvariantToString(count)); // 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); // Write out sequence points for (int i = 0; i < count; i++) { writer.WriteStartElement("entry"); writer.WriteAttributeString("il_offset", AsILOffset(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) { writer.WriteAttributeString("hidden", XmlConvert.ToString(true)); } writer.WriteAttributeString("start_row", CultureInvariantToString(startRow[i])); writer.WriteAttributeString("start_column", CultureInvariantToString(startColumn[i])); writer.WriteAttributeString("end_row", CultureInvariantToString(endRow[i])); writer.WriteAttributeString("end_column", CultureInvariantToString(endColumn[i])); //EDMAURER allow there to be PDBs generated for sources that don't have a name (document). int fileRefVal = -1; this.m_fileMapping.TryGetValue(docs[i].URL, out fileRefVal); writer.WriteAttributeString("file_ref", CultureInvariantToString(fileRefVal)); writer.WriteEndElement(); } writer.WriteEndElement(); // sequencepoints }
public int GetMethodVersion(ISymbolMethod method) { int version; unmanagedReader.GetMethodVersion(((SymbolMethod)method).InternalMethod, out version); return version; }
// 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 void WriteSequencePoints(ISymbolMethod method) { m_writer.WriteStartElement("sequencepoints"); int count = method.SequencePointCount; m_writer.WriteAttributeString("total", Util.CultureInvariantToString(count)); // Get the sequence points from the symbol store. // We could cache these arrays and reuse them. var offsets = new int[count]; var docs = new ISymbolDocument[count]; var startColumn = new int[count]; var endColumn = new int[count]; var startRow = new int[count]; var endRow = new int[count]; method.GetSequencePoints(offsets, docs, startRow, startColumn, endRow, endColumn); // Write out sequence points for (int i = 0; i < count; i++) { m_writer.WriteStartElement("entry"); m_writer.WriteAttributeString("il_offset", Util.AsIlOffset(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) { m_writer.WriteAttributeString("hidden", XmlConvert.ToString(true)); } //else { m_writer.WriteAttributeString("start_row", Util.CultureInvariantToString(startRow[i])); m_writer.WriteAttributeString("start_column", Util.CultureInvariantToString(startColumn[i])); m_writer.WriteAttributeString("end_row", Util.CultureInvariantToString(endRow[i])); m_writer.WriteAttributeString("end_column", Util.CultureInvariantToString(endColumn[i])); m_writer.WriteAttributeString("file_ref", Util.CultureInvariantToString(m_fileMapping[docs[i].URL])); } m_writer.WriteEndElement(); } m_writer.WriteEndElement(); // sequencepoints }
// Write all the locals in the given method out to an XML file. // Since the symbol store represents the locals in a recursive scope structure, we need to walk a tree. // Although the locals are technically a hierarchy (based off nested scopes), it's easiest for clients // if we present them as a linear list. We will provide the range for each local's scope so that somebody // could reconstruct an approximation of the scope tree. The reconstruction may not be exact. // (Note this would still break down if you had an empty scope nested in another scope. private void WriteLocals(ISymbolMethod method) { m_writer.WriteStartElement("locals"); { // If there are no locals, then this element will just be empty. WriteLocalsHelper((ISymbolScope2) method.RootScope, true); } m_writer.WriteEndElement(); }
void ReadSequencePoints(ISymbolMethod method, Hashtable 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; } }
/// <summary> /// Create a new PDB method object from an ISymbolMethod object. /// </summary> /// <param name="meth">The ISymbolMethod object to wrap.</param> internal PDBMethod(ISymbolMethod meth) { _meth = meth; }
// 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; }
/// <summary> /// Releases all resources used by the MDbgFunction. /// </summary> public void Dispose() { // Release unmanaged resources, especially symbol readers m_function = null; m_symMethod = null; m_SPoffsets = null; m_SPdocuments = null; m_SPstartLines = null; m_SPendLines = null; m_SPstartColumns = null; m_SPendColumns = null; m_SPcount = 0; }
private List<SymAttribute> ReadSymAttributes(ISymbolReader reader, ISymbolMethod method, bool haveCSharpCDI) { List<SymAttribute> attrs = new List<SymAttribute>(); foreach (string name in AttributeNamesToSearch()) { // If this attirubte represents C# CDI data, and we were able to expand it, then indicate that // the attribute here is redundant (as a raw view) and shouldn't be included again. if (name == k_cSharpCDIAttrName && haveCSharpCDI) continue; // Note that despite being defined on ISymbolReader instead of ISymbolMethod, custom // attributes are permitted only on method metadata tokens. byte[] attrVal = reader.GetSymAttribute(method.Token, name); if (attrVal != null) { SymAttribute attr = new SymAttribute(); attr.name = name; attr.value = Util.ToHexString(attrVal); attrs.Add(attr); } } return attrs; }
ISymbolDocument[] GetDocumentList(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); return docs; }
// Write out XML snippet to refer to the given method. private void WriteMethod(ISymbolMethod method) { m_writer.WriteElementString("methodref", Util.AsToken(method.Token.GetToken())); }
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; } }
public ISymbolMethod[] GetMethodsFromDocumentPosition( ISymbolDocument document, int line, int column) { ISymUnmanagedMethod[] unmanagedMethods; ISymbolMethod[] methods; int count = 0; uint i; m_reader.GetMethodsFromDocumentPosition(((SymbolDocument)document).InternalDocument, line, column, 0, out count, null); unmanagedMethods = new ISymUnmanagedMethod[count]; m_reader.GetMethodsFromDocumentPosition(((SymbolDocument)document).InternalDocument, line, column, count, out count, unmanagedMethods); methods = new ISymbolMethod[count]; for (i = 0; i < count; i++) { methods[i] = new SymMethod(unmanagedMethods[i]); } return methods; }
public int GetMethodVersion(ISymbolMethod method) { int version = 0; m_reader.GetMethodVersion(((SymMethod)method).InternalMethod, out version); return version; }
////////////////////////////////////////////////////////////////////////////////// // // 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 SequencePointCollection(ISymbolMethod method) { this.Count = method.SequencePointCount; this.Offsets = new int[Count]; this.Lines = new int[Count]; this.Columns = new int[Count]; this.EndLines = new int[Count]; this.EndColumns = new int[Count]; this.Documents = new ISymbolDocument[Count]; Populate(method); }
// 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 void WriteSequencePoints(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); xmlWriter.WriteStartElement("sequencePoints"); for (int i = 0; i < count; i++) { xmlWriter.WriteStartElement("entry"); // IL offsets are usually written in hexadecimal... xmlWriter.WriteAttributeString("ilOffset", "0x" + offsets[i].ToString("x4")); // ... but .NET XPath 1.0 cannot compare strings so we need a decimal number as well :-( xmlWriter.WriteAttributeString("ilOffsetDec", offsets[i].ToString()); xmlWriter.WriteAttributeString("fileRef", fileMapping[docs[i].URL].ToString()); // If it's a special 0xfeefee sequence point (e.g., "hidden"), // place an attribute on it to make it very easy for tools to recognize. // See http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx if (startRow[i] == 0xfeefee) { xmlWriter.WriteAttributeString("hidden", "true"); } else { xmlWriter.WriteAttributeString("startLine", startRow[i].ToString()); xmlWriter.WriteAttributeString("startColumn", startColumn[i].ToString()); xmlWriter.WriteAttributeString("endLine", endRow[i].ToString()); xmlWriter.WriteAttributeString("endColumn", endColumn[i].ToString()); } xmlWriter.WriteEndElement(); // </entry> } xmlWriter.WriteEndElement(); // </sequencePoints> }
// Write out XML snippet to refer to the given method. private void WriteMethod(ISymbolMethod method) { xmlWriter.WriteElementString("methodRef", method.Token.GetToken().ToString("x8")); }