Example #1
0
        private static void InitializeMdbg(MDbgEngine debugger, MDbgProcess proc)
        {
            bool stopOnNewThread = debugger.Options.StopOnNewThread;

            debugger.Options.StopOnNewThread = false;
            proc.Go().WaitOne();
            debugger.Options.StopOnNewThread = true;
            while (proc.CorProcess.HasQueuedCallbacks(null))
            {
                proc.Go().WaitOne();
            }
            debugger.Options.StopOnNewThread = stopOnNewThread;
        }
Example #2
0
        public void StartProcess()
        {
            Debugger.Options.StopOnLogMessage = false;
            if (options.PID != 0)
            {
                string clrVersion = string.IsNullOrEmpty(options.CLRVersion) ? MdbgVersionPolicy.GetDefaultAttachVersion(options.PID) : options.CLRVersion;
                Process = Debugger.Attach(options.PID, null, clrVersion);
                WriteLine("Attached to " + options.PID);
                Process.Go().WaitOne();
            }
            else if (!string.IsNullOrEmpty(options.Executable))
            {
                var clrVersion = MdbgVersionPolicy.GetDefaultLaunchVersion(options.Executable);
                Process = Debugger.Processes.CreateLocalProcess(new CorDebugger(clrVersion));
                if (Process == null)
                {
                    throw new Exception("Could not create debugging interface for runtime version " + clrVersion);
                }
                Process.DebugMode = DebugModeFlag.Debug;
                Process.CreateProcess(options.Executable, configuration.arguments != null ? configuration.arguments : "");
                Process.Go().WaitOne();
            }
            else
            {
                WriteLine(options.GetUsage());
                return;
            }

            Console.CancelKeyPress += OnAbort;
        }
Example #3
0
        // O2.Debugger.Mdbg.OriginalMdbgCode.mdbg.mdbgCommandsCustomizedForO2
        // , O2Thread.FuncVoid<string> o2Callback)
        public static bool AttachCmd(string arguments, O2Thread.FuncVoidT1 <string> o2Callback)
        {
            try
            {
                var ap = new ArgParser(arguments);
                if (ap.Count > 1)
                {
                    DI.log.error("in AttachCmd: Wrong # of arguments.");
                    return(false);
                }

                if (!ap.Exists(0))
                {
                    DI.log.error("in AttachCmd: Please choose some process to attach");
                    MdbgCommands.ProcessEnumCmd("");
                    return(false);
                }
                int pid = ap.AsInt(0);

                if (Process.GetCurrentProcess().Id == pid)
                {
                    DI.log.error("in AttachCmd: Cannot attach to myself!");
                    return(false);
                }

                MDbgProcess p = CommandBase.Debugger.Attach(pid);
                p.Go().WaitOne();
                return(true);
            }
            catch (Exception ex)
            {
                DI.log.ex(ex, "in AttachCmd");
                return(false);
            }
        }
Example #4
0
        public static CorValue CreateCorValue(this MDbgProcess process, string value)
        {
            CorEval eval = process.Threads.Active.CorThread.CreateEval();

            eval.NewString(value);
            process.Go().WaitOne();
            return((process.StopReason as EvalCompleteStopReason).Eval.Result);
        }
        private void DrainAttach(MDbgEngine debugger, MDbgProcess proc)
        {
            bool fOldStatus = debugger.Options.StopOnNewThread;

            debugger.Options.StopOnNewThread = false; // skip while waiting for AttachComplete
            proc.Go().WaitOne();
            Debug.Assert(proc.StopReason is AttachCompleteStopReason);

            debugger.Options.StopOnNewThread = true; // needed for attach= true; // needed for attach

            // Drain the rest of the thread create events.
            while (proc.CorProcess.HasQueuedCallbacks(null))
            {
                proc.Go().WaitOne();
                Debug.Assert(proc.StopReason is ThreadCreatedStopReason);
            }

            debugger.Options.StopOnNewThread = fOldStatus;
        }
