예제 #1
0
        protected void ProcessRecord(bool callWaitForEventDespiteCurrentStatus)
        {
            base.ProcessRecord();

            DEBUG_STATUS currentStatus = Debugger.GetExecutionStatus();

            LogManager.Trace("ExecutionBaseCommand.ProcessRecord: Current status is {0}.", currentStatus);
            if (!callWaitForEventDespiteCurrentStatus && (DEBUG_STATUS.BREAK == currentStatus))
            {
                // TODO: This is for attaching to a debugging server. Need to test it. Other cases?
                // Perhaps this logic should be changed to be more clear?
                LogManager.Trace("ExecutionBaseCommand: current status is already BREAK; will not call WaitForEvent.");
                return; // Don't need to call WaitForEvent.
            }

            using (InterceptCtrlC())
            {
                // We need to perform the wait on another thread, because we need to "pump"
                // on this thread, so that debug event callbacks can queue WriteObject calls
                // to this thread.
                LogManager.Trace("ExecutionBaseCommand: calling WaitForEvent (on dbgeng thread).");

                MsgLoop.Prepare();

                Task waitTask = Debugger.WaitForEventAsync();
                waitTask.ContinueWith((x) => { MsgLoop.SignalDone(); });

                MsgLoop.Run();

                Util.Await(waitTask);   // in case it threw
            } // end using( InterceptCtrlC )
        } // end ProcessRecord()
예제 #2
0
파일: Debugger.cs 프로젝트: zforks/KeeThief
        private void SetDebugStatus(DEBUG_STATUS status)
        {
            int hr = _control.SetExecutionStatus(status);

            if (hr < 0)
            {
                throw new Exception(GetExceptionString("IDebugControl::SetExecutionStatus", hr));
            }
        }
 private SimpleEventHandler(DebugUtilities debugUtilities)
 {
     _installed         = false;
     _utilities         = debugUtilities;
     SessionIsActive    = false;
     ExecutionStatus    = 0;
     _previousCallbacks = IntPtr.Zero;
     _breakpointHandler = null;
 }
예제 #4
0
        } // end BeginProcessing()

        private async Task _WaitIfNeededAsync()
        {
            DEBUG_STATUS execStatus = Debugger.GetExecutionStatus();

            if (_StatusRequiresWait(execStatus))
            {
                LogManager.Trace("InvokeDbgExtensionCommand: Current execution status ({0}) indicates that we should enter a wait.",
                                 execStatus);

                await WaitForBreakAsync();
            }
        } // end _WaitIfNeededAsync()
            public override int ChangeEngineState(DEBUG_CES flags, UInt64 argument)
            {
                if ((flags & DEBUG_CES.EXECUTION_STATUS) != 0)
                {
                    ExecutionStatus = (((DEBUG_STATUS)argument) & DEBUG_STATUS.MASK);

                    if ((((DEBUG_CES_EXECUTION_STATUS)argument) & DEBUG_CES_EXECUTION_STATUS.INSIDE_WAIT) == 0)
                    {
                        _utilities.DebugClient.ExitDispatch(_utilities.DebugClient);
                    }
                }
                return(S_OK);
            }
예제 #6
0
        private DEBUG_STATUS UpdateStatus(bool force = false)
        {
            DEBUG_STATUS status;

            Control.GetExecutionStatus(out status);
            if (Status != status)
            {
                var args = new StatusChangedEventArgs(Status, status);
                Status = status;
                OnStatusChanged(args);
            }
            return(Status);
        }
예제 #7
0
        private void Debugger_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            InvokeAsync(() => {
                if (e.NewStatus == _status)
                {
                    return;
                }

                _status = e.NewStatus;
                UpdateCommands();
                RunRecentExecutableCommand.RaiseCanExecuteChanged();
            });
        }
