public static ThreadSnapshot GetThreadSnapshot(MDbgThread thread) { var snapshot = new ThreadSnapshot(); snapshot.Id = thread.Id; long creation, exit, kernel, user; GetThreadTimes(thread.CorThread.Handle, out creation, out exit, out kernel, out user); snapshot.KernelTime = kernel; snapshot.UserTime = user; snapshot.StackTrace = new List <string>(); try { foreach (var frame in thread.Frames) { try { snapshot.StackTrace.Add(frame.Function.FullName); } catch { // no frame, so ignore } } } catch { // ignore the "cannot attach to thred" errors, we can't do anything about it, but leaving unhandled destroys the whole w3wp in production :( } return(snapshot); }
public void ProcessThreadSwitch(string command) { //Debug.Assert(false); //gotothread|<threadId> string[] parts = command.Split('|'); if (parts[0] == "gotothread" && IsInBreakMode) { string id = parts[1]; MDbgThread match = null; try { foreach (MDbgThread t in shell.Debugger.Processes.Active.Threads) { if (t.Id.ToString() == id) { match = t; break; } } } catch { // if it throws an invalid op, then that means our frames somehow got out of sync and we weren't fully refreshed. return; } if (match != null) { shell.Debugger.Processes.Active.Threads.Active = match; ReportCurrentState(); } } }
void ReportThreads() { if (IsInBreakMode) { MDbgThread tActive = GetCurrentThread(); var threadsInfo = new StringBuilder(); foreach (MDbgThread t in shell.Debugger.Processes.Active.Threads) { string stFrame = "<unknown>"; try { if (t.BottomFrame != null) { stFrame = t.BottomFrame.Function.FullName; } } catch { }//t.BottomFrame can throw threadsInfo.AppendFormat("<thread id=\"{0}\" name=\"{1}\" active=\"{2}\" number=\"{3}\" />", t.Id, stFrame.Replace("<", "$<").Replace(">", ">"), (t == tActive), t.Number, stFrame); } MessageQueue.AddNotification(NppCategory.Threads + "<threads>" + threadsInfo.ToString() + "</threads>"); } }
public static ThreadSnapshot GetThreadSnapshot(MDbgThread thread) { var snapshot = new ThreadSnapshot(); snapshot.Id = thread.Id; long creation, exit, kernel, user; GetThreadTimes(thread.CorThread.Handle, out creation, out exit, out kernel, out user); snapshot.KernelTime = kernel; snapshot.UserTime = user; snapshot.StackTrace = new List <string>(); foreach (MDbgFrame frame in thread.Frames) { try { snapshot.StackTrace.Add(frame.Function.FullName); } catch { // no frame, so ignore } } return(snapshot); }
// Notify this window that it's entering break mode. // Called on UI thread. protected override void OnBreakWorker() { ClearHighlight(); m_CurrentIpRow = -1; MainForm.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); MDbgThread t = proc.Threads.Active; MDbgFrame f = t.CurrentFrame; if ((f != null) && (f.Function == m_function)) { uint offsetIl; CorDebugMappingResult result; f.CorFrame.GetIP(out offsetIl, out result); // mapping is 0-based; row is 1-based. m_CurrentIpRow = m_il2RowMapping[offsetIl] + 1; } }); if (m_CurrentIpRow != -1) { HighlightRow(m_CurrentIpRow, MainForm.IsCurrentSourceActive); } }
// Update list w/ current callstack. Return an array of FramePair representing the callstack. // Run on worker thread. static FramePair[] GetFrameList(MDbgThread thread) { // Populate listbox with frames. MDbgFrame f = thread.BottomFrame; MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null; System.Collections.ArrayList l = new System.Collections.ArrayList(); int i = 0; int depth = 20; bool verboseOutput = true; while (f != null && (depth == 0 || i < depth)) { string line; if (f.IsInfoOnly) { line = string.Format(CultureInfo.InvariantCulture, "[{0}]", f.ToString()); } else { string frameDescription = "<unknown>"; try { // Get IP info. uint ipNative; uint ipIL; CorDebugMappingResult result; f.CorFrame.GetNativeIP(out ipNative); f.CorFrame.GetIP(out ipIL, out result); string frameLocation = String.Format(CultureInfo.InvariantCulture, " N=0x{0:x}, IL=0x{1:x} ({2})", ipNative, ipIL, result.ToString()); // This may actually do a ton of work, including evaluating parameters. frameDescription = f.ToString(verboseOutput ? "v" : null) + frameLocation; } catch (System.Runtime.InteropServices.COMException) { if (f.Function != null) { frameDescription = f.Function.FullName; } } line = string.Format(CultureInfo.InvariantCulture, "{0}{1}. {2}", f.Equals(af) ? "*" : " ", i, frameDescription); ++i; } l.Add(new FramePair(f, line)); f = f.NextUp; } if (f != null && depth != 0) // means we still have some frames to show.... { l.Add(new FramePair(null, string.Format(CultureInfo.InvariantCulture, "displayed only first {0} frames. For more frames use -c switch", depth) )); } return((FramePair[])l.ToArray(typeof(FramePair))); }
public void loadCurrentLocationFromMDbgThread(MDbgThread mdbgThread) { functionName = (mdbgThread.CurrentFrame != null && mdbgThread.CurrentFrame.Function != null) ? mdbgThread.CurrentFrame.Function.FullName : ""; //mdbgsourcePosition = mdbgThread.BottomFrame.SourcePosition; loadDataFromMDbgSourcePosition(mdbgThread.BottomFrame.SourcePosition); }
public static void WhereCmd(string arguments, O2Thread.FuncVoidT1 <string> o2Callback) { const int default_depth = 100; // default number of frames to print const string countOpt = "c"; const string verboseOpt = "v"; var ap = new ArgParser(arguments, countOpt + ":1;" + verboseOpt); int depth = default_depth; if (ap.OptionPassed(countOpt)) { ArgToken countArg = ap.GetOption(countOpt); if (countArg.AsString == "all") { depth = 0; // 0 means print entire stack0 } else { depth = countArg.AsInt; if (depth <= 0) { throw new MDbgShellException("Depth must be positive number or string \"all\""); } } } if (ap.Count != 0 && ap.Count != 1) { throw new MDbgShellException("Wrong # of arguments."); } if (ap.Count == 0) { // print current thread only InternalWhereCommand(CommandBase.Debugger.Processes.Active.Threads.Active, depth, ap.OptionPassed(verboseOpt)); } else if (ap.AsString(0).Equals("all")) { foreach (MDbgThread t in CommandBase.Debugger.Processes.Active.Threads) { InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt)); } } else { MDbgThread t = CommandBase.Debugger.Processes.Active.Threads[ap.AsInt(0)]; if (t == null) { throw new MDbgShellException("Wrong thread number"); } else { InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt)); } } }
/// <summary> /// Acts on the debugger callback, based on the stop option policy settings and the /// type of exception thrown. /// </summary> /// <param name="currentProcess">Current MDbgProcess.</param> /// <param name="args">Callback arguments.</param> public override void ActOnCallback(MDbgProcess currentProcess, CustomPostCallbackEventArgs args) { var ea = args.CallbackArgs as CorException2EventArgs; var ua = args.CallbackArgs as CorExceptionUnwind2EventArgs; bool bException2 = (ea != null); if (m_exceptionEnhancedOn || (bException2 && (ea.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE))) { MDbgThread currentThread = null; currentThread = currentProcess.Threads.GetThreadFromThreadId((args.CallbackArgs as CorThreadEventArgs).Thread.Id); string exceptionType = currentThread.CurrentException.TypeName; switch (DetermineBehavior(exceptionType)) { case DebuggerBehavior.Stop: if (bException2) { args.Controller.Stop(ea.Thread, new ExceptionThrownStopReason(ea.AppDomain, ea.Thread, ea.Frame, ea.Offset, ea.EventType, ea.Flags, m_exceptionEnhancedOn)); } else { args.Controller.Stop(ua.Thread, new ExceptionUnwindStopReason(ua.AppDomain, ua.Thread, ua.EventType, ua.Flags)); } break; case DebuggerBehavior.Log: CommandBase.WriteOutput("Exception thrown: " + currentThread.CurrentException.TypeName + " at function " + currentThread.CurrentFrame.Function.FullName + " in source file " + currentThread.CurrentSourcePosition.Path + ":" + currentThread.CurrentSourcePosition.Line); if (m_exceptionEnhancedOn) { if (bException2) { CommandBase.WriteOutput("Event type: " + ea.EventType); } else { CommandBase.WriteOutput("Event type: " + ua.EventType); } } CommandBase.WriteOutput(""); break; } } }
public static string GetCurrentLocationInSource(MDbgEngine debugger, IShell shell) { if (!debugger.Processes.Active.Threads.HaveActive) { return(""); // we won't try to show current location } MDbgThread thr = debugger.Processes.Active.Threads.Active; MDbgSourcePosition pos = thr.CurrentSourcePosition; if (pos == null) { MDbgFrame f = thr.CurrentFrame; if (f.IsManaged) { CorDebugMappingResult mappingResult; uint ip; f.CorFrame.GetIP(out ip, out mappingResult); string s = "IP: " + ip + " @ " + f.Function.FullName + " - " + mappingResult; return(s); } else { return("<Located in native code.>"); } } else { string fileLoc = shell.FileLocator.GetFileLocation(pos.Path); if (fileLoc == null) { // Using the full path makes debugging output inconsistant during automated test runs. // For testing purposes we'll get rid of them. //CommandBase.WriteOutput("located at line "+pos.Line + " in "+ pos.Path); return("located at line " + pos.Line + " in " + System.IO.Path.GetFileName(pos.Path)); } else { IMDbgSourceFile file = shell.SourceFileMgr.GetSourceFile(fileLoc); string prefixStr = pos.Line.ToString(CultureInfo.InvariantCulture) + ":"; if (pos.Line < 1 || pos.Line > file.Count) { shell.WriteLine("located at line " + pos.Line + " in " + pos.Path); throw new Exception(string.Format("Could not display current location; file {0} doesn't have line {1}.", file.Path, pos.Line)); } Debug.Assert((pos.Line > 0) && (pos.Line <= file.Count)); return(file[pos.Line]); } } }
private static void DumpThread(MDbgThread thread) { foreach (var frame in thread.Frames) { if (!frame.IsManaged || frame.Function.FullName.StartsWith("System.")) { break; } Console.WriteLine("{0}({1})", frame.Function.FullName, DumpArguments(frame)); } }
public static void GetActiveStatementCmd(string args) { MDbgThread t = Debugger.Processes.Active.Threads.Active; CorActiveFunction[] afa = t.CorThread.GetActiveFunctions(); WriteOutput("Active Statements Count: " + afa.Length); int frameNo = 0; foreach (CorActiveFunction caf in afa) { MDbgFunction f = Debugger.Processes.Active.Modules.LookupFunction(caf.Function); WriteOutput(String.Format(CultureInfo.InvariantCulture, "{0}. Method: {1}, IL offset: {2}", new Object[] { frameNo, f.FullName, caf.ILoffset })); frameNo++; } }
public O2MDbgThread(MDbgThread mdbgThread) : this() { MdbgThread = mdbgThread; Id = mdbgThread.Id; Number = mdbgThread.Number; HaveCurrentFrame = mdbgThread.HaveCurrentFrame; currentLocation = new O2MDbgCurrentLocation(mdbgThread.CurrentSourcePosition); if (mdbgThread.CurrentException != null && mdbgThread.CurrentException.IsNull == false) { currentException = mdbgThread.CurrentException.GetStringValue(false); currentException_expandedView = mdbgThread.CurrentException.GetStringValue(true); } calculateStackTrace(); o2MDbgvariables = DI.o2MDbg.sessionData.getCurrentFrameVariables(0 /*expandDepth*/, false /*canDoFunceval*/); }
private static void DumpThread(MDbgThread thread) { Console.Out.WriteLine(String.Format("OS Thread Id:{0}", thread.Id)); foreach (MDbgFrame frame in thread.Frames) { if (!frame.IsInfoOnly) { Console.Out.Write(String.Format(" {0}(", frame.Function.FullName)); foreach (MDbgValue value2 in frame.Function.GetArguments(frame)) { Console.Out.Write(value2.TypeName); } Console.Out.WriteLine(")"); } } }
// Refresh the callstack window. // runs on UI thread. protected override void RefreshToolWindowInternal() { // Information we need filled out. FramePair[] list = null; int number = 0; int id = 0; // Make cross thread call to access ICorDebug and fill out data MainForm.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); MDbgThread thread = proc.Threads.Active; try { number = thread.Number; id = thread.Id; list = GetFrameList(thread); } catch (Exception) { list = null; } }); if (list == null || list.Length == 0) { MarkCallstackAsRunning(); } else { ListBox.ObjectCollection l = this.listBoxCallstack.Items; l.Clear(); // Set Title. this.Text = "Callstack on Thread #" + number + " (tid=" + id + ")"; // Add items foreach (FramePair f in list) { l.Add(f); } } }
static MDbgFrame GetFrameByIndex(MDbgThread thread, int index) { MDbgFrame f = thread.BottomFrame; int count = 0; int depth = 20; while (f != null && (depth == 0 || count < depth)) { if (count == index) { return(f); } count++; f = f.NextUp; } return(null); }
// Helpers // Get the current frame for the process // Only called on Worker thread. public static MDbgFrame GetCurrentFrame(MDbgProcess proc) { if (proc == null) { return null; } if (!proc.Threads.HaveActive) { return null; } MDbgThread thread = proc.Threads.Active; if (!thread.HaveCurrentFrame) { return null; } MDbgFrame frame = thread.CurrentFrame; return frame; }
public static void InternalWhereCommand(MDbgThread thread, int depth, bool verboseOutput) { if (thread != null) { CommandBase.WriteOutput("Thread [#:" + MdbgCommands.g_threadNickNames.GetThreadName(thread) + "]"); MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null; MDbgFrame f = thread.BottomFrame; int i = 0; while (f != null && (depth == 0 || i < depth)) { string line; if (f.IsInfoOnly) { if (!CommandBase.ShowInternalFrames) { // in cases when we don't want to show internal frames, we'll skip them f = f.NextUp; continue; } line = String.Format(CultureInfo.InvariantCulture, " {0}", f); } else { string frameDescription = f.ToString(verboseOutput ? "v" : null); line = String.Format(CultureInfo.InvariantCulture, "{0}{1}. {2}", f.Equals(af) ? "*" : " ", i, frameDescription); ++i; } CommandBase.WriteOutput(line); f = f.NextUp; } if (f != null && depth != 0) // means we still have some frames to show.... { CommandBase.WriteOutput(String.Format(CultureInfo.InvariantCulture, "displayed only first {0} frames. For more frames use -c switch", depth)); } } }
// Invoked when we change the selection on the list box. // This will change the current active frame in the debugger and refresh. private void listBoxCallstack_DoubleClicked(object sender, EventArgs e) { object o = this.listBoxCallstack.SelectedItem; FramePair pair = (FramePair)o; MDbgFrame f = pair.m_frame; if (f == null) { return; } MainForm.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); // Update callstack MDbgThread t = proc.Threads.Active; try { t.CurrentFrame = f; } catch (InvalidOperationException) { // if it throws an invalid op, then that means our frames somehow got out of sync // and we weren't fully refreshed. return; } } // end delegate ); // Need to refresh UI to show update. this.MainForm.ShowCurrentLocation(); this.MainForm.Invalidate(); } // end listBoxCallstack_DoubleClicked
/// <summary> /// Acts on the current callback, based on the current debugger behavior for this stop /// option policy. /// </summary> /// <param name="currentProcess">Current MDbgProcess.</param> /// <param name="args">Callback arguments.</param> public override void ActOnCallback(MDbgProcess currentProcess, CustomPostCallbackEventArgs args) { CorEventArgs eventArgs = args.CallbackArgs as CorEventArgs; switch (m_behavior) { case DebuggerBehavior.Stop: args.Controller.Stop(eventArgs.Thread, MDbgUtil.CreateStopReasonFromEventArgs(eventArgs, currentProcess)); break; case DebuggerBehavior.Log: CommandBase.WriteOutput(eventArgs.ToString() + "\n"); break; case DebuggerBehavior.Notify: CommandBase.WriteOutput(eventArgs.ToString() + "\n"); MDbgThread currentThread = currentProcess.Threads.GetThreadFromThreadId((args.CallbackArgs as CorThreadEventArgs).Thread.Id); try { // Getting the current notification may not be implemented. MDbgValue notification = currentThread.CurrentNotification; if (notification != null) { CommandBase.WriteOutput(notification.GetStringValue(true, "-", null)); } else { CommandBase.WriteOutput("custom notification is null\n"); } } catch (NotImplementedException) { Trace.WriteLine("Custom Notifications Not Implemented"); } break; } }
// Parse a function breakpoint. ISequencePointResolver IBreakpointParser.ParseFunctionBreakpoint(string arguments) { Regex r; Match m; // maybe it's in the form: // "b ~number" r = new Regex(@"^~(\d+)$"); m = r.Match(arguments); string symNum = m.Groups[1].Value; if (symNum.Length > 0) { int intSymNum = Int32.Parse(symNum, CultureInfo.CurrentUICulture); MdbgSymbol symbol = shell.SymbolCache.Retrieve(intSymNum); return(new BreakpointFunctionLocation( string.Format(CultureInfo.InvariantCulture, ":{0}", symbol.ModuleNumber), symbol.ClassName, symbol.Method, symbol.Offset)); } // maybe it's in the form: // "b Mdbg.cs:34" r = new Regex(@"^(\S+:)?(\d+)$"); m = r.Match(arguments); string fname = m.Groups[1].Value; string lineNo = m.Groups[2].Value; int intLineNo = 0; if (lineNo.Length > 0) { if (fname.Length > 0) { fname = fname.Substring(0, fname.Length - 1); } else { MDbgSourcePosition pos = null; MDbgThread thr = shell.Debugger.Processes.Active.Threads.Active; if (thr != null) { pos = thr.CurrentSourcePosition; } if (pos == null) { throw new Exception("Cannot determine current file"); } fname = pos.Path; } intLineNo = Int32.Parse(lineNo, CultureInfo.CurrentUICulture); return(new BreakpointLineNumberLocation(fname, intLineNo)); } // now, to be valid, it must be in the form: // "b mdbg!Mdbg.Main+3" // // Note that this case must be checked after the source-file case above because // we want to assume that a number by itself is a source line, not a method name. // This is the most general form, so check this case last. (Eg, "Mdbg.cs:34" could // match as Class='MDbg', Method = 'cs:34'. ) // // The underlying metadata is extremely flexible and allows almost anything to be // in a method name, including spaces. Both C#, VB and MDbg's parsing are more restrictive. // Note we allow most characters in class and method names, except those we are using for separators // (+, ., :), <> since those are typically used to represent generics which we don't // support, and spaces since those are usually command syntax errors. // We exclude '*' for sanity reasons. // // Other caveats: // - we must allow periods in the method name for methods like ".ctor". // - be sure to allow $ character in the method and class names. Some compilers // like to use this in function names. // - Classes can't start with a number, but can include and end with numbers. // // Ideally we'd have a quoting mechanism and a more flexible parsing system to // handle generics, method overloads, etc. across all of MDbg. At least we have the 'x' // command and ~ shortcuts as a work-around. r = new Regex(@"^" + @"([^\!]+\!)?" + // optional module @"((?:[^.*+:<> ]+\.)*)" + // optional class @"([^*+:<>\d ][^*+:<> ]*)" + // method @"(\+\d+)?" + // optional offset @"$"); m = r.Match(arguments); string module = m.Groups[1].Value; string className = m.Groups[2].Value; string method = m.Groups[3].Value; string offset = m.Groups[4].Value; int intOffset = 0; if (method.Length > 0) { if (module.Length > 0) { module = module.Substring(0, module.Length - 1); } if (className.Length > 0) { // The class/module separator character is captured as part of className. // Chop it off to get just the classname. className = className.Substring(0, className.Length - 1); } if (offset.Length > 0) { intOffset = Int32.Parse(offset.Substring(1), CultureInfo.CurrentUICulture); } return(new BreakpointFunctionLocation(module, className, method, intOffset)); } // We don't recognize the syntax. Return null. If the parser is chained, it gives // our parent a chance to handle it. return(null); } // end function ParseFunctionBreakpoint
private void DisplaySource() { if (!_Shell.Debugger.Processes.HaveActive) { //CommandBase.WriteOutput("STOP: Process Exited"); return; // don't try to display current location } else { Object stopReason = _Shell.Debugger.Processes.Active.StopReason; Type stopReasonType = stopReason.GetType(); if (stopReasonType == typeof(StepCompleteStopReason)) { // just ignore those } } if (!_Shell.Debugger.Processes.Active.Threads.HaveActive) { return; // we won't try to show current location } MDbgThread thr = _Shell.Debugger.Processes.Active.Threads.Active; MDbgSourcePosition pos = thr.CurrentSourcePosition; if (pos == null) { MDbgFrame f = thr.CurrentFrame; if (f.IsManaged) { CorDebugMappingResult mappingResult; uint ip; f.CorFrame.GetIP(out ip, out mappingResult); string s = "IP: " + ip + " @ " + f.Function.FullName + " - " + mappingResult; CommandBase.WriteOutput(s); } else { CommandBase.WriteOutput("<Located in native code.>"); } } else { string fileLoc = _Shell.FileLocator.GetFileLocation(pos.Path); if (fileLoc == null) { // Using the full path makes debugging output inconsistant during automated test runs. // For testing purposes we'll get rid of them. //CommandBase.WriteOutput("located at line "+pos.Line + " in "+ pos.Path); CommandBase.WriteOutput("located at line " + pos.Line + " in " + System.IO.Path.GetFileName(pos.Path)); } else { IMDbgSourceFile file = _Shell.SourceFileMgr.GetSourceFile(fileLoc); string prefixStr = pos.Line.ToString(CultureInfo.InvariantCulture) + ":"; if (pos.Line < 1 || pos.Line > file.Count) { CommandBase.WriteOutput("located at line " + pos.Line + " in " + pos.Path); throw new MDbgShellException(string.Format("Could not display current location; file {0} doesn't have line {1}.", file.Path, pos.Line)); } string lineContent = file[pos.Line]; DisplayFile(file.Path, pos.Line); } } }
public O2MDbgCurrentLocation(MDbgThread mdbgThread) : this() { loadCurrentLocationFromMDbgThread(mdbgThread); raiseOnBreakEvent(); }
public virtual void DisplayCurrentLocation() { if (!Debugger.Processes.HaveActive) { CommandBase.WriteOutput("STOP: Process Exited"); return; // don't try to display current location } else { Debug.Assert(Debugger.Processes.HaveActive); Object stopReason = Debugger.Processes.Active.StopReason; Type stopReasonType = stopReason.GetType(); if (stopReasonType == typeof(StepCompleteStopReason)) { // just ignore those } else if (stopReasonType == typeof(ThreadCreatedStopReason)) { CommandBase.WriteOutput("STOP: Thread Created"); } else if (stopReasonType == typeof(BreakpointHitStopReason)) { MDbgBreakpoint b = (stopReason as BreakpointHitStopReason).Breakpoint; if (b.Number == 0) // specal case to keep compatibility with our test scripts. { CommandBase.WriteOutput("STOP: Breakpoint Hit"); } else { CommandBase.WriteOutput(String.Format(CultureInfo.InvariantCulture, "STOP: Breakpoint {0} Hit", new Object[] { b.Number })); } } else if (stopReasonType == typeof(ExceptionThrownStopReason)) { ExceptionThrownStopReason ex = (ExceptionThrownStopReason)stopReason; CommandBase.WriteOutput("STOP: Exception thrown"); PrintCurrentException(); if (Debugger.Options.StopOnExceptionEnhanced || ex.ExceptionEnhancedOn) { // when we are in ExceptionEnhanced mode, we print more information CommandBase.WriteOutput("\tOffset: " + ex.Offset); CommandBase.WriteOutput("\tEventType: " + ex.EventType); CommandBase.WriteOutput("\tIntercept: " + (ex.Flags != 0)); } } else if (stopReasonType == typeof(UnhandledExceptionThrownStopReason)) { CommandBase.WriteOutput("STOP: Unhandled Exception thrown"); PrintCurrentException(); CommandBase.WriteOutput(""); CommandBase.WriteOutput("This is unhandled exception, continuing will end the process"); } else if (stopReasonType == typeof(ExceptionUnwindStopReason)) { CommandBase.WriteOutput("STOP: Exception unwind"); CommandBase.WriteOutput("EventType: " + (stopReason as ExceptionUnwindStopReason).EventType); } else if (stopReasonType == typeof(ModuleLoadedStopReason)) { CommandBase.WriteOutput("STOP: Module loaded: " + (stopReason as ModuleLoadedStopReason).Module.CorModule.Name); } else if (stopReasonType == typeof(AssemblyLoadedStopReason)) { CommandBase.WriteOutput("STOP: Assembly loaded: " + (stopReason as AssemblyLoadedStopReason).Assembly.Name); } else if (stopReasonType == typeof(MDANotificationStopReason)) { CorMDA mda = (stopReason as MDANotificationStopReason).CorMDA; CommandBase.WriteOutput("STOP: MDANotification"); CommandBase.WriteOutput("Name=" + mda.Name); CommandBase.WriteOutput("XML=" + mda.XML); } else if (stopReasonType == typeof(MDbgErrorStopReason)) { Exception e = (stopReason as MDbgErrorStopReason).ExceptionThrown; CommandBase.WriteOutput("STOP: MdbgError"); CommandBase.WriteOutput(FormatExceptionDiagnosticText(e)); } else { CommandBase.WriteOutput("STOP " + Debugger.Processes.Active.StopReason); } } if (!Debugger.Processes.Active.Threads.HaveActive) { return; // we won't try to show current location } MDbgThread thr = Debugger.Processes.Active.Threads.Active; MDbgSourcePosition pos = thr.CurrentSourcePosition; if (pos == null) { MDbgFrame f = thr.CurrentFrame; if (f.IsManaged) { CorDebugMappingResult mappingResult; uint ip; f.CorFrame.GetIP(out ip, out mappingResult); string s = "IP: " + ip + " @ " + f.Function.FullName + " - " + mappingResult; CommandBase.WriteOutput(s); } else { CommandBase.WriteOutput("<Located in native code.>"); } } else { string fileLoc = FileLocator.GetFileLocation(pos.Path); if (fileLoc == null) { // Using the full path makes debugging output inconsistant during automated test runs. // For testing purposes we'll get rid of them. //CommandBase.WriteOutput("located at line "+pos.Line + " in "+ pos.Path); CommandBase.WriteOutput("located at line " + pos.Line + " in " + System.IO.Path.GetFileName(pos.Path)); } else { IMDbgSourceFile file = SourceFileMgr.GetSourceFile(fileLoc); string prefixStr = pos.Line.ToString(CultureInfo.InvariantCulture) + ":"; if (pos.Line < 1 || pos.Line > file.Count) { CommandBase.WriteOutput("located at line " + pos.Line + " in " + pos.Path); throw new MDbgShellException(string.Format("Could not display current location; file {0} doesn't have line {1}.", file.Path, pos.Line)); } Debug.Assert((pos.Line > 0) && (pos.Line <= file.Count)); string lineContent = file[pos.Line]; if (pos.StartColumn == 0 && pos.EndColumn == 0 || !(CommandBase.Shell.IO is IMDbgIO2)) // or we don't have support for IMDbgIO2 { // we don't know location in the line CommandBase.Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, prefixStr + lineContent + "\n"); } else { int hiStart; if (pos.StartColumn > 0) { hiStart = pos.StartColumn - 1; } else { hiStart = 0; } int hiLen; if (pos.EndColumn == 0 || // we don't know ending position (pos.EndLine > pos.StartLine)) // multi-line statement, select whole 1st line { hiLen = lineContent.Length; } else { hiLen = pos.EndColumn - 1 - hiStart; } Debug.Assert(CommandBase.Shell.IO is IMDbgIO2); // see if condition above (CommandBase.Shell.IO as IMDbgIO2).WriteOutput(MDbgOutputConstants.StdOutput, prefixStr + lineContent + "\n", hiStart + prefixStr.Length, hiLen); } } } }
public virtual LocationState DisplayCurrentLocation() { var locationState = new LocationState(ProcessStateEnum.Stop); if (!Debugger.Processes.HaveActive) { CommandBase.WriteOutput("STOP: Process Exited"); return(new LocationState(processState: ProcessStateEnum.Stop, message: "Process Exited")); } else { Debug.Assert(Debugger.Processes.HaveActive); Object stopReason = Debugger.Processes.Active.StopReason; Type stopReasonType = stopReason.GetType(); if (stopReasonType == typeof(StepCompleteStopReason)) { // just ignore those } else if (stopReasonType == typeof(ThreadCreatedStopReason)) { CommandBase.WriteOutput("STOP: Thread Created"); return(new LocationState(processState: ProcessStateEnum.Stop, message: "Thread Created")); } else if (stopReasonType == typeof(BreakpointHitStopReason)) { MDbgBreakpoint b = (stopReason as BreakpointHitStopReason).Breakpoint; if (b.Number == 0) // specal case to keep compatibility with our test scripts. { CommandBase.WriteOutput("STOP: Breakpoint Hit"); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: "Breakpoint Hit"); } else { CommandBase.WriteOutput(String.Format(CultureInfo.InvariantCulture, "STOP: Breakpoint {0} Hit", new Object[] { b.Number })); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Breakpoint { b.Number } Hit"); } } else if (stopReasonType == typeof(ExceptionThrownStopReason)) { ExceptionThrownStopReason ex = (ExceptionThrownStopReason)stopReason; CommandBase.WriteOutput("STOP: Exception thrown"); PrintCurrentException(); if (Debugger.Options.StopOnExceptionEnhanced || ex.ExceptionEnhancedOn) { // when we are in ExceptionEnhanced mode, we print more information CommandBase.WriteOutput("\tOffset: " + ex.Offset); CommandBase.WriteOutput("\tEventType: " + ex.EventType); CommandBase.WriteOutput("\tIntercept: " + (ex.Flags != 0)); } locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Exception thrown"); } else if (stopReasonType == typeof(UnhandledExceptionThrownStopReason)) { CommandBase.WriteOutput("STOP: Unhandled Exception thrown"); PrintCurrentException(); CommandBase.WriteOutput(""); CommandBase.WriteOutput("This is unhandled exception, continuing will end the process"); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Unhandled Exception thrown"); } else if (stopReasonType == typeof(ExceptionUnwindStopReason)) { CommandBase.WriteOutput("STOP: Exception unwind"); CommandBase.WriteOutput("EventType: " + (stopReason as ExceptionUnwindStopReason).EventType); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Exception unwind"); } else if (stopReasonType == typeof(ModuleLoadedStopReason)) { CommandBase.WriteOutput("STOP: Module loaded: " + (stopReason as ModuleLoadedStopReason).Module.CorModule.Name); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Module loaded: {(stopReason as ModuleLoadedStopReason).Module.CorModule.Name}"); } else if (stopReasonType == typeof(AssemblyLoadedStopReason)) { CommandBase.WriteOutput("STOP: Assembly loaded: " + (stopReason as AssemblyLoadedStopReason).Assembly.Name); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"Assembly loaded: {(stopReason as AssemblyLoadedStopReason).Assembly.Name}"); } else if (stopReasonType == typeof(MDANotificationStopReason)) { CorMDA mda = (stopReason as MDANotificationStopReason).CorMDA; CommandBase.WriteOutput("STOP: MDANotification"); CommandBase.WriteOutput("Name=" + mda.Name); CommandBase.WriteOutput("XML=" + mda.XML); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"MDANotification"); } else if (stopReasonType == typeof(MDbgErrorStopReason)) { Exception e = (stopReason as MDbgErrorStopReason).ExceptionThrown; CommandBase.WriteOutput("STOP: MdbgError"); CommandBase.WriteOutput(FormatExceptionDiagnosticText(e)); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: $"MdbgError"); } else { CommandBase.WriteOutput("STOP " + Debugger.Processes.Active.StopReason); locationState = new LocationState(processState: ProcessStateEnum.Stop, message: Debugger.Processes.Active.StopReason.ToString()); } } if (!Debugger.Processes.Active.Threads.HaveActive) { return(locationState); } MDbgThread thr = Debugger.Processes.Active.Threads.Active; MDbgSourcePosition pos = thr.CurrentSourcePosition; if (pos == null) { MDbgFrame f = thr.CurrentFrame; if (f.IsManaged) { CorDebugMappingResult mappingResult; uint offset; f.CorFrame.GetIP(out offset, out mappingResult); CommandBase.WriteOutput($"Offset:{offset} Function:{f.Function.FullName}"); locationState = new LocationState(processState: ProcessStateEnum.Running, message: $"Offset:{offset} Function:{f.Function.FullName}", function: f.Function.FullName); } else { CommandBase.WriteOutput("<Located in native code.>"); locationState = new LocationState(processState: ProcessStateEnum.Running, message: "<Located in native code.>"); } } else { string fileLoc = FileLocator.GetFileLocation(pos.Path); MDbgFrame f = thr.CurrentFrame; if (fileLoc == null) { // Using the full path makes debugging output inconsistant during automated test runs. // For testing purposes we'll get rid of them. //CommandBase.WriteOutput("located at line "+pos.Line + " in "+ pos.Path); Console.WriteLine($@"ln:{pos.Line} col:{pos.StartColumn}:{pos.EndColumn} in [{f.Function.FullName}] - {pos.Path}"); locationState = new LocationState(processState: ProcessStateEnum.Running, function: f.Function.FullName, lineNumber: pos.Line, file: pos.Path); } else { IMDbgSourceFile file = SourceFileMgr.GetSourceFile(fileLoc); string prefixStr = pos.Line.ToString(CultureInfo.InvariantCulture) + ":"; if (pos.Line < 1 || pos.Line > file.Count) { Console.WriteLine($@"ln:{pos.Line} col:{pos.StartColumn}:{pos.EndColumn} in [{f.Function.FullName}] - {pos.Path}"); locationState = new LocationState(processState: ProcessStateEnum.Running, function: f.Function.FullName, lineNumber: pos.Line, file: pos.Path); throw new MDbgShellException(string.Format("Could not display current location; file {0} doesn't have line {1}.", file.Path, pos.Line)); } Debug.Assert((pos.Line > 0) && (pos.Line <= file.Count)); string lineContent = file[pos.Line]; if (pos.StartColumn == 0 && pos.EndColumn == 0 || !(CommandBase.Shell.IO is IMDbgIO2)) // or we don't have support for IMDbgIO2 { // we don't know location in the line CommandBase.Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, prefixStr + lineContent + "\n"); } else { Console.WriteLine($@"ln:{pos.Line} col:{pos.StartColumn}:{pos.EndColumn} in [{f.Function.FullName}] - {pos.Path}"); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(lineContent); Console.ResetColor(); locationState = new LocationState(processState: ProcessStateEnum.Running, function: f.Function.FullName, lineNumber: pos.Line, file: pos.Path, code: lineContent); } } } return(locationState); }
/// <summary> /// Acts on the debugger callback, based on the stop option policy settings and the /// type of exception thrown. /// </summary> /// <param name="currentProcess">Current MDbgProcess.</param> /// <param name="args">Callback arguments.</param> public override void ActOnCallback(MDbgProcess currentProcess, CustomPostCallbackEventArgs args) { CorException2EventArgs ea = args.CallbackArgs as CorException2EventArgs; CorExceptionUnwind2EventArgs ua = args.CallbackArgs as CorExceptionUnwind2EventArgs; bool bException2 = (ea != null); if (m_exceptionEnhancedOn || (bException2 && (ea.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE))) { MDbgThread currentThread = null; currentThread = currentProcess.Threads.GetThreadFromThreadId((args.CallbackArgs as CorThreadEventArgs).Thread.Id); string exceptionType = null; DebuggerBehavior behavior; try { // Getting the current exception may not be implemented. exceptionType = currentThread.CurrentException.TypeName; behavior = DetermineBehavior(exceptionType); } catch (NotImplementedException) { behavior = this.m_default; } switch (behavior) { case DebuggerBehavior.Stop: if (bException2) { args.Controller.Stop(ea.Thread, new ExceptionThrownStopReason(ea.AppDomain, ea.Thread, ea.Frame, ea.Offset, ea.EventType, ea.Flags, m_exceptionEnhancedOn)); } else { args.Controller.Stop(ua.Thread, new ExceptionUnwindStopReason(ua.AppDomain, ua.Thread, ua.EventType, ua.Flags)); } break; case DebuggerBehavior.Log: string output = "Exception thrown: " + currentThread.CurrentException.TypeName + " at function " + currentThread.CurrentFrame.Function.FullName; if (currentThread.CurrentSourcePosition != null) { output += " in source file " + currentThread.CurrentSourcePosition.Path + ":" + currentThread.CurrentSourcePosition.Line; } CommandBase.WriteOutput(output); if (m_exceptionEnhancedOn) { if (bException2) { CommandBase.WriteOutput("Event type: " + ea.EventType); } else { CommandBase.WriteOutput("Event type: " + ua.EventType); } } CommandBase.WriteOutput(""); break; } } }