Example #6
0
        CorValue GetResult()
        {
            process.Go().WaitOne();

            // now display result of the funceval
            if (process.StopReason is EvalCompleteStopReason)
            {
                eval = (process.StopReason as EvalCompleteStopReason).Eval;
                Debug.Assert(eval != null);

                return(eval.Result);
            }
            return(null);
        }
        /// <summary>
        ///  Eval a function in the target process.
        /// </summary>
        /// <param name="functionNameFromScope">The full function name.</param>
        MDbgValue FunctionEval(string functionNameFromScope)
        {
            CorAppDomain corAD    = this.MDbgProcess.Threads.Active.CorThread.AppDomain;
            MDbgFunction function = this.MDbgProcess.ResolveFunctionNameFromScope(
                functionNameFromScope, corAD);
            CorEval eval = this.MDbgProcess.Threads.Active.CorThread.CreateEval();

            eval.CallFunction(function.CorFunction, new CorValue[0]);
            MDbgProcess.Go().WaitOne();

            MDbgValue value = null;

            if (MDbgProcess.StopReason is EvalCompleteStopReason)
            {
                CorValue result =
                    (MDbgProcess.StopReason as EvalCompleteStopReason).Eval.Result;
                if (result != null)
                {
                    value = new MDbgValue(MDbgProcess, result);
                }
            }
            return(value);
        }
Example #8
0
 public static MDbgProcess goAndWait(this MDbgProcess process)
 {
     process.Go().WaitOne();
     return(process);
 }
