/// <summary> /// returns a list of samples (in time) of list (per thread) of CallstackSamples /// </summary> /// <param name="pid">the process id to attach to</param> /// <param name="numOfSamples"></param> /// <param name="timeBetweenSamplesInMillis"></param> /// <returns></returns> public List<ProcessSample> GetSample(MDbgProcess proc, int numOfSamples, int timeBetweenSamplesInMillis, bool extraDetails = false, bool originFirst = false) { List<ProcessSample> samples = new List<ProcessSample>(); try { m_intMainThreadId = -1; if (m_onlyMainThread) { MDbgThread mainthread = GetMainThread(proc); m_intMainThreadId = mainthread.Id; //if (e.CallbackType == ManagedCallbackType.OnException2) //{ // var ce = (CorException2EventArgs)e.CallbackArgs; // if (ce.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE) // { // var thread = process.Threads.Lookup(ce.Thread); // foreach (var frame in thread.Frames) // { // if (!frame.IsManaged || frame.Function.FullName.StartsWith("System.")) // break; // log.Log("{0}({1})", frame.Function.FullName, string.Join(", ", frame.Function.GetArguments(frame).Select( // arg => string.Format("{0} = {1}", arg.Name, arg.GetStringValue(false))))); // } // } //} } if (m_intMainThreadId == -1) { m_onlyMainThread = false; } Console.WriteLine("startTime: " + DateTime.Now.ToString("hh:mm:ss.fff")); int sleepTime = timeBetweenSamplesInMillis; Stopwatch s = Stopwatch.StartNew(); for (int i = 0; i < numOfSamples; i++) { ProcessSample frames = GetCallstacks(proc, m_onlyMainThread, extraDetails, originFirst); samples.Add(frames); //samples.Insert(0,frames); s.Reset(); s.Start(); proc.Go(); //sleepTime -= (int)s.ElapsedMilliseconds; //sleep if (sleepTime > 0) Thread.Sleep(sleepTime); //reset sleep time sleepTime = timeBetweenSamplesInMillis; s.Reset(); s.Start(); proc.AsyncStop().WaitOne(); //sleepTime -= (int)s.ElapsedMilliseconds; } Console.WriteLine("EndTime: " + DateTime.Now.ToString("hh:mm:ss.fff")); } finally { //if (proc != null) { proc.Detach().WaitOne(); } } return samples; }
/// <summary> /// Gets the output of a function using MDbg. /// </summary> /// <example> /// <code lang="CS" title="Getting the Message from an Exception" description="An example showing how you would get the value of the Message property of an Exception. The variable ex is a MDbgValue object that represents the exception you are examining."> /// MDbgValue returnValue = ResolveFunction(debuggedProc, ex, "System.Exception.get_Message"); /// string message = returnValue.GetStringValue(true); /// </code> /// </example> /// <param name="debuggedProc">The process we are debugging.</param> /// <param name="ex">The MDbgValue object to execute the function on.</param> /// <param name="function">The full name of the function in MDbg syntax.</param> /// <returns>The MDbgValue that contains the return value of the function. If the function /// could not be evaluated, it returns null.</returns> private MDbgValue ResolveFunction(MDbgProcess debuggedProc, MDbgValue ex, string function) { CorAppDomain appDomain = debuggedProc.Threads.Active.CorThread.AppDomain; MDbgFunction func = debuggedProc.ResolveFunctionNameFromScope(function, appDomain); if (func == null) throw new Exception("A required function is missing. Are you running a template compiled with an different version of ArchAngel?"); CorEval eval = debuggedProc.Threads.Active.CorThread.CreateEval(); eval.CallFunction(func.CorFunction, new[] { ex.CorValue }); debuggedProc.Go().WaitOne(); if (!(debuggedProc.StopReason is EvalCompleteStopReason)) { return null; } eval = ((EvalCompleteStopReason)debuggedProc.StopReason).Eval; if (eval == null) { return null; } CorValue cv = eval.Result; if (cv != null) { MDbgValue mv = new MDbgValue(debuggedProc, cv); return mv; } return null; }
public void StartListening() { if (m_processId == -1) return; if (m_blnIsListening) return; m_debugger = new MDbgEngine(); m_process = null; m_blnIsListening = true; Task t = Task.Factory.StartNew(() => { try { string timeString1 = DebuggerUtils.GetTimeString(true); m_process = DebuggerUtils.AttachToProcess(m_processId, m_debugger); LastLogFileName = Path.Combine(LogFileDirectory, m_process.Name + "(" + m_processId + ") T" + timeString1 + ".log"); } catch (Exception ex) { DebuggerUtils.HandleException(ex); } try { //m_process.Go(); //m_process.Go().WaitOne(); //m_process.Detach(); //m_debugger.Options.StopOnLogMessage = true; m_debugger.Options.StopOnException = true; //m_debugger.Options.StopOnExceptionEnhanced = false; m_debugger.Options.StopOnUnhandledException = true; m_blnIsListening = true; while (m_process.IsAlive) { //if (e.CallbackType == ManagedCallbackType.OnException2) //{ // var ce = (CorException2EventArgs)e.CallbackArgs; // if (ce.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE) // { // var thread = process.Threads.Lookup(ce.Thread); // foreach (var frame in thread.Frames) // { // if (!frame.IsManaged || frame.Function.FullName.StartsWith("System.")) // break; // log.Log("{0}({1})", frame.Function.FullName, string.Join(", ", frame.Function.GetArguments(frame).Select( // arg => string.Format("{0} = {1}", arg.Name, arg.GetStringValue(false))))); // } // } //} try { m_process.Go().WaitOne(); //if (e.CallbackType == ManagedCallbackType.OnBreakpoint) //m_process.Go().WaitOne(); object o = m_process.StopReason; ExceptionThrownStopReason stopReason = o as ExceptionThrownStopReason; if (stopReason != null) { if (stopReason.EventType == Microsoft.Samples.Debugging.CorDebug.NativeApi.CorDebugExceptionCallbackType.DEBUG_EXCEPTION_UNHANDLED) { string timeString = DebuggerUtils.GetTimeString(true); if (WriteDumpOnUncaughtExceptions) { m_strLastDumpFileName = Path.Combine(m_strDumpFileDirectory, m_process.Name + timeString + ".dmp"); DumpWriter.WriteDump(m_process.CorProcess.Id, m_strLastDumpFileName, DumpOptions.WithFullMemory); } } if (LogExceptions) { //File.AppendAllText(LastLogFileName, DateTime.Now.ToString("dd\\MM\\yyyy mm:hh:ss.fff]") + DebuggerUtils.GetExceptionDescFromProcess(m_process) + "\n"); try { string exceptionDesc = DebuggerUtils.GetExceptionDescFromProcess(m_process, true); //Console.Out.WriteLine("----------------------------------------------------"); //Console.Out.WriteLine(exceptionDesc); File.AppendAllText(LastLogFileName, "----------------------------------------------------\n" + DateTime.Now.ToString("dd\\MM\\yyyy mm:hh:ss.fff]") + exceptionDesc + "\n"); m_sbProcessLog.AppendLine("----------------------------------------------------\n"); m_sbProcessLog.AppendLine(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff")); m_sbProcessLog.AppendLine(exceptionDesc); } catch (Exception ex) { DebuggerUtils.HandleException(ex); } //m_process.Go(); } } } catch (Exception ex) { DebuggerUtils.HandleException(ex); } } m_blnIsListening = false; } catch (Exception ex) { DebuggerUtils.HandleException(ex); } //m_process.PostDebugEvent += m_processEventHandler; }); }
/// <summary>Starts the debugging process. This is synchronised on the Debugger /// object it is called on.</summary> /// <remarks> /// Assumes that the DebuggerSync object has been set up correctly and that something /// is listening to the BackgroundWorker events. It will lock indefinitely if something /// doesn't tell it to continue by calling set on the DebuggerSync.ContinueDebugExecution /// object. /// </remarks> public void Run() { lock (this) { int pid = DebugProcess.GetDebugProcessId(); CommandReceiver obj = DebugProcess.GetCommandReceiver(); // Get Assembly Search paths. These are used for finding // any assemblies that are used by the template. List<string> assemblySearchPaths = new List<string>(); foreach (string assemblyLocation in AssemblyLocations) { string dir = Path.GetDirectoryName(assemblyLocation).ToLower(); if (assemblySearchPaths.BinarySearch(dir) < 0) { assemblySearchPaths.Add(dir); assemblySearchPaths.Sort(); } } obj.ExecuteCommand(new RunFunctionCommand(CompiledAssemblyLocation, TestNamespace, TestClassname, TestFunctionName, ArgumentList, UserOptions, AaprojXml, IsFunctionStatic)); // This is a race condition, but it is required because we can't create the breakpoints // before attaching to the process. MDbgEngine debugger = new MDbgEngine(); proc = debugger.Attach(pid); _CurrentlyRunningBreakpoints.Clear(); foreach (int bp in _Breakpoints) { _CurrentlyRunningBreakpoints.Add(bp, proc.Breakpoints.CreateBreakpoint(CodeFilename, bp)); } proc.Breakpoints.CreateBreakpoint("Commands.cs", LAST_LINE_IN_MAIN); proc.Breakpoints.CreateBreakpoint(CodeFilename, LAST_LINE_IN_FUNCTION); _CurrentlyRunningProcess = proc; while (proc.IsAlive) { // Let the debuggee run and wait until it hits a debug event. switch (_DebuggerSync.NextDebugAction) { case DebugActionType.Continue: proc.Go().WaitOne(); break; case DebugActionType.StepInto: proc.StepInto(false).WaitOne(); break; case DebugActionType.StepOver: proc.StepOver(false).WaitOne(); break; case DebugActionType.StepOut: proc.StepOut().WaitOne(); break; case DebugActionType.Stop: _CurrentlyRunningProcess = null; proc.Breakpoints.DeleteAll(); proc.Detach(); break; } if (!proc.IsAlive) { proc = null; break; } // Get a DebugInformation object filled with the info we need. DebugInformation di = GetDebugInformation(proc); // If this is the last line, we need to stop debugging. if (di.StartLineNumber == LAST_LINE_IN_MAIN) { di.Stopped = false; di.StopReason = StopReason.DebuggerFinished; di.StopReasonText = "Debugger Finished"; _DebuggerSync.DebugBackgroundWorker.ReportProgress(99, di); _CurrentlyRunningProcess = null; proc.Breakpoints.DeleteAll(); proc.Detach(); break; } // Any other lines in the main function should just be skipped. if (di.SourceFile == "Commands.cs") { _DebuggerSync.NextDebugAction = DebugActionType.Continue; continue; } if (di.StartLineNumber == LAST_LINE_IN_FUNCTION) { _DebuggerSync.NextDebugAction = DebugActionType.StepOut; continue; } // If an exception was thrown, report it then stop debugging. if (di.ExceptionThrown) { di.Stopped = false; _DebuggerSync.DebugBackgroundWorker.ReportProgress(99, di); _CurrentlyRunningProcess = null; proc.Breakpoints.DeleteAll(); proc.Detach(); break; } di.Stopped = true; _DebuggerSync.DebugBackgroundWorker.ReportProgress(50, di); _DebuggerSync.ContinueDebugExecution.WaitOne(); continue; } } _CurrentlyRunningProcess = null; }
/// <summary> /// Skip past fake attach events. /// </summary> /// <param name="debugger"></param> /// <param name="proc"></param> public static 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; }