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; }
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; }
// 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); } }
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; }
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); }
public static MDbgProcess goAndWait(this MDbgProcess process) { process.Go().WaitOne(); return(process); }
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()); }
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); }
void SendCommand(string format, params object[] args) { wh = process.Go(); }