Example #9
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Usage();
                return;
            }

            int samples        = 10;
            int sampleInterval = 1000;


            var state = ParseState.Unknown;

            foreach (var arg in args.Skip(1))
            {
                switch (state)
                {
                case ParseState.Unknown:
                    if (arg.ToLower() == "/s")
                    {
                        state = ParseState.Samples;
                    }
                    else if (arg.ToLower() == "/i")
                    {
                        state = ParseState.Interval;
                    }
                    else
                    {
                        Usage();
                        return;
                    }
                    break;

                case ParseState.Samples:
                    if (!Int32.TryParse(arg, out samples))
                    {
                        Usage();
                        return;
                    }
                    state = ParseState.Unknown;
                    break;

                case ParseState.Interval:
                    if (!Int32.TryParse(arg, out sampleInterval))
                    {
                        Usage();
                        return;
                    }
                    state = ParseState.Unknown;
                    break;

                default:
                    break;
                }
            }

            string pidOrProcess = args[0];


            var stats    = new Dictionary <int, List <ThreadSnapshot> >();
            var debugger = new MDbgEngine();
            int pid      = -1;

            var processes = Process.GetProcessesByName(pidOrProcess);

            if (processes.Length < 1)
            {
                try {
                    pid = Int32.Parse(pidOrProcess);
                } catch {
                    Console.WriteLine("Error: could not find any processes with that name or pid");
                    return;
                }
            }
            else
            {
                if (processes.Length > 1)
                {
                    Console.WriteLine("Warning: multiple processes share that name, attaching to the first");
                }
                pid = processes[0].Id;
            }


            MDbgProcess attached = null;

            try {
                attached = debugger.Attach(pid);
            } catch (Exception e) {
                Console.WriteLine("Error: failed to attach to process: " + e);
                return;
            }

            attached.Go().WaitOne();

            for (int i = 0; i < samples; i++)
            {
                foreach (MDbgThread thread in attached.Threads)
                {
                    var snapshot = ThreadSnapshot.GetThreadSnapshot(thread);
                    List <ThreadSnapshot> snapshots;
                    if (!stats.TryGetValue(snapshot.Id, out snapshots))
                    {
                        snapshots          = new List <ThreadSnapshot>();
                        stats[snapshot.Id] = snapshots;
                    }

                    snapshots.Add(snapshot);
                }

                attached.Go();
                Thread.Sleep(sampleInterval);
                attached.AsyncStop().WaitOne();
            }

            attached.Detach().WaitOne();

            // perform basic analysis to see which are the top N stack traces observed,
            //  weighted on cost

            Dictionary <Guid, long>   costs  = new Dictionary <Guid, long>();
            Dictionary <Guid, string> stacks = new Dictionary <Guid, string>();

            foreach (var stat in stats.Values)
            {
                long prevTime = -1;
                foreach (var snapshot in stat)
                {
                    long time = snapshot.KernelTime + snapshot.UserTime;
                    if (prevTime != -1)
                    {
                        foreach (var tuple in snapshot.StackHashes)
                        {
                            if (costs.ContainsKey(tuple.Item1))
                            {
                                costs[tuple.Item1] += time - prevTime;
                            }
                            else
                            {
                                costs[tuple.Item1]  = time - prevTime;
                                stacks[tuple.Item1] = tuple.Item2;
                            }
                        }
                    }
                    prevTime = time;
                }
            }

            Console.WriteLine("Most expensive stacks");
            Console.WriteLine("------------------------------------");
            foreach (var group in costs.OrderByDescending(p => p.Value).GroupBy(p => p.Value))
            {
                List <string> stacksToShow = new List <string>();

                foreach (var pair in group.OrderByDescending(p => stacks[p.Key].Length))
                {
                    if (!stacksToShow.Any(s => s.Contains(stacks[pair.Key])))
                    {
                        stacksToShow.Add(stacks[pair.Key]);
                    }
                }

                foreach (var stack in stacksToShow)
                {
                    Console.WriteLine(stack);
                    Console.WriteLine("===> Cost ({0})", group.Key);
                    Console.WriteLine();
                }
            }


            var offenders = stats.Values
                            .Select(_ => ThreadSnapshotStats.FromSnapshots(_))
                            .OrderBy(stat => stat.TotalKernelTime + stat.TotalUserTime)
                            .Reverse();

            foreach (var stat in offenders)
            {
                Console.WriteLine("------------------------------------");
                Console.WriteLine(stat.ThreadId);
                Console.WriteLine("Kernel: {0} User: {1}", stat.TotalKernelTime, stat.TotalUserTime);
                foreach (var method in stat.CommonStack)
                {
                    Console.WriteLine(method);
                }
                Console.WriteLine("Other Stacks:");
                var prev = new List <string>();
                foreach (var trace in stats[stat.ThreadId].Select(_ => _.StackTrace))
                {
                    if (!prev.SequenceEqual(trace))
                    {
                        Console.WriteLine();
                        foreach (var method in trace)
                        {
                            Console.WriteLine(method);
                        }
                    }
                    else
                    {
                        Console.WriteLine("<skipped>");
                    }
                    prev = trace;
                }
                Console.WriteLine("------------------------------------");
            }
        }
        private string PrintObject(int indentLevel, CorDebug.CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            // Print generics-aware type.
            string name = InternalUtil.PrintCorType(m_process, ov.ExactType);

            var txt = new StringBuilder();

            txt.Append(name);

            if (expandDepth > 0)
            {
                // we gather the field info of the class before we do
                // funceval since funceval requires running the debugger process
                // and this in turn can cause GC and invalidate our references.
                var expandedDescription = new StringBuilder();
                if (IsComplexType)
                {
                    foreach (MDbgValue v in GetFields())
                    {
                        expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)).
                        Append("=").Append(IndentedBlock(indentLevel + 2,
                                                         v.GetStringValue(expandDepth - 1, false)));
                    }
                }

                if (ov.IsValueClass && canDoFunceval)
                // we could display even values for real Objects, but we will just show
                // "description" for valueclasses.
                {
                    CorDebug.CorClass cls      = ov.ExactType.Class;
                    CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer;
                    var mdType = importer.GetType(cls.Token) as MetadataType;

                    if (mdType.ReallyIsEnum)
                    {
                        txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType));
                    }
                    else if (m_process.IsRunning)
                    {
                        txt.Append(" <N/A during run>");
                    }
                    else
                    {
                        MDbgThread activeThread = m_process.Threads.Active;

                        CorDebug.CorValue     thisValue;
                        CorDebug.CorHeapValue hv = ov.CastToHeapValue();
                        if (hv != null)
                        {
                            // we need to pass reference value.
                            CorDebug.CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
                            thisValue = handle;
                        }
                        else
                        {
                            thisValue = ov;
                        }

                        try
                        {
                            CorDebug.CorEval eval = m_process.Threads.Active.CorThread.CreateEval();
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND,
                                                                         activeThread.CorThread);

                            MDbgFunction toStringFunc =
                                m_process.ResolveFunctionName(null, "System.Object", "ToString"
                                                              , thisValue.ExactType.Class.Module.Assembly.AppDomain);
                            Debug.Assert(toStringFunc != null);
                            // we should be always able to resolve ToString function.

                            eval.CallFunction(toStringFunc.CorFunction, new[] { thisValue });
                            m_process.Go();
                            do
                            {
                                m_process.StopEvent.WaitOne();
                                if (m_process.StopReason is EvalCompleteStopReason)
                                {
                                    CorDebug.CorValue cv = eval.Result;
                                    Debug.Assert(cv != null);
                                    var    mv      = new MDbgValue(m_process, cv);
                                    string valName = mv.GetStringValue(0);

                                    // just purely for esthetical reasons we 'discard' "
                                    if (valName.StartsWith("\"") && valName.EndsWith("\""))
                                    {
                                        valName = valName.Substring(1, valName.Length - 2);
                                    }

                                    txt.Append(" <").Append(valName).Append(">");
                                    break;
                                }
                                if ((m_process.StopReason is ProcessExitedStopReason) ||
                                    (m_process.StopReason is EvalExceptionStopReason))
                                {
                                    txt.Append(" <N/A cannot evaluate>");
                                    break;
                                }
                                // hitting bp or whatever should not matter -- we need to ignore it
                                m_process.Go();
                            } while (true);
                        }
                        catch (COMException e)
                        {
                            // Ignore canot copy a VC class error - Can't copy a VC with object refs in it.
                            if (e.ErrorCode != (int)CorDebug.HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS)
                            {
                                throw;
                            }
                        }
                        finally
                        {
                            // we need to resume all the threads that we have suspended no matter what.
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN,
                                                                         activeThread.CorThread);
                        }
                    }
                }
                txt.Append(expandedDescription.ToString());
            }
            return(txt.ToString());
        }
