public static void ShowCmd(string arguments, O2Thread.FuncVoidT1 <string> o2Callback) { MDbgSourcePosition pos = CommandBase.Debugger.Processes.Active.Threads.Active.CurrentSourcePosition; if (pos == null) { throw new MDbgShellException("No source location"); } string fileLoc = CommandBase.Shell.FileLocator.GetFileLocation(pos.Path); if (fileLoc == null) { throw new MDbgShellException(String.Format(CultureInfo.InvariantCulture, "Source file '{0}' not available.", pos.Path)); } IMDbgSourceFile file = CommandBase.Shell.SourceFileMgr.GetSourceFile(fileLoc); var ap = new ArgParser(arguments); if (ap.Count > 1) { throw new MDbgShellException("Wrong # of arguments."); } int around; if (ap.Exists(0)) { around = ap.AsInt(0); } else { around = 3; } int lo, hi; lo = pos.Line - around; if (lo < 1) { lo = 1; } hi = pos.Line + around; if (hi > file.Count) { hi = file.Count; } for (int i = lo; i < hi; i++) { CommandBase.WriteOutput(String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", i, i == pos.Line ? ":*" : " ", file[i])); } }
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 void loadDataFromMDbgSourcePosition(MDbgSourcePosition mDbgSourcePosition) { hasSourceCodeDetails = (mDbgSourcePosition != null); if (mDbgSourcePosition != null) { FileName = mDbgSourcePosition.Path; Line = mDbgSourcePosition.Line; IsSpecial = mDbgSourcePosition.IsSpecial; StartColumn = mDbgSourcePosition.StartColumn; EndColumn = mDbgSourcePosition.EndColumn; StartLine = mDbgSourcePosition.StartLine; EndLine = mDbgSourcePosition.EndLine; } }
protected override void DrawGlyphWorker(PaintEventArgs e) { // base class does nothing. // Draw current source-line arrows in the glyph bar. MDbgSourcePosition pos = this.m_pos; if (pos != null) { { int iLine = pos.Line; Bitmap bmp = this.MainForm.IsCurrentSourceActive ? m_glyphs.CurrentLineArrow : m_glyphs.NotCurrentLineArrow; this.DrawGlyphAtLine(e, bmp, iLine); } } DrawBreakpoints(e); }
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); } }
public O2MDbgCurrentLocation(MDbgSourcePosition mdbgsourcePosition) : this() { loadDataFromMDbgSourcePosition(mdbgsourcePosition); }
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); }
// 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); }
protected override void OnRunWorker() { m_pos = null; }
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); } } }
// 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