Ejemplo n.º 1
0
        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]));
            }
        }
Ejemplo n.º 2
0
        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]);
                }
            }
        }
Ejemplo n.º 3
0
        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;
            }
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
            }
        }
Ejemplo n.º 6
0
 public O2MDbgCurrentLocation(MDbgSourcePosition mdbgsourcePosition) : this()
 {
     loadDataFromMDbgSourcePosition(mdbgsourcePosition);
 }
Ejemplo n.º 7
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
 // 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);
 }
Ejemplo n.º 10
0
 protected override void OnRunWorker()
 {
     m_pos = null;
 }
Ejemplo n.º 11
0
        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);
                }
            }
        }
Ejemplo n.º 12
0
        // 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