Example #11
0
        private static bool DebugActiveSilverlightProcess(int processId, DebugModeFlag debugMode)
        {
            MDbgProcess p = null;

            string[]          fullPaths;
            EventWaitHandle[] continueStartupEvents;
            bool bMatchFound = false;

            // some pre-condition checks
            if (processId <= 0)
            {
                throw new MDbgShellException("Invalid arguments passed in");
            }

            // Get all funcs exported by the coreclr's dbg shim.
            Silverlight.InitSLApi();

            // Enumerate all coreclr instances in the process
            Silverlight.EnumerateCLRs((uint)processId, out fullPaths, out continueStartupEvents);
            int nSilverlight = fullPaths.Length;

            if (fullPaths == null || nSilverlight == 0)
            {
                throw new MDbgShellException("Could not enumerate any CLRs in specifed Silverlight process");
            }

            // for each coreclr instance found.....
            for (int i = 0; i < nSilverlight && !bMatchFound; i++)
            {
                // Attach to the first one

                WriteOutput("FOUND: " + fullPaths[i]);
                string slVersion = Silverlight.CreateVersionStringFromModule((uint)processId, fullPaths[i]);
                sVersionString = slVersion;
                // we'll get the required ICorDebug interface from dbgshim.dll
                ICorDebug cordbg = null;
                try
                {
                    cordbg = Silverlight.CreateDebuggingInterfaceFromVersionEx(CorDebugInterfaceVersion.CorDebugLatestVersion, slVersion);
                }
                catch (COMException ce)
                {
                    Console.WriteLine("CDIFVEx failed, will retry with CDIFV.\n" + ce.ToString());
                }

                if (cordbg == null)
                {
                    cordbg = Silverlight.CreateDebuggingInterfaceFromVersion(slVersion);
                }

                p = GetProcessFromCordb(cordbg);

                // specify JIT flages here
                p.DebugMode = debugMode;
                p.Attach((int)processId);
                bMatchFound = true;


                // signal the continue event

                if (!continueStartupEvents[i].SafeWaitHandle.IsInvalid)
                {
                    continueStartupEvents[i].Set();
                }

                if (null != p)
                {
                    p.Go().WaitOne();
                }
            }

            return(bMatchFound);
        }
Example #12
0
 void SendCommand(string format, params object[] args)
 {
     wh = process.Go();
 }