示例#1
0
        public static void XCmd(string arguments)
        {
            if (arguments.Length == 0)
            {
                WriteOutput("Please specify module.");
                ListCmd("mo");
            }
            else
            {
                const int default_count = 100; // default number of frames to print

                const string countOpt = "c";

                ArgParser ap = new ArgParser(arguments, countOpt + ":1");
                int count = default_count;
                if (ap.OptionPassed(countOpt))
                {
                    ArgToken countArg = ap.GetOption(countOpt);
                    if (countArg.AsString == "all")
                    {
                        count = 0; // 0 means print all symbols
                    }
                    else
                    {
                        count = countArg.AsInt;
                        if (count <= 0)
                        {
                            throw new MDbgShellException("Count must be positive number or string \"all\"");
                        }
                    }
                }

                string moduleName, substrPart;

                string expr = ap.AsString(0);
                int i = expr.IndexOf('!');
                if (i == -1)
                {
                    moduleName = expr;
                    substrPart = null;
                }
                else
                {
                    moduleName = expr.Substring(0, i);
                    substrPart = expr.Substring(i + 1);
                }

                SymbolCache.Clear();
                // enum functions from the module
                MDbgModule m = Debugger.Processes.Active.Modules.Lookup(moduleName);
                if (m == null)
                {
                    throw new MDbgShellException("module not found!");
                }

                bool shouldPrint = substrPart == null;
                Regex r = null;
                if (substrPart != null)
                {
                    r = new Regex(ConvertSimpleExpToRegExp(substrPart));
                }

                foreach (Type t in m.Importer.DefinedTypes)
                {
                    foreach (MethodInfo mi in t.GetMethods())
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append(t.Name).Append(".").Append(mi.Name).Append("(");
                        bool needComma = false;
                        foreach (ParameterInfo pi in mi.GetParameters())
                        {
                            if (needComma)
                            {
                                sb.Append(",");
                            }
                            sb.Append(pi.Name);
                            needComma = true;
                        }
                        sb.Append(")");
                        string fullFunctionName = sb.ToString();
                        if (r != null)
                        {
                            shouldPrint = r.IsMatch(fullFunctionName);
                        }
                        if (shouldPrint)
                        {
                            int idx = SymbolCache.Add(new MdbgSymbol(m.Number, t.Name, mi.Name, 0));
                            WriteOutput("~" + idx + ". " + fullFunctionName);
                            if (count != 0 && idx >= count)
                            {
                                WriteOutput(string.Format(CultureInfo.CurrentUICulture, "displayed only first {0} hits. For more symbols use -c switch", count));
                                return;
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        public static void WhereCmd(string arguments)
        {
            const int default_depth = 100; // default number of frames to print

            const string countOpt = "c";
            const string verboseOpt = "v";

            ArgParser 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 stack
                }
                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(Debugger.Processes.Active.Threads.Active, depth, ap.OptionPassed(verboseOpt));
            }
            else if (ap.AsString(0).Equals("all"))
            {
                foreach (MDbgThread t in Debugger.Processes.Active.Threads)
                    InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt));
            }
            else
            {
                MDbgThread t = Debugger.Processes.Active.Threads[ap.AsInt(0)];
                if (t == null)
                {
                    throw new MDbgShellException("Wrong thread number");
                }
                else
                {
                    InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt));
                }
            }
        }
