Beispiel #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()
Beispiel #2
0
        } // end InterceptCtrlC()

        protected override void ProcessRecord()
        {
            if (!DbgProvider.IsInGuestMode)
            {
                throw new InvalidOperationException("This command is only intended to be used by the !dbgshell implementation.");
            }

            LogManager.Trace("WaitForBangDbgShellCommandCommand.ProcessRecord: DbgShell is going dormant.");

            using (var disposer = new ExceptionGuard())
            {
                disposer.Protect(SetDebuggerAndContextAndUpdateCallbacks());
                disposer.Protect(InterceptCtrlC());
                disposer.Protect(Debugger.SuspendEventOutput());   // don't want our "modload" output etc. spewing while we are dormant

                base.ProcessRecord();
                // 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.
                _RegisterWaitForGuestModeEvent(disposer);

                // Give the user a hint about what's going on.
                var s = new ColorString(ConsoleColor.DarkGray,
                                        "(DbgShell will remain running in the background until you run !dbgshell again)").ToString(true);
                Host.UI.WriteLine(s);

                MsgLoop.Prepare();

                // This will allow the extension command to return (it tells the dbgeng
                // thread that it can return).
                DbgProvider.GuestModePassivate();

                MsgLoop.Run(); // This will complete when the guest mode event gets signaled.
            } // end using( disposer )
        } // end ProcessRecord()
Beispiel #3
0
        } // end _CallExtensionAsync()

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

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

            // TODO: Why does this cmdlet even need to be an ExecutionBaseCommand?

            using (InterceptCtrlC())
                using (Debugger.SetCurrentCmdlet(this))
                {
                    ulong hExt = 0;

                    int dotIdx = ExtensionCommand.LastIndexOf('.');
                    if (dotIdx > 0)
                    {
                        if (dotIdx == (ExtensionCommand.Length - 1))
                        {
                            throw new ArgumentException("ExtensionCommand cannot end with a '.'.");
                        }

                        string extName = ExtensionCommand.Substring(0, dotIdx);
                        var    elr     = Debugger.GetExtensionDllHandle(extName, true);
                        if (null == elr)
                        {
                            throw new DbgProviderException(Util.Sprintf("Could not find/load extension: {0}.",
                                                                        extName),
                                                           "CouldNotLoadExtension",
                                                           ErrorCategory.ObjectNotFound,
                                                           extName);
                        }
                        if (!String.IsNullOrEmpty(elr.LoadOutput))
                        {
                            SafeWriteObject(elr.LoadOutput);
                        }

                        ExtensionCommand = ExtensionCommand.Substring(dotIdx + 1);
                    }

                    MsgLoop.Prepare();

                    Task t = _CallExtensionAsync(hExt, ExtensionCommand, ExtensionArgs);

                    MsgLoop.Run();

                    Host.UI.WriteLine();
                    Util.Await(t); // in case it threw
                }                  // end using( InterceptCtrlC )
        } // end ProcessRecord()
Beispiel #4
0
        } // end _FixPsPathsInSymbolPath()

        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            if (null == Path)
            {
                Path = String.Empty;
            }

            //
            // Fix PS-specific paths.
            //
            var fixedPath = _FixPsPathsInSymbolPath(Path, GetUnresolvedProviderPathFromPSPath);

            if (0 == fixedPath.Length)
            {
                WriteWarning("The symbol path is empty.");
            }

            Debugger.SymbolPath = fixedPath;
            if (PassThru)
            {
                WriteObject(Debugger.SymbolPath);
            }

            MsgLoop.Prepare();

            // If the specified symbol path is inaccessible, the SetSymbolPathWide call
            // will generate some warning dbgeng output. But we'd also like to be able to
            // get output about the "expanded" symbol path. Unfortunately, there is no way
            // to get that, except to parse ".sympath" output. Since executing ".sympath"
            // will also repeat the warning about the inaccessible symbol path, we won't
            // start displaying dbgeng output until now.
            using (Debugger.HandleDbgEngOutput(_HandleDbgEngOutput))
            {
                // TODO: Feature request: no way to get expanded symbol path except to parse ".sympath" output.
                var t = Debugger.InvokeDbgEngCommandAsync(".sympath", false);

                t.ContinueWith((x) => MsgLoop.SignalDone());

                MsgLoop.Run();

                Util.Await(t);   // in case it threw
            }
        } // end ProcessRecord()
Beispiel #5
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()
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            using (var disposer = new ExceptionGuard(Debugger.HandleDbgEngOutput(_ConsumeLine)))
            {
                // Failure to load an extension should be a terminating error.
                //
                // Because the only reason to load an extension is so that you can call
                // commands in it. And if you didn't load it, then none of those commands
                // will work.

                string providerPath = PathOrName;

                if (providerPath.IndexOfAny(sm_dirSeparators) >= 0)
                {
                    // We support PS paths.
                    //
                    // (we don't want to call GetUnresolvedProviderPathFromPSPath if it's
                    // just a bare name, else PS will interpret that as a relative path,
                    // which would be wrong)
                    providerPath = GetUnresolvedProviderPathFromPSPath(PathOrName);
                }

                MsgLoop.Prepare();

                var t = Debugger.AddExtensionAsync(providerPath);
                t.ContinueWith((x) => { disposer.Dispose(); SignalDone(); });

                MsgLoop.Run();

                var elr = Util.Await(t);   // in case it threw
                if (!string.IsNullOrEmpty(elr.LoadOutput))
                {
                    SafeWriteObject(elr.LoadOutput);
                }
                SafeWriteVerbose("Loaded extension: {0}", PathOrName);
            } // end using( disposer )
        }     // end ProcessRecord()
