/// <summary> /// Gets the source position from a given Instruction Pointer /// </summary> /// <param name="ip">The Instruction Pointer.</param> /// <returns>The Source Position.</returns> public MDbgSourcePosition GetSourcePositionFromIP(int ip) { EnsureIsUpToDate(); if (!m_haveSymbols) { return null; } if ((m_SPcount > 0) && (m_SPoffsets[0] <= ip)) { int i; for (i = 0; i < m_SPcount; ++i) { if (m_SPoffsets[i] >= ip) { break; } } if ((i == m_SPcount) || (m_SPoffsets[i] != ip)) { --i; } MDbgSourcePosition sp = null; if (m_SPstartLines[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 (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } if (sp == null) { // we didn't find any non-special seqeunce point before current one, let's try to search // after. j = i; while (++j < m_SPcount) { if (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } } // 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. if (sp == null) { return null; } } else { // non special sequence point. sp = new MDbgSourcePosition(false, m_SPdocuments[i].URL, m_SPstartLines[i], m_SPendLines[i], m_SPstartColumns[i], m_SPendColumns[i]); } if (CorFunction.Version != 1) // function has been edited { sp.m_fixedFile = Module.GetEditsSourceFile(CorFunction.Version - 1); } return sp; } return null; }
// Update windows (source, callstack,etc) to show our current source location. // This may be called when any UI element needs to update the UI (for example, the user selects // a different active frame in the callstack window). // This must be called on the UI thread. public void ShowCurrentLocation() { m_CurrentSourcePosition = null; // Update tool windows. If we don't have an active process / threads, they'll update accordingly. RefreshHelperWindows(); if(this.IsProcessStopped && GuiExtension.Shell.Debugger.Processes.Active.Threads.HaveActive) { // Show source file. MDbgThreadCollection tc = null; MDbgThread thread = null; MDbgFrame fCurrent = null; MDbgSourcePosition pos = null; MDbgFunction function = null; string stCurrentFrame = "?"; this.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); tc = proc.Threads; thread = tc.Active; if (!thread.HaveCurrentFrame) { WriteOutput(MDbgOutputConstants.StdError, "No frame for current thread #" + thread.Number); return; } fCurrent = thread.CurrentFrame; function = fCurrent.Function; pos = fCurrent.SourcePosition; stCurrentFrame = fCurrent.ToString(); }); if (fCurrent == null) { return; } bool fActive = (fCurrent == thread.BottomFrame); // Update current cached location m_CurrentSourcePosition = pos; this.m_fCurrentIsActive = fActive; // Try to display source. bool fOk = false; bool fShowIL = m_fShowIL; if (!fShowIL && (pos != null)) { // We're not in IL-mode, so show source-lines. fOk = OpenSourceFile(pos.Path); } else { // If we're in IL mode (or if we have no source), then show the IL! fOk = OpenSourceFile(function); } // Must always refresh the existing source forms. Even if we don't have a current source form, // we'll need to let our previous source know that it's lost focus. SourceViewerForm.OnBreak(); if (fOk) { return; } if (pos != null) { WriteOutput(MDbgOutputConstants.StdError, "Cannot display position in file: " + pos.Path); } else { WriteOutput(MDbgOutputConstants.StdError, "No source for current frame: " + stCurrentFrame); } } //SourceViewerForm.ClearCurrentSelection(); }
// Update windows (source, callstack,etc) to show our current source location. // This must be called on the UI thread. public void ShowCurrentLocation() { m_CurrentSourcePosition = null; // Update tool windows. If we don't have an active process / threads, they'll update accordingly. RefreshHelperWindows(); MDbgProcess proc = this.ActiveProcess; if((proc != null) && GuiExtension.Shell.Debugger.Processes.Active.Threads.HaveActive) { // Show source file. MDbgThreadCollection tc = proc.Threads; MDbgThread thread = tc.Active; if (!thread.HaveCurrentFrame) { WriteOutput(MDbgOutputConstants.StdError, "No source for current thread #" + thread.Number); return; } // Looks like a bug in MDbg where Thread's aren't getting refreshed. // Thus APIs fail with CORDBG_E_OBJECT_NEUTERED. So we forcifully // refresh them. { // @todo - RefreshStack() will reset the frame to the bottom most. //MDbgFrame fOld = thread.CurrentFrame; //tc.RefreshStack(); //thread.CurrentFrame = fOld; } MDbgFrame fCurrent = thread.CurrentFrame; MDbgSourcePosition pos = fCurrent.SourcePosition; bool fActive = (fCurrent == thread.BottomFrame); // Update current cached location m_CurrentSourcePosition = pos; this.m_fCurrentIsActive = fActive; // Try to display source. bool fOk = false; if (pos != null) { fOk = OpenSourceFile(pos.Path); } // Must always refresh the existing source forms. Even if we don't have a current source form, // we'll need to let our previous source know that it's lost focus. SourceViewerForm.OnBreak(); if (fOk) { return; } if (pos != null) { WriteOutput(MDbgOutputConstants.StdError, "Cannot display position in file: " + pos.Path); } else { WriteOutput(MDbgOutputConstants.StdError, "No source for current frame: " + fCurrent.ToString()); } } //SourceViewerForm.ClearCurrentSelection(); }
// Highlight the statement for the given Source Position protected void HighlightStatementAtPos(MDbgSourcePosition pos) { HighlightRangeWorker( pos.StartLine,pos.StartColumn,pos.EndLine,pos.EndColumn, this.MainForm.IsCurrentSourceActive); }
/// <summary> /// Returns a string that represents current frame /// Currently supported formats: /// null or empty string: returns short frame format (just frame name) /// "v" : returns long frame format (including module & arguments) /// </summary> /// <param name="format">Which format to use.</param> /// <returns>The formatted string that represtents the current frame.</returns> public override string ToString(string format) { string fn; switch (m_frame.FrameType) { case CorFrameType.ILFrame: MDbgSourcePosition sl = SourcePosition; string sp; if (sl != null) { string filePath = sl.Path; if (!Thread.m_threadMgr.m_process.m_engine.Options.ShowFullPaths) { filePath = Path.GetFileName(sl.Path); } sp = " (" + filePath + ":" + sl.Line.ToString(System.Globalization.CultureInfo.CurrentUICulture) + ")"; } else { sp = " (source line information unavailable)"; } StringBuilder sbFuncName = new StringBuilder(); MDbgModule module = this.Function.Module; MDbgProcess proc = Thread.m_threadMgr.m_process; // Get class name w/ generic args. CorType tClass = this.FunctionType; if (tClass != null) { InternalUtil.PrintCorType(sbFuncName, proc, tClass); } sbFuncName.Append('.'); // Get method name w/ generic args. MethodInfo mi = this.Function.MethodInfo; sbFuncName.Append(mi.Name); InternalUtil.AddGenericArgs(sbFuncName, proc, this.FunctionTypeParameters); string stFuncName = sbFuncName.ToString(); if (format == "v") { CorModule m = module.CorModule; // verbose frame output // in verbose output we'll print module name + arguments to the functions StringBuilder sb = new StringBuilder(); bool bFirst = true; foreach (MDbgValue v in this.Function.GetArguments(this)) { if (sb.Length != 0) { sb.Append(", "); } // skip this references if (!(bFirst && v.Name == "this")) { sb.Append(v.Name).Append("=").Append(v.GetStringValue(0)); } bFirst = false; } if (m.IsDynamic || m.IsInMemory) { fn = m.Name; } else { fn = System.IO.Path.GetFileName(m.Name); } MDbgAppDomain ad = this.Thread.m_threadMgr.m_process.AppDomains.Lookup(m.Assembly.AppDomain); fn += "#" + ad.Number + "!" + stFuncName + "(" + sb.ToString() + ") " + sp; } else { fn = stFuncName + sp; } break; case CorFrameType.NativeFrame: fn = "[IL Method without Metadata]"; break; case CorFrameType.InternalFrame: switch (m_frame.InternalFrameType) { case CorDebugInternalFrameType.STUBFRAME_NONE: fn = "None"; break; case CorDebugInternalFrameType.STUBFRAME_M2U: fn = "M-->U"; break; case CorDebugInternalFrameType.STUBFRAME_U2M: fn = "U-->M"; break; case CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION: fn = "AD Switch"; break; case CorDebugInternalFrameType.STUBFRAME_LIGHTWEIGHT_FUNCTION: fn = "LightWeight"; break; case CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL: fn = "FuncEval"; break; case CorDebugInternalFrameType.STUBFRAME_INTERNALCALL: fn = "InternalCall"; break; case CorDebugInternalFrameType.STUBFRAME_CLASS_INIT: fn = "ClassInit"; break; case CorDebugInternalFrameType.STUBFRAME_EXCEPTION: fn = "Exception"; break; case CorDebugInternalFrameType.STUBFRAME_SECURITY: fn = "Security"; break; case CorDebugInternalFrameType.STUBFRAME_JIT_COMPILATION: fn = "JitCompilation"; break; default: fn = "UNKNOWN"; break; } fn = "[Internal Frame, '" + fn + "']"; break; default: fn = "UNKNOWN Frame Type"; break; } return(fn); }
protected override void OnRunWorker() { m_pos = null; }
protected override void OnBreakWorker() { ClearHighlight(); m_pos = MainForm.CurrentSource; if (m_pos == null) { return; } if (m_pos.Path != this.Text) { m_pos = null; } // Hilight in current source if (m_pos != null) { HighlightStatementAtPos(m_pos); } }
// Set whether the GUI is in "Run-mode" or "Break-mode" // OnOff = true if we're stopping; false if we're going to start running // This will also set the ActiveProcess property so that other events on the // UI thread can see if it's safe to access Mdbg objects. // This must be called on the UI thread. private void SetCommandInputState(bool OnOff) { // Enable / disable UI elements. cmdInput.Enabled = OnOff; breakCmd.Enabled=!OnOff; // Although the underlying MDbg engine supports multiple processes, // We'll only support 1 process from the UI to keep things simple. bool fHasProcess = GuiExtension.Debugger.Processes.HaveActive; // If we're stopped, and we don't already have a process, then allow creating one. bool fAllowCreate = OnOff && !fHasProcess; menuItemLaunch.Enabled = fAllowCreate; menuItemAttach.Enabled = fAllowCreate; // If we're stopped, and we do have a process, allow killing it. bool fAllowKill = OnOff && fHasProcess; menuItemDetach.Enabled = fAllowKill; menuItemKill.Enabled = fAllowKill; SetTitle(OnOff); if(OnOff) { // Enter "Break" Mode if (fHasProcess) { m_process = GuiExtension.Debugger.Processes.Active; } else { m_process = null; } Activate(); // bring GUI up when we e.g. hit breakpoint this.Cursor = Cursors.Default; ShowCurrentLocation(); // calculate current source location. SourceViewerForm.OnBreak(); //WritePrompt(); cmdInput.Focus(); } else { m_process = null; // Enter "Run" mode m_CurrentSourcePosition = null; SourceViewerForm.OnRun(); this.Cursor = Cursors.AppStarting; } }
/// <summary> /// Gets the source position from a given Instruction Pointer /// </summary> /// <param name="ip">The Instruction Pointer.</param> /// <returns>The Source Position.</returns> public MDbgSourcePosition GetSourcePositionFromIP(int ip) { EnsureIsUpToDate(); if (!m_haveSymbols) { return(null); } if ((m_SPcount > 0) && (m_SPoffsets[0] <= ip)) { int i; for (i = 0; i < m_SPcount; ++i) { if (m_SPoffsets[i] >= ip) { break; } } if (i == m_SPcount || m_SPoffsets[i] != ip) { --i; } MDbgSourcePosition sp = null; if (m_SPstartLines[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 (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } if (sp == null) { // we didn't find any non-special seqeunce point before current one, let's try to search // after. j = i; while (++j < m_SPcount) { if (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } } Debug.Assert(sp != null, "Only SpecialSequence point detected"); } else { // non special sequence point. sp = new MDbgSourcePosition(false, m_SPdocuments[i].URL, m_SPstartLines[i], m_SPendLines[i], m_SPstartColumns[i], m_SPendColumns[i]); } if (CorFunction.Version != 1) // function has been edited { sp.m_fixedFile = Module.GetEditsSourceFile(CorFunction.Version - 1); } return(sp); } return(null); }
/// <summary> /// Gets the source position from a given Instruction Pointer /// </summary> /// <param name="ip">The Instruction Pointer.</param> /// <returns>The Source Position.</returns> public MDbgSourcePosition GetSourcePositionFromIP(int ip) { EnsureIsUpToDate(); if (!m_haveSymbols) { return(null); } if ((m_SPcount > 0) && (m_SPoffsets[0] <= ip)) { int i; for (i = 0; i < m_SPcount; ++i) { if (m_SPoffsets[i] >= ip) { break; } } if ((i == m_SPcount) || (m_SPoffsets[i] != ip)) { --i; } MDbgSourcePosition sp = null; if (m_SPstartLines[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 (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } if (sp == null) { // we didn't find any non-special seqeunce point before current one, let's try to search // after. j = i; while (++j < m_SPcount) { if (m_SPstartLines[j] != SpecialSequencePoint) { sp = new MDbgSourcePosition(true, m_SPdocuments[j].URL, m_SPstartLines[j], m_SPendLines[j], m_SPstartColumns[j], m_SPendColumns[j]); break; } } } // 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. if (sp == null) { return(null); } } else { // non special sequence point. sp = new MDbgSourcePosition(false, m_SPdocuments[i].URL, m_SPstartLines[i], m_SPendLines[i], m_SPstartColumns[i], m_SPendColumns[i]); } if (CorFunction.Version != 1) // function has been edited { sp.m_fixedFile = Module.GetEditsSourceFile(CorFunction.Version - 1); } return(sp); } return(null); }