// 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); } }
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�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 }); }
/// <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); }
/// <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; } } }
public LocalVariableNameReader(MethodInfo m) { ISymbolReader symReader = SymUtil.GetSymbolReaderForFile(m.DeclaringType.Assembly.Location, null); ISymbolMethod met = symReader.GetMethod(new SymbolToken(m.MetadataToken)); VisitLocals(met.RootScope); }
// 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 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); }
public static ISymbolMethod GetSymbolMethod(this CorFunction func, CorDebuggerSession session) { ISymbolReader reader = session.GetReaderForModule(func.Module.Name); if (reader == null) { return(null); } return(reader.GetMethod(new SymbolToken(func.Token))); }
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 COR_DEBUG_STEP_RANGE[] getStepRanges(CorFrame frame, ISymbolReader reader, uint offset) { var method = reader.GetMethod(new SymbolToken(frame.FunctionToken)); foreach (var sp in new SequencePointFactory().Generate(method)) { if (sp.Offset > offset) return createStepRange(offset, sp.Offset); } return null; }
public MethodSymbol ReadMethodSymbol(int token) { var symbolMethod = _reader.GetMethod(new SymbolToken(token)); if (symbolMethod == null) { return(null); } return(new MethodSymbol(token, ReadSequencePoints(symbolMethod))); }
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); } }
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; } }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. private void WriteAllMethods(ISymbolReader reader) { m_writer.WriteComment("This is a list of all methods in the assembly that matches this PDB."); m_writer.WriteComment( "For each method, we provide the sequence tables that map from IL offsets back to source."); m_writer.WriteStartElement("methods"); // Use reflection to enumerate all methods foreach (Type t in m_assembly.GetTypes()) { foreach ( MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; m_writer.WriteStartElement("method"); { m_writer.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); m_writer.WriteAttributeString("token", Util.AsToken(token)); // This localSigMetadataToken information actually comes from the metadata in the assembly because the symbol reading API does not provide it. if (methodReflection.GetMethodBody() != null) { int lSMT = methodReflection.GetMethodBody().LocalSignatureMetadataToken; if (lSMT != 0) { m_writer.WriteAttributeString("localSigMetadataToken", Util.AsToken(lSMT)); } } ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { WriteSequencePoints(methodSymbol); WriteLocals(methodSymbol); ISymbolScope[] children = methodSymbol.RootScope.GetChildren(); if (children.Length != 0) { WriteScopes((ISymbolScope2)children[0]); } } } m_writer.WriteEndElement(); // method } } m_writer.WriteEndElement(); }
private void GetUniqDocsForMethod(ISymbolReader reader, Dictionary<string, int> uniqDocs,int metadataToken) { ISymbolMethod methodSymbol = null; try { methodSymbol = reader.GetMethod(new SymbolToken(metadataToken)); ISymbolDocument[] docs = GetDocumentList(methodSymbol); foreach (ISymbolDocument d in docs) { if (!uniqDocs.ContainsKey(d.URL)) uniqDocs[d.URL] = 1; } } catch (COMException) { } }
internal void InitializeMethodBody(ModuleDefMD module, MethodDef ownerMethod, CilBody body, uint methodRid) { Debug.Assert((module == null) == (ownerMethod == null)); if (reader == null || body == null) { return; } var token = new SymbolToken((int)(0x06000000 + methodRid)); ISymbolMethod method; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif method = reader.GetMethod(token); if (method != null) { var pdbMethod = new PdbMethod(); pdbMethod.Scope = CreateScope(module, ownerMethod == null ? new GenericParamContext() : GenericParamContext.Create(ownerMethod), body, method.RootScope); AddSequencePoints(body, method); var method2 = method as ISymbolMethod2; Debug.Assert(method2 != null); if (module != null && method2 != null && method2.IsAsyncMethod) { pdbMethod.AsyncMethod = CreateAsyncMethod(module, ownerMethod, body, method2); } if (ownerMethod != null) { // Read the custom debug info last so eg. local names have been initialized var cdiData = reader.GetSymAttribute(token, "MD2"); if (cdiData != null && cdiData.Length != 0) { PdbCustomDebugInfoReader.Read(ownerMethod, body, pdbMethod.CustomDebugInfos, cdiData); } } body.PdbMethod = pdbMethod; } #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif }
// Write out a reference to the entry point method (if one exists) private void WriteEntryPoint(ISymbolReader reader) { // If there is no entry point token (such as in a dll), this will throw. SymbolToken token = reader.UserEntryPoint; if (token.GetToken() == 0) { // If the Symbol APIs fail when looking for an entry point token, there is no entry point. return; } ISymbolMethod m = reader.GetMethod(token); xmlWriter.WriteStartElement("entryPoint"); WriteMethod(m); xmlWriter.WriteEndElement(); // </entryPoint> }
/// <summary> /// Return a particular method. /// </summary> /// <param name="token">The token to identify the method.</param> /// <returns>The method with the given token.</returns> public PDBMethod GetMethod(int token) { try { ISymbolMethod method = _reader.GetMethod(new SymbolToken(token)); if (method != null) { return(new PDBMethod(method)); } else { return(null); } } catch { return(null); // call fails on tokens which are not referenced } }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. private void WriteAllMethods(ISymbolReader reader) { xmlWriter.WriteStartElement("methods"); // Use reflection to enumerate all methods. // Skip all types that cannot be loaded. // Source: http://stackoverflow.com/a/7889272/143684 List <Type> types; try { types = assembly.GetTypes().ToList(); } catch (ReflectionTypeLoadException ex) { types = ex.Types.Where(t => t != null).ToList(); } foreach (Type t in types) { foreach (MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; xmlWriter.WriteStartElement("method"); xmlWriter.WriteAttributeString("token", "0x" + token.ToString("x8")); xmlWriter.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { WriteSequencePoints(methodSymbol); } xmlWriter.WriteEndElement(); // </method> } } xmlWriter.WriteEndElement(); // </methods> }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. void WriteAllMethods(ISymbolReader reader) { m_writer.WriteComment("This is a list of all methods in the assembly that matches this PDB."); m_writer.WriteComment("For each method, we provide the sequence tables that map from IL offsets back to source."); m_writer.WriteStartElement("methods"); // Use reflection to enumerate all methods foreach (Type t in m_assembly.GetTypes()) { foreach (MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; ISymbolMethod methodSymbol = null; m_writer.WriteStartElement("method"); { m_writer.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); m_writer.WriteAttributeString("token", Util.AsToken(token)); try { methodSymbol = reader.GetMethod(new SymbolToken(token)); WriteSequencePoints(methodSymbol); WriteLocals(methodSymbol); } catch (COMException e) { m_writer.WriteComment(String.Concat("No symbol info", e.Message)); } } m_writer.WriteEndElement(); // method } } m_writer.WriteEndElement(); }
/// <summary> /// Initializes a <see cref="CilBody"/> with information found in the PDB file. The /// instructions in <paramref name="body"/> must have valid offsets. This method is /// automatically called by <see cref="ModuleDefMD"/> and you don't need to explicitly call /// it. /// </summary> /// <param name="body">Method body</param> /// <param name="methodRid">Method row ID</param> public void InitializeDontCall(CilBody body, uint methodRid) { if (reader == null || body == null) { return; } var token = new SymbolToken((int)(0x06000000 + methodRid)); ISymbolMethod method; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif method = reader.GetMethod(token); if (method != null) { body.Scope = CreateScope(body, method.RootScope); AddSequencePoints(body, method); } //TODO: reader.GetSymAttribute() #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif }
/// <summary> /// Read the pdb file for this module and frame /// Retrieve infomation about the function /// </summary> /// <remarks> /// When an unmanaged app like reflector loads CLR, "Function.Module.Name" /// doesn't return a valid value and so this function returns null. /// </remarks> /// <returns>SourcePosition of the function</returns> private SourcePosition GetMetaDataInfo(CorMetadataImport importer) { SourcePosition functionPos = null; //position in this function where we are try { moduleFullName = thisFrame.Function.Module.Name; moduleShortName = System.IO.Path.GetFileName(moduleFullName); } catch (ArgumentException) { moduleFullName = ""; moduleShortName = ""; return(null); } //TODO: Implement a better method to determine the symbol path than just assuming it's in the same // directory string sympath = "."; //dealing with readinf the source in the module ISymbolReader metaReader = null; ISymbolBinder1 symbolBinder = new SymbolBinder(); try { if (moduleFullName.Length > 0) { metaReader = (symbolBinder as SymbolBinder). GetReaderForFile(importer.RawCOMObject, moduleFullName, sympath); } } catch (COMException) { //Debug.WriteLine(ed.ToString(CultureInfo.CurrentCulture.NumberFormat)); //will get here for any function which we cant read the .pdb file for //its not a big deal we just wont have source and line info } if (metaReader != null) { ISymbolMethod symMethod = null; try { symMethod = metaReader.GetMethod(new SymbolToken((int)thisFrame.Function.Token), thisFrame.Function.Version); int sequenceCount = symMethod.SequencePointCount; symDocs = new ISymbolDocument[sequenceCount]; offsets = new int[sequenceCount]; startLines = new int[sequenceCount]; startColumns = new int[sequenceCount]; endLines = new int[sequenceCount]; endColumns = new int[sequenceCount]; //Get the sequence points and store them in the apporpriate arrays. Seqeunce points //represent the different points in the files which correlate to il instruction and lines symMethod.GetSequencePoints(offsets, symDocs, startLines, startColumns, endLines, endColumns); functionPos = GetSourcePositionFromFrame(); } catch (COMException) { functionPos = null; } finally { symDocs = null; symMethod = null; } } CorType ctype = GetClassType(); if (ctype != null) { StringBuilder sb = new StringBuilder(); GetFunctionClassPath(sb, ctype); functionFullName = sb.ToString(); } else { functionFullName = ""; } MethodInfo methIn = importer.GetMethodInfo(thisFrame.Function.Token); functionFullName += "." + methIn.Name; functionShortName = methIn.Name; return(functionPos); }
private void GetUniqDocsForMethod(ISymbolReader reader, Dictionary<string, int> uniqDocs,int metadataToken) { ISymbolMethod methodSymbol = null; try { methodSymbol = reader.GetMethod(new SymbolToken(metadataToken)); ISymbolDocument[] docs = GetDocumentList(methodSymbol); foreach (ISymbolDocument d in docs) { if (!uniqDocs.ContainsKey(d.URL)) uniqDocs[d.URL] = 1; } } catch (COMException) { } }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. void WriteAllMethods(ISymbolReader reader) { m_writer.WriteComment("This is a list of all methods in the assembly that matches this PDB."); m_writer.WriteComment("For each method, we provide the sequence tables that map from IL offsets back to source."); m_writer.WriteStartElement("methods"); // Use reflection to enumerate all methods foreach (Type t in m_assembly.GetTypes()) { foreach (MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; ISymbolMethod methodSymbol = null; m_writer.WriteStartElement("method"); { m_writer.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); m_writer.WriteAttributeString("token", Util.AsToken(token)); try { methodSymbol = reader.GetMethod(new SymbolToken(token)); WriteSequencePoints(methodSymbol); WriteLocals(methodSymbol); } catch (COMException ) { m_writer.WriteComment("No symbol info"); } } m_writer.WriteEndElement(); // method } } m_writer.WriteEndElement(); }
private void setBreakpointThroughModule(CorModule module, ISymbolReader reader) { var token = reader.UserEntryPoint; if (hasNoApplicationEntryPoint(token)) return; var method = reader.GetMethod(token); var function = module.GetFunctionFromToken(method.Token.GetToken()); var br = function.CreateBreakpoint(); br.Activate(true); }
/// <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 static SequencePoint GetSequencePoint(CorDebuggerSession session, CorFrame frame) { ISymbolReader reader = session.GetReaderForModule(frame.Function.Module); if (reader == null) { return(null); } ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token)); if (met == null) { return(null); } int SequenceCount = met.SequencePointCount; if (SequenceCount <= 0) { return(null); } CorDebugMappingResult mappingResult; uint ip; frame.GetIP(out ip, out mappingResult); if (mappingResult == CorDebugMappingResult.MAPPING_NO_INFO || mappingResult == CorDebugMappingResult.MAPPING_UNMAPPED_ADDRESS) { return(null); } int[] offsets = new int[SequenceCount]; int[] lines = new int[SequenceCount]; int[] endLines = new int[SequenceCount]; int[] columns = new int[SequenceCount]; int[] endColumns = new int[SequenceCount]; ISymbolDocument[] docs = new ISymbolDocument[SequenceCount]; met.GetSequencePoints(offsets, docs, lines, columns, endLines, endColumns); if ((SequenceCount > 0) && (offsets [0] <= ip)) { int i; for (i = 0; i < SequenceCount; ++i) { if (offsets [i] >= ip) { break; } } if ((i == SequenceCount) || (offsets [i] != ip)) { --i; } if (lines [i] == SpecialSequencePoint) { int j = i; // let's try to find a sequence point that is not special somewhere earlier in the code // stream. while (j > 0) { --j; if (lines [j] != SpecialSequencePoint) { return(new SequencePoint() { IsSpecial = true, Offset = offsets [j], StartLine = lines [j], EndLine = endLines [j], StartColumn = columns [j], EndColumn = endColumns [j], Document = docs [j] }); } } // we didn't find any non-special seqeunce point before current one, let's try to search // after. j = i; while (++j < SequenceCount) { if (lines [j] != SpecialSequencePoint) { return(new SequencePoint() { IsSpecial = true, Offset = offsets [j], StartLine = lines [j], EndLine = endLines [j], StartColumn = columns [j], EndColumn = endColumns [j], Document = docs [j] }); } } // Even if sp is null at this point, it's a valid scenario to have only special sequence // point in a function. For example, we can have a compiler-generated default ctor which // doesn't have any source. return(null); } else { return(new SequencePoint() { IsSpecial = false, Offset = offsets [i], StartLine = lines [i], EndLine = endLines [i], StartColumn = columns [i], EndColumn = endColumns [i], Document = docs [i] }); } } return(null); }
private List<Method> ReadAllMethods(ISymbolReader reader) { List<Method> methods = new List<Method>(); foreach (MethodData methodReflection in GetAllMethods(_assemblyPath)) { int token = methodReflection.Token; ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { Method methodData = new Method(); methodData.token = Util.AsToken(token); methodData.name = 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(); //if (body != null) //{ int lSMT = methodReflection.SignatureToken; 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; }
private Variable[] getVariables(ISymbolReader reader) { var variables = new List<Variable>(); try { var method = reader.GetMethod(new SymbolToken(_thread.ActiveFrame.Function.Token)); var scope = method.RootScope; variables.AddRange(enumerateLocals(scope)); } catch (Exception exception) { } return variables.ToArray(); }
void Step(bool into) { if (stepper != null) { stepper.IsActive(); CorFrame frame = activeThread.ActiveFrame; ISymbolReader reader = GetReaderForModule(frame.Function.Module.Name); if (reader == null) { RawContinue(into); return; } ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token)); if (met == null) { RawContinue(into); return; } uint offset; CorDebugMappingResult mappingResult; frame.GetIP(out offset, out mappingResult); // Find the current line SequencePoint currentSeq = null; foreach (SequencePoint sp in met.GetSequencePoints()) { if (sp.Offset > offset) { break; } currentSeq = sp; } if (currentSeq == null) { RawContinue(into); return; } // Exclude all ranges belonging to the current line List <COR_DEBUG_STEP_RANGE> ranges = new List <COR_DEBUG_STEP_RANGE> (); SequencePoint lastSeq = null; foreach (SequencePoint sp in met.GetSequencePoints()) { if (lastSeq != null && lastSeq.Line == currentSeq.Line) { COR_DEBUG_STEP_RANGE r = new COR_DEBUG_STEP_RANGE(); r.startOffset = (uint)lastSeq.Offset; r.endOffset = (uint)sp.Offset; ranges.Add(r); } lastSeq = sp; } stepper.StepRange(into, ranges.ToArray()); ClearEvalStatus(); process.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN, null); process.Continue(false); } }
internal static StackFrame CreateFrame(CorDebuggerSession session, CorFrame frame) { // TODO: Fix remaining. uint address = 0; //string typeFQN; //string typeFullName; string addressSpace = ""; string file = ""; int line = 0; int column = 0; string method = ""; string lang = ""; string module = ""; string type = ""; bool hasDebugInfo = false; bool hidden = false; bool external = true; if (frame.FrameType == CorFrameType.ILFrame) { if (frame.Function != null) { module = frame.Function.Module.Name; CorMetadataImport importer = new CorMetadataImport(frame.Function.Module); MethodInfo mi = importer.GetMethodInfo(frame.Function.Token); method = mi.DeclaringType.FullName + "." + mi.Name; type = mi.DeclaringType.FullName; addressSpace = mi.Name; ISymbolReader reader = session.GetReaderForModule(frame.Function.Module.Name); if (reader != null) { ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token)); if (met != null) { CorDebugMappingResult mappingResult; frame.GetIP(out address, out mappingResult); SequencePoint prevSp = null; foreach (SequencePoint sp in met.GetSequencePoints()) { if (sp.Offset > address) { break; } prevSp = sp; } if (prevSp != null) { line = prevSp.Line; column = prevSp.Offset; file = prevSp.Document.URL; address = (uint)prevSp.Offset; } } } // FIXME: Still steps into. //hidden = mi.GetCustomAttributes (true).Any (v => v is System.Diagnostics.DebuggerHiddenAttribute); } lang = "Managed"; hasDebugInfo = true; } else if (frame.FrameType == CorFrameType.NativeFrame) { frame.GetNativeIP(out address); method = "<Unknown>"; lang = "Native"; } else if (frame.FrameType == CorFrameType.InternalFrame) { switch (frame.InternalFrameType) { case CorDebugInternalFrameType.STUBFRAME_M2U: method = "[Managed to Native Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_U2M: method = "[Native to Managed Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: method = "[Lightweight Method Call]"; break; case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: method = "[Application Domain Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: method = "[Function Evaluation]"; break; } } if (method == null) { method = "<Unknown>"; } var loc = new SourceLocation(method, file, line, column); return(new StackFrame((long)address, addressSpace, loc, lang, external, hasDebugInfo, hidden, null, null)); }
// Write out a reference to the entry point method (if one exists) private void WriteEntryPoint(ISymbolReader reader) { // If there is no entry point token (such as in a dll), this will throw. SymbolToken token = reader.UserEntryPoint; if (token.GetToken() == 0) { // 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'"); return; } 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(); }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. private void WriteAllMethods(ISymbolReader reader) { m_writer.WriteComment("This is a list of all methods in the assembly that matches this PDB."); m_writer.WriteComment( "For each method, we provide the sequence tables that map from IL offsets back to source."); m_writer.WriteStartElement("methods"); // Use reflection to enumerate all methods foreach (Type t in m_assembly.GetTypes()) { foreach ( MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; m_writer.WriteStartElement("method"); { m_writer.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); m_writer.WriteAttributeString("token", Util.AsToken(token)); // This localSigMetadataToken information actually comes from the metadata in the assembly because the symbol reading API does not provide it. if (methodReflection.GetMethodBody() != null) { int lSMT = methodReflection.GetMethodBody().LocalSignatureMetadataToken; if (lSMT != 0) { m_writer.WriteAttributeString("localSigMetadataToken", Util.AsToken(lSMT)); } } ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { WriteSequencePoints(methodSymbol); WriteLocals(methodSymbol); ISymbolScope[] children = methodSymbol.RootScope.GetChildren(); if (children.Length != 0) { WriteScopes((ISymbolScope2) children[0]); } } } m_writer.WriteEndElement(); // method } } m_writer.WriteEndElement(); }
private Snapshot get_location(ISymbolReader reader) { var frame = _thread.ActiveFrame; var function = frame.Function; uint offset; CorDebugMappingResult mapping_result; frame.GetIP(out offset, out mapping_result); SequencePoint real_sp = null; try { var method = reader.GetMethod(new SymbolToken(frame.Function.Token)); foreach (var sp in new SequencePointFactory().Generate(method)) { if (sp.Offset > offset) break; if (sp.LineStart != 0xfeefee) real_sp = sp; } } catch (Exception) { // If we cant fint symbol method ignore } if (real_sp == null) return null; // string.Format("Location (offset {0})", offset); return new Snapshot(new Position(real_sp.Document.URL, real_sp.Offset, real_sp.LineStart, real_sp.LineStartColumn, real_sp.LineEnd, real_sp.LineEndColumn)); }
// Write out a reference to the entry point method (if one exists) private void WriteEntryPoint(ISymbolReader reader) { // If there is no entry point token (such as in a dll), this will throw. SymbolToken token = reader.UserEntryPoint; if (token.GetToken() == 0) { // If the Symbol APIs fail when looking for an entry point token, there is no entry point. return; } ISymbolMethod m = reader.GetMethod(token); xmlWriter.WriteStartElement("entryPoint"); WriteMethod(m); xmlWriter.WriteEndElement(); // </entryPoint> }
internal static StackFrame CreateFrame(CorDebuggerSession session, CorFrame frame) { uint address = 0; string file = ""; int line = 0; string method = ""; string lang = ""; string module = ""; if (frame.FrameType == CorFrameType.ILFrame) { if (frame.Function != null) { module = frame.Function.Module.Name; CorMetadataImport importer = new CorMetadataImport(frame.Function.Module); MethodInfo mi = importer.GetMethodInfo(frame.Function.Token); method = mi.DeclaringType.FullName + "." + mi.Name; ISymbolReader reader = session.GetReaderForModule(frame.Function.Module.Name); if (reader != null) { ISymbolMethod met = reader.GetMethod(new SymbolToken(frame.Function.Token)); if (met != null) { uint offset; CorDebugMappingResult mappingResult; frame.GetIP(out offset, out mappingResult); SequencePoint prevSp = null; foreach (SequencePoint sp in met.GetSequencePoints()) { if (sp.Offset > offset) { break; } prevSp = sp; } if (prevSp != null) { line = prevSp.Line; file = prevSp.Document.URL; } } } } lang = "Managed"; } else if (frame.FrameType == CorFrameType.NativeFrame) { frame.GetNativeIP(out address); method = "<Unknown>"; lang = "Native"; } else if (frame.FrameType == CorFrameType.InternalFrame) { switch (frame.InternalFrameType) { case CorDebugInternalFrameType.STUBFRAME_M2U: method = "[Managed to Native Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_U2M: method = "[Native to Managed Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: method = "[Lightweight Method Call]"; break; case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: method = "[Application Domain Transition]"; break; case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: method = "[Function Evaluation]"; break; } } if (method == null) { method = "<Unknown>"; } return(new StackFrame((long)address, module, method, file, line, lang)); }
// Dump all of the methods in the given ISymbolReader to the XmlWriter provided in the ctor. private void WriteAllMethods(ISymbolReader reader) { xmlWriter.WriteStartElement("methods"); // Use reflection to enumerate all methods. // Skip all types that cannot be loaded. // Source: http://stackoverflow.com/a/7889272/143684 List<Type> types; try { types = assembly.GetTypes().ToList(); } catch (ReflectionTypeLoadException ex) { types = ex.Types.Where(t => t != null).ToList(); } foreach (Type t in types) { foreach (MethodInfo methodReflection in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { int token = methodReflection.MetadataToken; xmlWriter.WriteStartElement("method"); xmlWriter.WriteAttributeString("token", "0x" + token.ToString("x8")); xmlWriter.WriteAttributeString("name", t.FullName + "." + methodReflection.Name); ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token)); if (methodSymbol != null) { WriteSequencePoints(methodSymbol); } xmlWriter.WriteEndElement(); // </method> } } xmlWriter.WriteEndElement(); // </methods> }