Beispiel #7
0
        } // end _WaitIfNeededAsync()

        private async Task _CallExtensionAsync(ulong hExt, string extCommand, string extArgs)
        {
            LogManager.Trace("_CallExtensionAsync: {0} {1}", extCommand, extArgs);

            try
            {
                // N.B. We need to be sure that we have unregistered for DbgEngOutput etc.
                // /BEFORE/ SignalDone is called. If not, there could be some DbgEng
                // output that comes after SignalDone has been called, but before we get
                // back from MsgLoop.Run() and dispose of the registrations, and that
                // would blow chunks. (because things like SafeWriteVerbose would not
                // work, because the q was completed when SignalDone was called)
                using (Debugger.HandleDbgEngOutput(_ConsumeLine))
                {
                    await Debugger.CallExtensionAsync(hExt, extCommand, extArgs);
                    await _WaitIfNeededAsync();
                }
            }
            finally
            {
                MsgLoop.SignalDone();
            }
        } // end _CallExtensionAsync()
        // I think this should be for kernel-mode only.
        // [Parameter( Mandatory = false )]
        // public SwitchParameter IgnoreInaccessibleMemory { get; set; }



        protected override void ProcessRecord()
        {
            // Support relative paths in PS.
            string dumpFileResolved = SessionState.Path.GetUnresolvedProviderPathFromPSPath(DumpFile);

            DEBUG_FORMAT flags = DEBUG_FORMAT.DEFAULT;

            flags |= DEBUG_FORMAT.USER_SMALL_FULL_MEMORY |
                     DEBUG_FORMAT.USER_SMALL_HANDLE_DATA |
                     DEBUG_FORMAT.USER_SMALL_UNLOADED_MODULES |
                     DEBUG_FORMAT.USER_SMALL_INDIRECT_MEMORY |
                     DEBUG_FORMAT.USER_SMALL_DATA_SEGMENTS |
                     DEBUG_FORMAT.USER_SMALL_PROCESS_THREAD_DATA |
                     DEBUG_FORMAT.USER_SMALL_PRIVATE_READ_WRITE_MEMORY |
                     DEBUG_FORMAT.USER_SMALL_FULL_MEMORY_INFO |
                     DEBUG_FORMAT.USER_SMALL_THREAD_INFO |
                     DEBUG_FORMAT.USER_SMALL_CODE_SEGMENTS |
                     DEBUG_FORMAT.USER_SMALL_FULL_AUXILIARY_STATE;  // TODO: Need to learn what this means


            // I think this should be for kernel-mode only.
            // if( IgnoreInaccessibleMemory )
            // {
            //     flags |= DEBUG_FORMAT.USER_SMALL_IGNORE_INACCESSIBLE_MEM;
            // }

            // TODO: Figure out these things, and see if there are new ones I don't know about:
            //       DEBUG_FORMAT.USER_SMALL_FILTER_MEMORY |
            //       DEBUG_FORMAT.USER_SMALL_FILTER_PATHS |

            //       DEBUG_FORMAT.USER_SMALL_NO_OPTIONAL_DATA |

            //       DEBUG_FORMAT.USER_SMALL_NO_AUXILIARY_STATE |


            if (!AllowClobber)
            {
                flags |= DEBUG_FORMAT.NO_OVERWRITE;
            }

            if (Compress)
            {
                flags |= DEBUG_FORMAT.WRITE_CAB;
            }

            if (CompressWithSymbols)
            {
                flags |= DEBUG_FORMAT.WRITE_CAB;
                flags |= DEBUG_FORMAT.CAB_SECONDARY_FILES;
                // TODO: What is CAB_SECONDARY_ALL_IMAGES for? DbgEng.h says
                //
                //    "When creating a CAB with secondary images do searches
                //    for all image files, regardless of whether they're
                //    needed for the current session or not."
                //
                // but I don't know what it means for an image file to be "needed" for the
                // current session versus not.
            }

            if ((Compress || CompressWithSymbols) &&
                !DumpFile.EndsWith(".cab", StringComparison.OrdinalIgnoreCase))
            {
                WriteWarning("Output will be compressed, but output file name does not end in '.cab'.");
                WriteWarning("You will need to rename the resulting file to end with '.cab' if you want to be able to mount the dump file with Mount-DbgDumpFile.");
            }

            // TODO: Just let the API fail instead of doing this pre-check?
            if (File.Exists(dumpFileResolved))
            {
                if (!AllowClobber)
                {
                    // is there a better "already exists" exception?
                    WriteError(new InvalidOperationException(Util.Sprintf("The file '{0}' already exists. Use -AllowClobber to overwrite it.",
                                                                          DumpFile)),
                               "DumpFileAlreadyExists",
                               ErrorCategory.ResourceExists,
                               DumpFile);
                    return;
                }
            }

            using (var disposer = new ExceptionGuard())
            {
                disposer.Protect(Debugger.HandleDbgEngOutput((x) => SafeWriteVerbose(x.TrimEnd())));
                disposer.Protect(new CtrlCInterceptor(_CtrlCHandler));

                try
                {
                    MsgLoop.Prepare();

                    var task = Debugger.WriteDumpAsync(DumpFile,
                                                       flags,
                                                       Comment,
                                                       CancelTS.Token);
                    task.ContinueWith((_t) => { disposer.Dispose(); SignalDone(); });

                    MsgLoop.Run();

                    Util.Await(task);   // in case it threw
                }
                catch (DbgProviderException dpe)
                {
                    if ((dpe.HResult == DebuggerObject.E_UNEXPECTED) &&
                        CancelTS.IsCancellationRequested)
                    {
                        WriteWarning("Dump file creation canceled.");
                    }
                    else
                    {
                        WriteError(dpe);
                    }
                }
            } // end using( dbgeng output, CTRL-C )
        }     // end ProcessRecord()