private Parameter[] getParameters() { var parameters = new List<Parameter>(); var metadata_import = new CorMetadataImport(_thread.ActiveFrame.Function.Module); var method_info = metadata_import.GetMethodInfo(_thread.ActiveFrame.FunctionToken); foreach (var parameter in method_info.GetParameters()) { var argument = _thread.ActiveFrame.GetArgument(parameter.Position - 1); parameters.Add(new Parameter(parameter.Name, getValue(argument))); } return parameters.ToArray(); }
/// <summary> /// Constructor /// </summary> /// <param name="frame">The CorFrame frame object</param> /// <param name="importer">The meta data importer for the module this frame is contained within</param> internal FrameInfo(CorFrame frame, CorMetadataImport importer) { if (frame == null) { throw new ArgumentNullException("frame"); } if (importer == null) { throw new ArgumentNullException("importer"); } thisFrame = frame; metaImporter = importer; functionShortName = ""; functionFullName = ""; moduleShortName = ""; moduleFullName = ""; functionFileName = ""; functionLineNumber = -1;//-1 is set by deafult which means no line number SourcePosition functionPos = null; //position in this function where we are //make binder and reader for the metadata if (thisFrame.FrameType == CorFrameType.InternalFrame) { functionFullName = functionShortName = InternalFrameToString(); } else { functionPos = GetMetaDataInfo(importer); } if (functionPos != null) { functionLineNumber = functionPos.Line; functionFileName = Path.GetFileName(functionPos.Path); } else { ResourceManager stackStrings = new ResourceManager(typeof(Resources)); functionLineNumber = -1;//no line number available functionFileName = stackStrings.GetString("sourceUnavailable"); } }
private ISymbolReader getSymbolReader(CorModule module) { ISymbolReader reader = null; string sympath = Path.GetDirectoryName(module.Name); string moduleName = module.Name; try { SymbolBinder binder = new SymbolBinder(); var importer = new CorMetadataImport(module); reader = binder.GetReaderForFile(importer.RawCOMObject, moduleName, sympath); } catch (COMException ex) { if (ex.ErrorCode == unchecked((int)0x806D0014)) // E_PDB_CORRUPT { // Ignore it. // This may happen for mismatched pdbs } else throw; } return reader; }
void OnModuleLoad (object sender, CorModuleEventArgs e) { CorMetadataImport mi = new CorMetadataImport (e.Module); try { // Required to avoid the jit to get rid of variables too early e.Module.JITCompilerFlags = CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION; } catch { // Some kind of modules don't allow JIT flags to be changed. } string file = e.Module.Assembly.Name; lock (documents) { ISymbolReader reader = null; if (file.IndexOfAny (System.IO.Path.InvalidPathChars) == -1 && System.IO.File.Exists (System.IO.Path.ChangeExtension (file, ".pdb"))) { try { reader = symbolBinder.GetReaderForFile (mi.RawCOMObject, file, "."); foreach (ISymbolDocument doc in reader.GetDocuments ()) { if (string.IsNullOrEmpty (doc.URL)) continue; string docFile = System.IO.Path.GetFullPath (doc.URL); DocInfo di = new DocInfo (); di.Document = doc; di.Reader = reader; di.Module = e.Module; documents[docFile] = di; NotifySourceFileLoaded (docFile); } } catch (Exception ex) { OnDebuggerOutput (true, string.Format ("Debugger Error: {0}\n", ex.Message)); } e.Module.SetJmcStatus (true, null); } else { // Flag modules without debug info as not JMC. In this way // the debugger won't try to step into them e.Module.SetJmcStatus (false, null); } ModuleInfo moi; if (modules.TryGetValue (e.Module.Name, out moi)) { moi.References++; } else { moi = new ModuleInfo (); moi.Module = e.Module; moi.Reader = reader; moi.Importer = mi; moi.References = 1; modules[e.Module.Name] = moi; } } e.Continue = true; }
void OnUpdateModuleSymbols (object sender, CorUpdateModuleSymbolsEventArgs e) { SymbolBinder binder = new SymbolBinder (); CorMetadataImport mi = new CorMetadataImport (e.Module); ISymbolReader reader = binder.GetReaderFromStream (mi.RawCOMObject, e.Stream); foreach (ISymbolDocument doc in reader.GetDocuments ()) { Console.WriteLine (doc.URL); } e.Continue = true; }
internal static StackFrame CreateFrame (CorDebuggerSession session, CorFrame frame) { uint address = 0; string file = ""; int line = 0; string method = ""; string lang = ""; string module = ""; string type = ""; 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; 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>"; var loc = new SourceLocation (method, file, line); return new StackFrame ((long) address, loc, lang); }
public TypeDefEnum(CorMetadataImport corMeta) { m_corMeta = corMeta; }
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); }
//methods /// <summary> /// Loop through all frames in thread getting info on them then building /// a arrayList representation of the stack trace with them /// If called when already attached it will skip attaching and detaching and let the function that called it worry about that /// otherwise this function will deal with attaching and deataching /// </summary> /// <param name="depth">How many frames deep to display, 0 means show all</param> public void UpdateStackTrace(int depth) { frameStack.Clear(); //not needed right now cause this class is remade each update bool enteredAttached = processInfo.Attached; if (!enteredAttached) { processInfo.AttachAndStop(); } try { int frameNum = 0; foreach (CorChain chain in thread.Chains) { foreach (CorFrame frame in chain.Frames) { if ((frameNum >= depth) && (depth != 0)) { break; } if (frame.Function == null) { continue; } CorModule module = frame.Function.Module; string moduleName = module.Name; CorMetadataImport importer = null; if (metaImportHash.ContainsKey(moduleName)) { importer = metaImportHash[moduleName] as CorMetadataImport; } else {//make a new importer then add it to the hash importer = new CorMetadataImport(module); metaImportHash[moduleName] = importer; } //add the next frame to the frame stack frameStack.Add(new FrameInfo(frame, importer)); frameNum++; } if ((frameNum > depth) && (depth != 0)) { break; } } } catch (COMException ex) { Debug.WriteLine(ex.ToString()); } finally { if (!enteredAttached) { processInfo.DetachAndResume(); } } }
/// <summary> /// Dispose managed and unmanaged objects /// </summary> /// <param name="disposing">Dispose managed objects</param> protected virtual void Dispose(bool disposing) { if (disposing) { // Free other state (managed objects). metaImporter = null; symDocs = null; offsets = null; startLines = null; endLines = null; startColumns = null; endColumns = null; } // Free your own state (unmanaged objects). }
/// <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 ISymbolBinder2). 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; }
public void ShowStackTrace(CorThread thread) { var builder = new StringBuilder(); foreach (CorFrame frame in thread.ActiveChain.Frames) { if (frame.FrameType == CorFrameType.ILFrame) builder.AppendLine("[IL]"); var import = new CorMetadataImport(frame.Function.Module); MethodInfo methodInfo = import.GetMethodInfo(frame.FunctionToken); builder.AppendLine(string.Format("{0}:{1}", methodInfo.DeclaringType, methodInfo.Name)); } subscriber.PublishedSource(builder.ToString()); subscriber.Stopped(this, thread); }
public static void Disassemble(byte[] ilCode, CorMetadataImport importer, out string[] lines, out int[] ip2line) { ArrayList ils = new ArrayList(); ip2line = new int[ilCode.Length]; int pc = 0; while (pc < ilCode.Length) { string instruction = ""; int instruction_start = pc; int opCodeSize; ILOpCode opCode = DecodeOpcode(ilCode, pc, out opCodeSize); pc += opCodeSize; switch ((OpcodeFormat)GenTables.opCodeTypeInfo[(int)opCode].Type) { default: Debug.Assert(false); break; case OpcodeFormat.InlineNone: instruction = GenTables.opCodeTypeInfo[(int)opCode].Name; break; case OpcodeFormat.ShortInlineI: case OpcodeFormat.ShortInlineVar: { byte arg = ilCode[pc]; pc++; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.InlineVar: { Int16 arg = BitConverter.ToInt16(ilCode, pc); pc += 2; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.InlineI: case OpcodeFormat.InlineRVA: { Int32 arg = BitConverter.ToInt32(ilCode, pc); pc += 4; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.InlineI8: { Int64 arg = BitConverter.ToInt64(ilCode, pc); pc += 8; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.ShortInlineR: { float arg = BitConverter.ToSingle(ilCode, pc); pc += 4; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.InlineR: { double arg = BitConverter.ToDouble(ilCode, pc); pc += 8; instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.ShortInlineBrTarget: { sbyte offset = (sbyte)ilCode[pc]; pc++; int dest = pc + offset; instruction = String.Format(CultureInfo.InvariantCulture, "{0} IL_{1,-4:X}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, dest}); break; } case OpcodeFormat.InlineBrTarget: { Int32 offset = BitConverter.ToInt32(ilCode, pc); pc += 4; int dest = pc + offset; instruction = String.Format(CultureInfo.InvariantCulture, "{0} IL_{1,-4:X}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, dest}); break; } case OpcodeFormat.InlineSwitch: case OpcodeFormat.InlinePhi: instruction = "MESSED UP!"; // variable size Debug.Assert(false); break; case OpcodeFormat.InlineString: case OpcodeFormat.InlineField: case OpcodeFormat.InlineType: case OpcodeFormat.InlineToken: case OpcodeFormat.InlineMethod: { int token = BitConverter.ToInt32(ilCode, pc); pc += 4; CorTokenType tokenType = TokenUtils.TypeFromToken(token); // if it is reference token we need to dereference it. string arg = null; switch (tokenType) { default: Debug.Assert(false); break; case CorTokenType.mdtTypeDef: int extendsToken; arg = importer.GetTypeNameFromDef(token, out extendsToken); break; case CorTokenType.mdtTypeRef: arg = importer.GetTypeNameFromRef(token); break; case CorTokenType.mdtTypeSpec: arg = "NYI"; break; case CorTokenType.mdtMethodDef: MethodInfo mi = importer.GetMethodInfo(token); Type dt = mi.DeclaringType; arg = (dt == null ? "" : dt.Name) + "." + mi.Name; break; case CorTokenType.mdtFieldDef: arg = "NYI"; break; case CorTokenType.mdtMemberRef: arg = importer.GetMemberRefName(token); break; case CorTokenType.mdtString: arg = "\"" + importer.GetUserString(token) + "\""; break; } // switch(tokenType) instruction = String.Format(CultureInfo.InvariantCulture, "{0} {1}", new Object[]{GenTables.opCodeTypeInfo[(int)opCode].Name, arg}); break; } case OpcodeFormat.InlineSig: instruction = GenTables.opCodeTypeInfo[(int)opCode].Name; pc += 4; break; } // switch((OpcodeFormat)GenTables.opCodeTypeInfo[(int)opCode].Type) ils.Add(String.Format(CultureInfo.InvariantCulture, "IL_{0,-4:X}: {1}", new Object[] { instruction_start, instruction })); // add ip2line mapping for (int i = instruction_start; i < pc; i++) ip2line[i] = ils.Count - 1; // last line } // while(pc<ilCode.Length) lines = (string[])ils.ToArray(typeof(string)); return; }
/// <summary> /// Releases all resources used by the MDbgModule. /// </summary> public void Dispose() { // Our funtion list may hold onto unmanaged SymbolMethod objects, so dispose that too. m_functions.Dispose(); m_functions = null; // Release unmanaged resources if (m_symReader != null) { // Disposing the symbol reader will release the file lock on the PDB (even when other // reader COM objects have yet to be released by the garbage collector). ((IDisposable)m_symReader).Dispose(); m_symReader = null; } m_module = null; m_importer = null; }
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 endLine = 0; int column = 0; int endColumn = 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; var sp = GetSequencePoint (session, frame); if (sp != null) { line = sp.StartLine; column = sp.StartColumn; endLine = sp.EndLine; endColumn = sp.EndColumn; file = sp.Document.URL; address = (uint)sp.Offset; } if (session.IsExternalCode (file)) { external = true; } else { if (session.Options.ProjectAssembliesOnly) { external = mi.GetCustomAttributes (true).Any (v => v is System.Diagnostics.DebuggerHiddenAttribute || v is System.Diagnostics.DebuggerNonUserCodeAttribute); } else { external = mi.GetCustomAttributes (true).Any (v => v is System.Diagnostics.DebuggerHiddenAttribute); } } 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, endLine, endColumn); return new StackFrame ((long)address, addressSpace, loc, lang, external, hasDebugInfo, hidden, null, null); }
/// <summary> /// Releases all resources used by the MDbgModule. /// </summary> public void Dispose() { // Our funtion list may hold onto unmanaged SymbolMethod objects, so dispose that too. m_functions.Dispose(); m_functions = null; // Release unmanaged resources. m_symReader = null; m_module = null; m_importer = null; }