/// <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;
        }
Exemple #2
0
        /// <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;
            });
        }
Exemple #4
0
        /// <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;
        }