示例#3
0
        public static void AttachCmd(string arguments)
        {
            const string versionArg = "ver";
            const string continuationEventArg = "attachEvent";
            const string pidArg = "pid";
            ArgParser ap = new ArgParser(arguments, versionArg + ":1;" + continuationEventArg + ":1;" + pidArg + ":1");

            if (ap.Count > 1)
            {
                throw new MDbgShellException("Wrong # of arguments.");
            }

            if (!ap.Exists(0) && !ap.OptionPassed(pidArg))
            {
                WriteOutput("Please choose some process to attach");
                ProcessEnumCmd("");
                return;
            }

            int pid;
            if (ap.Exists(0))
            {
                pid = ap.AsInt(0);
                if (ap.OptionPassed(pidArg))
                {
                    WriteOutput("Do not specify pid option when also passing pid as last argument");
                    return;
                }
            }
            else
            {
                Debug.Assert(ap.OptionPassed(pidArg)); // verified above
                pid = ap.GetOption(pidArg).AsInt;
            }


            //
            // Do some sanity checks to give useful end-user errors.
            // 


            // Can't attach to ourselves!
            if (Process.GetCurrentProcess().Id == pid)
            {
                throw new MDbgShellException("Cannot attach to myself!");
            }

            // Can't attach to a process that we're already debugging.
            // ICorDebug may enforce this, but the error may not be very descriptive for an end-user.
            // For example, ICD may propogate an error from the OS, and the OS may return
            // something like AccessDenied if another debugger is already attached.
            // This only checks for cases where this same instance of MDbg is already debugging
            // the process of interest. 
            foreach (MDbgProcess procOther in Debugger.Processes)
            {
                if (pid == procOther.CorProcess.Id)
                {
                    throw new MDbgShellException("Can't attach to process " + pid + " because it's already being debugged");
                }
            }

            // Get the OS handle if there was one
            SafeWin32Handle osEventHandle = null;
            if (ap.OptionPassed(continuationEventArg))
            {
                osEventHandle = new SafeWin32Handle(new IntPtr(ap.GetOption(continuationEventArg).AsHexOrDecInt));
            }

            // determine the version to attach to
            string version = null;
            if (ap.OptionPassed(versionArg))
            {
                version = ap.GetOption(versionArg).AsString;
            }
            else
            {
                version = MdbgVersionPolicy.GetDefaultAttachVersion(pid);
            }
            if (version == null)
            {
                throw new MDbgShellException("Can't determine what version of the CLR to attach to in process " +
                    pid + ". Use -ver to specify a version");
            }

            // attach
            MDbgProcess p;
            p = Debugger.Attach(pid, osEventHandle, version);

            p.Go().WaitOne();

            if (osEventHandle != null)
            {
                osEventHandle.Dispose();
            }
        }
示例#4
0
        public static void OpendumpCmd(string arguments)
        {
            const string pathArg = "path";
            ArgParser ap = new ArgParser(arguments, pathArg + ":1");

            if (ap.Count > 1)
            {
                throw new MDbgShellException("Wrong # of arguments.");
            }

            if (!ap.Exists(0) && !ap.OptionPassed(pathArg))
            {
                throw new MDbgShellException("Specify a dump file to open");
            }

            string path;
            if (ap.Exists(0))
                path = ap.AsString(0);
            else
                path = ap.GetOption(pathArg).AsString;

            DumpReader dump = new DumpReader(path);
            MDbgProcess process = Debugger.Processes.CreateProcess();

            // An exception partway through attaching can leave the debugger in an odd in-between state.
            // We need to attempt to detach.
            bool success = false;
            try
            {
                process.AttachToDump(dump, null);
                success = true;
            }
            finally
            {
                // Fault handler (emulate with finally & success bool since C# doesn't support fault blocks)
                // Detach on failure so we're not left with a partially attached process
                if (!success)
                    process.Detach();
            }

            WriteOutput("DBI path: " + ((LibraryProvider)process.LibraryProvider).LastLoadedDbi);
            // If there's an exception of interest stored in the dump, use it.
            // Otherwise, fall back on going to the first thread with managed code.
            if (dump.IsExceptionStream())
            {
                uint TID = dump.ExceptionStreamThreadId();
                WriteOutput("OS TID from last exception in dump was 0n" + TID);
                MDbgThread thread = process.Threads.GetThreadFromThreadId((int)TID);

                if (null == thread)
                {
                    WriteOutput("Could not find a managed thread corresponding to native TID!\n"
                        + "This should indicate that the last event was a native event on an unmanaged thread.\n"
                        );
                }
                else
                {
                    process.Threads.Active = thread;
                    WriteOutput("Active thread set to " + process.Threads.Active.Id);
                }
            }
            else
            {
                WriteOutput("No exception in dump, current thread will be chosen randomly.");
                // Set the currently active thread to the first thread we find with managed code on it.
                bool foundThread = false;
                for (int i = 0; i < process.Threads.Count && !foundThread; i++)
                {
                    foreach (MDbgFrame frame in process.Threads[i].Frames)
                    {
                        if (frame != null && frame.IsManaged)
                        {
                            process.Threads.Active = process.Threads[i];
                            foundThread = true;
                        }
                    }
                }
                if (!foundThread)
                {
                    WriteOutput("Warning: couldn't find thread with managed frame at base in dump");
                }
            }

            // This can fail silently if we can't walk the first frame of the stack.
            process.AsyncStop();
            process.Threads.Active.InvalidateStackWalker();
            WriteOutput("Dump loaded successfully.");
        }