예제 #8
0
        } // end BeginProcessing()

        protected override void ProcessRecord()
        {
            var inputCallbacks = Debugger.GetInputCallbacks() as DebugInputCallbacks;

            if (null != inputCallbacks)
            {
                inputCallbacks.UpdateCmdlet(this);
            }

            //var outputCallbacks = Debugger.GetOutputCallbacks() as DebugOutputCallbacks;
            //if( null != outputCallbacks )
            //    outputCallbacks.UpdateCmdlet( this );

            using (var disposer = new ExceptionGuard())
            {
                disposer.Protect(Debugger.SetCurrentCmdlet(this));
                disposer.Protect(InterceptCtrlC());

                MsgLoop.Prepare();

                string actualCommand = string.Join(" ", Command);
                Task   t             = Debugger.InvokeDbgEngCommandAsync(actualCommand, OutputPrefix, _ConsumeLine);
                Task   t2            = t.ContinueWith(async(x) =>
                {
                    DEBUG_STATUS execStatus = Debugger.GetExecutionStatus();
                    if (_StatusRequiresWait(execStatus))
                    {
                        LogManager.Trace("InvokeDbgExtensionCommand: Current execution status ({0}) indicates that we should enter a wait.",
                                         execStatus);

                        await WaitForBreakAsync();
                    }

                    disposer.Dispose();
                    SignalDone();
                }).Unwrap();

                MsgLoop.Run();

                Host.UI.WriteLine();
                Util.Await(t);   // in case it threw
                Util.Await(t2);  // in case it threw
            } // end using( disposer )
        } // end ProcessRecord()
예제 #9
0
        }     // end _StatusRequiresWait

        protected async Task WaitForBreakAsync()
        {
            // The actual wait is performed on the dbgeng thread, allowing us to "pump"
            // "messages" on this thread (so that debug event callbacks can queue
            // WriteObject calls to this thread).
            LogManager.Trace("ExecutionBaseCommand.WaitForBreakAsync()");

            bool execStatusRequiresWait = true;

            while (execStatusRequiresWait)
            {
                await Debugger.WaitForEventAsync();

                DEBUG_STATUS execStatus = Debugger.GetExecutionStatus();
                execStatusRequiresWait = _StatusRequiresWait(execStatus);
                if (execStatusRequiresWait)
                {
                    LogManager.Trace("Execution status requires an additional wait: {0}", execStatus);
                }
            }
        } // end WaitForBreakNoLoop()
예제 #10
0
        public void Be_Able_To_Continue_Execution_Until_A_Break_Occurs()
        {
            var controlMock        = new Mock <IDebugControl6>();
            var clientMock         = new Mock <IDebugClient5>();
            var registersMock      = new Mock <IDebugRegisters2>();
            var systemObjectsMock  = new Mock <IDebugSystemObjects>();
            var dataSpacesMock     = new Mock <IDebugDataSpaces>();
            var executeWrapperMock = new Mock <IExecuteWrapper>();

            DEBUG_STATUS status = DEBUG_STATUS.GO;
            int          i      = 0;

            controlMock.Setup(control => control.GetExecutionStatus(out status)).Callback(() =>
            {
                DEBUG_STATUS status2 = DEBUG_STATUS.BREAK;
                if (i > 0)
                {
                    controlMock.Setup(control => control.GetExecutionStatus(out status2));
                }
                i++;
            });


            const string Value = @"PEB at 00000041e9154000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            No";

            executeWrapperMock.Setup(wrapper => wrapper.Execute(It.IsAny <string>())).Returns(Value);

            var eng = new DebugEngineProxy(controlMock.Object, clientMock.Object, registersMock.Object,
                                           systemObjectsMock.Object,
                                           dataSpacesMock.Object, executeWrapperMock.Object);

            eng.RunUntilBreak();

            controlMock.Verify(control => control.GetExecutionStatus(out status), Times.Exactly(3));
        }
예제 #11
0
        } // end InterceptCtrlC()

        protected static bool _StatusRequiresWait(DEBUG_STATUS execStatus)
        {
            switch (execStatus)
            {
            case DEBUG_STATUS.BREAK:
            case DEBUG_STATUS.NO_DEBUGGEE:
            case DEBUG_STATUS.RESTART_REQUESTED:
                return(false);

            case DEBUG_STATUS.GO:
            case DEBUG_STATUS.STEP_OVER:
            case DEBUG_STATUS.STEP_INTO:
            case DEBUG_STATUS.STEP_BRANCH:
            case DEBUG_STATUS.REVERSE_GO:
            case DEBUG_STATUS.REVERSE_STEP_BRANCH:
            case DEBUG_STATUS.REVERSE_STEP_OVER:
            case DEBUG_STATUS.REVERSE_STEP_INTO:
                return(true);

            case DEBUG_STATUS.OUT_OF_SYNC:
            case DEBUG_STATUS.TIMEOUT:
            case DEBUG_STATUS.WAIT_INPUT:
                Util.Fail(Util.Sprintf("I wonder if I should handle this status here: {0}", execStatus));
                return(false);

            case DEBUG_STATUS.GO_HANDLED:
            case DEBUG_STATUS.GO_NOT_HANDLED:
            case DEBUG_STATUS.IGNORE_EVENT:
            case DEBUG_STATUS.NO_CHANGE:
                Util.Fail(Util.Sprintf("I don't think I should ever receive this status: {0}", execStatus));
                return(false);

            default:
                string msg = Util.Sprintf("Unexpected DEBUG_STATUS: {0} ({1}).", execStatus, (int)execStatus);
                Util.Fail(msg);
                throw new Exception(msg);
            } // end switch( execStatus )
        }     // end _StatusRequiresWait
