public static System.Reflection.MethodInfo GetMethodInfo(this CorFunction func, CorDebuggerSession session) { CorMetadataImport mi = session.GetMetadataForModule(func.Module.Name); if (mi != null) { return(mi.GetMethodInfo(func.Token)); } else { return(null); } }
/*private void CorProcess_OnStepComplete(object sender, CorStepCompleteEventArgs e) * { * // if (iCount++ % 100 == 0 && logOnBreakpoint) * DI.log.info("[{0}] CorProcess_OnStepComplete {1}", iStepCount++, getActiveFrameFunctionName(e)); * e.Continue = handleDebugFlowAction(); * } * * private void CorProcess_OnBreakpointSetError(object sender, CorBreakpointEventArgs e) * { * if (logOnBreakpoint) * DI.log.info("CorProcess_OnBreakpointSetError {0}", getActiveFrameFunctionName(e)); * e.Continue = true; * } * * private void CorProcess_OnBreakpoint(object sender, CorBreakpointEventArgs e) * { * DI.log.info("in CorProcess_OnBreakpoint"); * /*( if (handleBreakpoints) * { * if (logOnBreakpoint) * log.info("Breakpoint on {0}", getActiveFrameFunctionName(e)); * e.Continue = handleDebugFlowAction(); * }* / * e.Continue = true; * } * * private bool handleDebugFlowAction() * { * switch (onBreakPointAction) * { * case OnBreakPointAction.StepOut: * o2MDbgOLD.mdbgProcess.StepOut(); * break; * case OnBreakPointAction.StepInto: * o2MDbgOLD.mdbgProcess.StepInto(false); * break; * case OnBreakPointAction.StepOver: * o2MDbgOLD.mdbgProcess.StepOver(false); * break; * * case OnBreakPointAction.Stop: * return false; * case OnBreakPointAction.Continue: * return true; * } * return true; * } */ public static string getActiveFrameFunctionName(CorEventArgs e) { try { if (e.Thread.ActiveFrame == null) { return("e.Thread.ActiveFrame == null"); } //var corFunctionBreakpoint = (CorFunctionBreakpoint)e.Breakpoint; var corMetadataImport = new CorMetadataImport(e.Thread.ActiveFrame.Function.Class.Module); MethodInfo methodInfo = corMetadataImport.GetMethodInfo(e.Thread.ActiveFrame.Function.Token); return((methodInfo.DeclaringType.FullName ?? "(null)") + " :: " + (methodInfo.Name ?? "(null)")); } catch (Exception ex) { DI.log.ex(ex, "getActiveFrameFunctionName"); return(""); } }
internal static StackFrame CreateFrame(CorDebuggerSession session, CorFrame frame) { uint address = 0; string addressSpace = ""; string file = ""; int line = 0; int endLine = 0; int column = 0; int endColumn = 0; string method = "[Unknown]"; 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); var declaringType = mi.DeclaringType; if (declaringType != null) { method = declaringType.FullName + "." + mi.Name; type = declaringType.FullName; } else { method = mi.Name; } 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 = "[Native frame]"; 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; } } var loc = new SourceLocation(method, file, line, column, endLine, endColumn); return(new StackFrame(address, addressSpace, loc, lang, external, hasDebugInfo, hidden, module, type)); }
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)); }
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; }
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)); }
/// <summary> /// Builds a string representation of an internal frame /// With info like what type of internal frame it is /// </summary> /// <returns>string representation of internal frame</returns> private string InternalFrameToString() { Debug.Assert(thisFrame.FrameType == CorFrameType.InternalFrame); StringBuilder sb = new StringBuilder(); sb.Append("[Internal thisFrame, "); switch (thisFrame.InternalFrameType) { case CorDebugInternalFrameType.STUBFRAME_M2U: sb.Append("'M-->U', "); break; case CorDebugInternalFrameType.STUBFRAME_U2M: sb.Append("'U-->M', "); break; case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: sb.Append("'AD switch':(AD '"); CorFrame c = thisFrame.Caller; if (c != null) { sb.Append(c.Function.Module.Assembly.AppDomain.Name); } sb.Append("'. #"); if (c != null) { sb.Append(c.Function.Module.Assembly.AppDomain.Id); } sb.Append(") -->(AD '"); c = thisFrame.Callee; if (c != null) { sb.Append(c.Function.Module.Assembly.AppDomain.Name); } sb.Append("'. #"); if (c != null) { sb.Append(c.Function.Module.Assembly.AppDomain.Id); } sb.Append(")]"); return(sb.ToString()); case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: sb.Append("'Dynamic Method', "); break; case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: sb.Append("'FuncEval', "); break; case CorDebugInternalFrameType.STUBFRAME_NONE: default: sb.Append("'Unknown Type', "); break; } Type t = null; try { MethodInfo methin = metaImporter.GetMethodInfo(thisFrame.Function.Token); t = methin.DeclaringType; sb.Append((t == null ? "<module>" : t.FullName)) .Append("::") .Append((methin == null) ? "<unknown function>" : methin.Name); } catch (COMException ex) { if (ex.ErrorCode != (int)HResult.CORDBG_E_CODE_NOT_AVAILABLE) { throw; } sb.Append(String.Format(CultureInfo.CurrentCulture.NumberFormat, "(no function, hr=0x{0:x})", ex.ErrorCode)); } sb.Append("]"); return(sb.ToString()); }
/// <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); }