/// <summary> /// Gets the SourcePosition from a given CorFrame. /// </summary> /// <param name="frame">The CorFrame.</param> /// <returns>The SourcePosition of the given frame.</returns> private SourcePosition GetSourcePositionFromFrame() { uint ip; CorDebugMappingResult mappingResult; thisFrame.GetIP(out ip, out mappingResult); // MAPPING_APPROXIMATE, MAPPING_EXACT, MAPPING_PROLOG, or MAPPING_EPILOG are all ok and we should show sources. // But these two indicate that something went wrong and nothing is available. if (mappingResult == CorDebugMappingResult.MAPPING_NO_INFO || mappingResult == CorDebugMappingResult.MAPPING_UNMAPPED_ADDRESS) { return(null); } return(GetSourcePositionFromIP((int)ip)); }
/// <summary> /// Gets the MDbgSourcePosition from a given CorFrame. /// </summary> /// <param name="frame">The CorFrame.</param> /// <returns>The MDbgSourcePosition of the given frame.</returns> public MDbgSourcePosition GetSourcePositionFromFrame(CorFrame frame) { // EnsureIsUpToDate is called from GetSourcePositionFromIP // we only support this, when the frame is our function Debug.Assert(frame.FunctionToken == m_function.Token); uint ip; CorDebugMappingResult mappingResult; frame.GetIP(out ip, out mappingResult); // MAPPING_APPROXIMATE, MAPPING_EXACT, MAPPING_PROLOG, or MAPPING_EPILOG are all ok and we should show sources. // But these two indicate that something went wrong and nothing is available. if (mappingResult == CorDebugMappingResult.MAPPING_NO_INFO || mappingResult == CorDebugMappingResult.MAPPING_UNMAPPED_ADDRESS) { return(null); } return(GetSourcePositionFromIP((int)ip)); }
// Does the real work for an IL step. // fStepIn - true if step in; else false for step-over. // fVerbose - true if we should print out verbose diagnostic information. public static void ILStepWorker(bool stepIn, bool isVerbose, string args) { if ((args != null) && (args.Trim().Length > 0)) { throw new MDbgShellException("no arguments expected."); } // Do an IL-level step by single-stepping native code until our IL IP changes. MDbgProcess proc = GuiExtension.Shell.Debugger.Processes.Active; CorFrame curFrame = proc.Threads.Active.CurrentFrame.CorFrame; uint ipNative; uint offsetStart; uint offsetNew; ulong oldStackStart; ulong oldStackEnd; ulong newStackStart; ulong newStackEnd; CorDebugMappingResult result; curFrame.GetIP(out offsetStart, out result); curFrame.GetStackRange(out oldStackStart, out oldStackEnd); curFrame.GetNativeIP(out ipNative); if (isVerbose) { WriteOutput(String.Format(" IL step starting at offset IL_{0:x}, N=0x{1:x}, frame=({2:x},{3:x})", offsetStart, ipNative, oldStackStart, oldStackEnd)); } // We'll just do native single-steps until our IL ip changes. while (true) { // Single step native code. if (stepIn) { proc.StepInto(true).WaitOne(); } else { proc.StepOver(true).WaitOne(); } // Since we continued the process, our old frame becomes invalid and we need to get a new one. curFrame = proc.Threads.Active.CurrentFrame.CorFrame; curFrame.GetStackRange(out newStackStart, out newStackEnd); if ((newStackStart != oldStackStart) || (newStackEnd != oldStackEnd)) { // We're in a new frame. Maybe from step-in or step-out. if (isVerbose) { WriteOutput(String.Format(" IL step stopping at new frame =({0:x},{1:x})", newStackStart, newStackEnd)); } break; } curFrame.GetIP(out offsetNew, out result); curFrame.GetNativeIP(out ipNative); if ((offsetNew == offsetStart) && (proc.StopReason.GetType() == typeof(StepCompleteStopReason))) { if (isVerbose) { WriteOutput(String.Format(" IL step continuing. N=0x{0:x}", ipNative)); } continue; } if (isVerbose) { WriteOutput(String.Format(" IL step complete at IL_{0:x}", offsetNew)); } break; } }
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); }
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)); }
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)); }
////////////////////////////////////////////////////////////////////////////////// // // Support for printing local printing variables // ////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Gets an Array of MDbgValues for the Active Local Vars in the given frame. /// </summary> /// <param name="managedFrame">The Frame to look in.</param> /// <returns>The MDbgValue[] Active Local Valiables.</returns> public MDbgValue[] GetActiveLocalVars(MDbgFrame managedFrame) { Debug.Assert(managedFrame != null); if (managedFrame == null) { throw new ArgumentException(); } CorFrame frame = managedFrame.CorFrame; // we only support this, when the frame is our function Debug.Assert(frame.FunctionToken == m_function.Token); if (!(frame.FunctionToken == m_function.Token)) { throw new ArgumentException(); } EnsureIsUpToDate(); if (!m_haveSymbols) { // if we don't have symbols -- we'll print local variables as (loca1_0,local_1,local_2,...) // to give them names consistent with ILasm. int c = frame.GetLocalVariablesCount(); if (c < 0) { c = 0; // in case we cannot get locals, } // we'll hide them. MDbgValue[] locals = new MDbgValue[c]; for (int i = 0; i < c; ++i) { CorValue arg = null; try { arg = frame.GetLocalVariable(i); } catch (System.Runtime.InteropServices.COMException e) { if (e.ErrorCode != (int)Microsoft.Samples.Debugging.CorDebug.HResult.CORDBG_E_IL_VAR_NOT_AVAILABLE) { throw; } } locals[i] = new MDbgValue(m_module.Process, "local_" + (i), arg); } return(locals); } uint ip; CorDebugMappingResult mappingResult; frame.GetIP(out ip, out mappingResult); ArrayList al = new ArrayList(); ISymbolScope scope = SymMethod.RootScope; AddLocalVariablesToList(frame, (int)ip, al, scope); return((MDbgValue[])al.ToArray(typeof(MDbgValue))); }