예제 #12
0
        public void AttachAndExecute()
        {
            // Explicitly load app-local dependencies.
            LoadNative("dbghelp.dll");
            LoadNative("symsrv.dll");
            LoadNative("dbgeng.dll");

            // Attach to the process.
            using (DataTarget targetProcess = DataTarget.AttachToProcess(_PID, AttachTimeoutInMsec))
            {
                // Create a new debugger wrapper object.
                Debugger debugger = new Debugger(targetProcess, _Log);

                // Subscribe to exception handling.
                debugger.Callbacks.HandleExceptionEvent += HandleException;

                // Dump symbol information and set high verbosity on symbol output.
                debugger.Execute(".sympath");
                debugger.Execute("!sym noisy");

                // Force load the PDB for clr.dll
                debugger.Execute(".reload /f clr.dll");

                // Ensure that the PDB for clr.dll was successfully loaded.  We do this by attempting to load one of the required symbols.
                ulong baseAddress;
                if (debugger.DebugSymbols.GetSymbolModule("clr!SVR::gc_heap::n_heaps", out baseAddress) != 0)
                {
                    throw new Exception("CLR symbols are not properly loaded.  Please set the symbol path and try again.");
                }

                // Load SOS.
                debugger.Execute(".loadby sos clr");

                // Execute find roots, which will throw an exception when we complete the mark phase.
                debugger.Execute("!FindRoots -gen " + _GenerationToTrigger);

                // GO!
                debugger.DebugControl.SetExecutionStatus(DEBUG_STATUS.GO);

                // Loop until we have captured the right number of dumps, or we are no longer attached
                // to the debuggee.
                DEBUG_STATUS debuggerStatus = DEBUG_STATUS.NO_CHANGE;
                int          hr;
                do
                {
                    hr = debugger.DebugControl.WaitForEvent(0, WaitForEventTimeoutInMsec);
                    if (hr < 0)
                    {
                        _Log.WriteLine("Failure encountered in WaitForEvent.  HR: {0:x}", hr);
                        _EncounteredException = new Exception("Failure encountered in WaitForEvent.");
                        break;
                    }
                    hr = debugger.DebugControl.GetExecutionStatus(out debuggerStatus);
                    if (hr < 0)
                    {
                        _Log.WriteLine("Failure encountered in GetExecutionStatus.  HR: {0:x}", hr);
                        _EncounteredException = new Exception("Failure encountered in GetExecutionStatus.");
                        break;
                    }
                }while ((debuggerStatus != DEBUG_STATUS.NO_DEBUGGEE) && (_EncounteredException == null) && (!_CapturedDump));

                // Once we're done, detach the debuggee so that it doesn't get killed.
                if (debuggerStatus != DEBUG_STATUS.NO_CHANGE)
                {
                    debugger.DebugClient.DetachProcesses();
                }

                // If we encountered an exception, throw it here.
                if (_EncounteredException != null)
                {
                    throw _EncounteredException;
                }
            }
        }
예제 #13
0
 private void SetDebugStatus(DEBUG_STATUS status)
 {
     int hr = _control.SetExecutionStatus(status);
     if (hr < 0)
         throw new Exception(GetExceptionString("IDebugControl::SetExecutionStatus", hr));
 }
예제 #14
0
 public int GetExecutionStatus(out DEBUG_STATUS status)
 {
     return(_control.GetExecutionStatus(out status));
 }
예제 #15
0
 internal StatusChangedEventArgs(DEBUG_STATUS oldStatus, DEBUG_STATUS newStatus)
 {
     OldStatus = oldStatus;
     NewStatus = newStatus;
 }