示例#5
0
        public static void FuncEvalCmd(string arguments)
        {
            const string appDomainOption = "ad";
            ArgParser ap = new ArgParser(arguments, appDomainOption + ":1");
            if (!(ap.Count >= 1))
            {
                throw new MDbgShellException("Not Enough arguments");
            }

            // Currently debugger picks first function -- we have not implementing resolving overloaded functions.
            // Good example is Console.WriteLine -- there is 18 different types:
            // 1) [06000575] Void WriteLine()
            // 2) [06000576] Void WriteLine(Boolean)
            // 3) [06000577] Void WriteLine(Char)
            // 4) [06000578] Void WriteLine(Char[])
            // 5) [06000579] Void WriteLine(Char[], Int32, Int32)
            // 6) [0600057a] Void WriteLine(Decimal)
            // 7) [0600057b] Void WriteLine(Double)
            // 8) [0600057c] Void WriteLine(Single)
            // 9) [0600057d] Void WriteLine(Int32)
            // 10) [0600057e] Void WriteLine(UInt32)
            // 11) [0600057f] Void WriteLine(Int64)
            // 12) [06000580] Void WriteLine(UInt64)
            // 13) [06000581] Void WriteLine(Object)
            // 14) [06000582] Void WriteLine(String)
            // 15) [06000583] Void WriteLine(String, Object)
            // 16) [06000584] Void WriteLine(String, Object, Object)
            // 17) [06000585] Void WriteLine(String, Object, Object, Object)
            // 18) [06000586] Void WriteLine(String, Object, Object, Object, Object, ...)
            // 19) [06000587] Void WriteLine(String, Object[])
            //
            CorAppDomain appDomain;
            if (ap.OptionPassed(appDomainOption))
            {
                MDbgAppDomain ad = Debugger.Processes.Active.AppDomains[ap.GetOption(appDomainOption).AsInt];
                if (ad == null)
                {
                    throw new ArgumentException("Invalid Appdomain Number");
                }
                appDomain = ad.CorAppDomain;
            }
            else
            {
                appDomain = Debugger.Processes.Active.Threads.Active.CorThread.AppDomain;
            }

            MDbgFunction func = Debugger.Processes.Active.ResolveFunctionNameFromScope(ap.AsString(0), appDomain);
            if (null == func)
            {
                throw new MDbgShellException(String.Format(CultureInfo.InvariantCulture, "Could not resolve {0}", new Object[] { ap.AsString(0) }));
            }

            CorEval eval = Debugger.Processes.Active.Threads.Active.CorThread.CreateEval();

            // Get Variables
            ArrayList vars = new ArrayList();
            String arg;
            for (int i = 1; i < ap.Count; i++)
            {
                arg = ap.AsString(i);

                CorValue v = Shell.ExpressionParser.ParseExpression2(arg, Debugger.Processes.Active,
                    Debugger.Processes.Active.Threads.Active.CurrentFrame);

                if (v == null)
                {
                    throw new MDbgShellException("Cannot resolve expression or variable " + ap.AsString(i));
                }

                if (v is CorGenericValue)
                {
                    vars.Add(v as CorValue);
                }

                else
                {
                    CorHeapValue hv = v.CastToHeapValue();
                    if (hv != null)
                    {
                        // we cannot pass directly heap values, we need to pass reference to heap valus
                        CorReferenceValue myref = eval.CreateValue(CorElementType.ELEMENT_TYPE_CLASS, null).CastToReferenceValue();
                        myref.Value = hv.Address;
                        vars.Add(myref);
                    }
                    else
                    {
                        vars.Add(v);
                    }
                }

            }

            eval.CallFunction(func.CorFunction, (CorValue[])vars.ToArray(typeof(CorValue)));
            Debugger.Processes.Active.Go().WaitOne();

            // now display result of the funceval
            if (!(Debugger.Processes.Active.StopReason is EvalCompleteStopReason))
            {
                // we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason
                WriteOutput("Func-eval not fully completed and debuggee has stopped");
                WriteOutput("Result of funceval won't be printed when finished.");
            }
            else
            {
                eval = (Debugger.Processes.Active.StopReason as EvalCompleteStopReason).Eval;
                Debug.Assert(eval != null);

                CorValue cv = eval.Result;
                if (cv != null)
                {
                    MDbgValue mv = new MDbgValue(Debugger.Processes.Active, cv);
                    WriteOutput("result = " + mv.GetStringValue(1));
                    if (cv.CastToReferenceValue() != null)
                        if (Debugger.Processes.Active.DebuggerVars.SetEvalResult(cv))
                            WriteOutput("results saved to $result");
                }
            }
            Shell.DisplayCurrentLocation();
        }
示例#6
0
        public static void PrintCmd(string arguments)
        {
            const string debuggerVarsOpt = "d";
            const string noFuncevalOpt = "nf";
            const string expandDepthOpt = "r";

            ArgParser ap = new ArgParser(arguments, debuggerVarsOpt + ";" + noFuncevalOpt + ";" + expandDepthOpt + ":1");
            bool canDoFunceval = !ap.OptionPassed(noFuncevalOpt);

            int? expandDepth = null;			    // we use optional here because
            // different codes bellow has different
            // default values.
            if (ap.OptionPassed(expandDepthOpt))
            {
                expandDepth = ap.GetOption(expandDepthOpt).AsInt;
                if (expandDepth < 0)
                    throw new MDbgShellException("Depth cannot be negative.");
            }

            MDbgFrame frame = Debugger.Processes.Active.Threads.Active.CurrentFrame;
            if (ap.OptionPassed(debuggerVarsOpt))
            {
                // let's print all debugger variables
                MDbgProcess p = Debugger.Processes.Active;
                foreach (MDbgDebuggerVar dv in p.DebuggerVars)
                {
                    MDbgValue v = new MDbgValue(p, dv.CorValue);
                    WriteOutput(dv.Name + "=" + v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth,
                                                              canDoFunceval));
                }
            }
            else
            {
                if (ap.Count == 0)
                {
                    // get all active variables
                    MDbgFunction f = frame.Function;

                    ArrayList vars = new ArrayList();
                    MDbgValue[] vals = f.GetActiveLocalVars(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }

                    vals = f.GetArguments(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }
                    foreach (MDbgValue v in vars)
                    {
                        WriteOutput(v.Name + "=" + v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth,
                                                                 canDoFunceval));
                    }
                }
                else
                {
                    // user requested printing of specific variables
                    for (int j = 0; j < ap.Count; ++j)
                    {
                        MDbgValue var = Debugger.Processes.Active.ResolveVariable(ap.AsString(j), frame);
                        if (var != null)
                        {
                            WriteOutput(ap.AsString(j) + "=" + var.GetStringValue(expandDepth == null ? 1
                                : (int)expandDepth, canDoFunceval));
                        }
                        else
                        {
                            throw new MDbgShellException("Variable not found");
                        }
                    }
                }
            }
        }
示例#7
0
        public static void ThreadCmd(string arguments)
        {
            const string nickNameStr = "nick";
            ArgParser ap = new ArgParser(arguments, nickNameStr + ":1");
            if (ap.Count == 0)
            {
                if (ap.OptionPassed(nickNameStr))
                {
                    g_threadNickNames.SetThreadNickName(ap.GetOption(nickNameStr).AsString, Debugger.Processes.Active.Threads.Active);
                }
                else
                {
                    // we want to display active threads
                    MDbgProcess p = Debugger.Processes.Active;

                    WriteOutput("Active threads:");
                    foreach (MDbgThread t in p.Threads)
                    {
                        string stateDescription = GetThreadStateDescriptionString(t);
                        WriteOutput(string.Format("th #:{0} (ID:{1}){2}",
                                                  g_threadNickNames.GetThreadName(t),
                                                  t.Id,
                                                  stateDescription.Length == 0 ? String.Empty : " " + stateDescription));
                    }
                }
            }
            else
            {
                MDbgThread t = g_threadNickNames.GetThreadByNickName(ap.AsString(0));

                if (t == null)
                {
                    throw new MDbgShellException("No such thread");
                }
                Debugger.Processes.Active.Threads.Active = t;

                string currentThreadStateString = GetThreadStateDescriptionString(t);
                if (currentThreadStateString.Length > 0)
                    currentThreadStateString = currentThreadStateString.Insert(0, " ");

                WriteOutput(string.Format(CultureInfo.InvariantCulture, "Current thread is #{0}{1}.",
                                          t.Number, currentThreadStateString));
                Shell.DisplayCurrentLocation();
            }
        }