Exemplo n.º 1
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            try
            {
                if (Increment)
                {
                    var ctx = Debugger.GetCurrentDbgEngContext();
                    _Worker(ctx.FrameIndex + 1, "CannotIncrementPastTopOfStack");
                    DbgProvider.SetAutoRepeatCommand(".f+");
                }
                else if (Decrement)
                {
                    var ctx = Debugger.GetCurrentDbgEngContext();
                    _Worker(ctx.FrameIndex - 1, "CannotDecrementPastBottomOfStack");
                    DbgProvider.SetAutoRepeatCommand(".f-");
                }
                else
                {
                    _Worker(FrameNumber, "StackFrameOutsideOfActualStack");
                }
            }
            catch (DbgProviderException dpe)
            {
                WriteError(dpe);
            }

            DbgProvider.SetLocationByDebuggerContext();
        } // end ProcessRecord()
        // NOTE: If a derived class needs to override BeginProcessing, it should be sure
        // to call base.BeginProcessing() /before/ calling any of the SafeWrite* methods.
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            m_pipelineThread = Thread.CurrentThread;
            if (LogCmdletOutline)
            {
                LogManager.Trace("---------------------------");
                LogManager.Trace("BeginProcessing for command {0}: {1}", this, GetCommand());
            }

            // You might think that the host should be the one to clear the auto-repeat
            // command, and in general, you'd be right. But the host doesn't actually get
            // involved with EVERY command that is run--it is only involved with every
            // /input/. And that input could be a script, and that script could run some
            // commands that set up an auto-repeat command (like stepping), and then run
            // some other commands (like .detach, or anything), leaving the auto-repeat
            // command set up, but the user definitely does not expect pressing [enter]
            // to step again (or do whatever the auto-repeat command was). So, for non-
            // formatting commands, we'll always start out by clearing the auto-repeat
            // command. (We exclude formatting commands, because then auto-repeat commands
            // would never work, because formatting commands are always tacked on to the
            // end of pipelines.)
            //
            // Note that this does not completely solve the problem, because cmdlets that
            // derive from DbgBaseCommand are not the only commands that could be run
            // after an auto-repeat command. But it at least helps.
            //
            // A more complete alternative might be to hook the PreCommandLookupAction and
            // clear the auto-repeat command there, but it would have to be a lot
            // trickier, because we'd need to do things like exclude auto-repeat-command-
            // clearing during execution of the "prompt" command, the PSReadline command,
            // etc. (in addition to formatting commands).
            if (!typeof(Formatting.Commands.FormatBaseCommand).IsAssignableFrom(GetType()) &&
                !typeof(Formatting.Commands.GetAltFormatViewDefCommand).IsAssignableFrom(GetType()))
            {
                DbgProvider.SetAutoRepeatCommand(null);
            }

            if (TrySetDebuggerContext)
            {
                // Need to set context based on current path.
                PathInfo pi      = this.CurrentProviderLocation(DbgProvider.ProviderId);
                string   curPath = pi.ProviderPath;
                // It's okay if it fails (maybe current dir is "Dbg:\")--some commands don't
                // need a context.
                Debugger.TrySetContextByPath(curPath);
            }
        } // end BeginProcessing()
Exemplo n.º 3
0
        } // end ProcessRecord()

        private void _UnassembleInstructions(ulong addr, Func <ulong, bool> keepGoing)
        {
            ColorString csBlockId;

            try
            {
                ulong disp;
                var   addrName = Debugger.GetNameByOffset(addr, out disp);
                csBlockId = DbgProvider.ColorizeSymbol(addrName);
                if (0 != disp)
                {
                    csBlockId.Append(Util.Sprintf("+{0:x}", disp));
                }
            }
            catch (DbgEngException)
            {
                // Ignore. We'll just use the address as the block id. If we really can't
                // get the memory there, we'll fail with a good error message later.
                csBlockId = new ColorString().Append(DbgProvider.FormatAddress(addr,
                                                                               Debugger.TargetIs32Bit,
                                                                               true));
            }

            csBlockId.Append(":").MakeReadOnly();

            bool hasCodeBytes = !Debugger.AssemblyOptions.HasFlag(DbgAssemblyOptions.NoCodeBytes);

            while (keepGoing(addr))
            {
                ulong  tmpAddr = addr;
                string disasm  = Debugger.Disassemble(tmpAddr, out addr).Trim();
                WriteObject(_ParseDisassembly(tmpAddr,
                                              disasm,
                                              csBlockId,
                                              hasCodeBytes));
            }
            DbgProvider.SetAutoRepeatCommand(Util.Sprintf("{0} -Address 0x{1} -InstructionCount {2}",
                                                          MyInvocation.InvocationName,
                                                          addr.ToString("x"),
                                                          InstructionCount));
            NextAddrToDisassemble = addr;
        } // end _UnassembleInstructions()
Exemplo n.º 4
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            if (0 == Address)
            {
                Address = NextAddressToDump;
            }

            if (!MyInvocation.BoundParameters.ContainsKey("DefaultDisplayFormat"))
            {
                DefaultDisplayFormat = NextDefaultFormat;
            }

            if (!MyInvocation.BoundParameters.ContainsKey("LengthInBytes"))
            {
                if (DefaultDisplayFormat != NextDefaultFormat)
                {
                    // We're switching formats; may need to also switch the default size.
                    LengthInBytes = _GetDefaultReadSize(DefaultDisplayFormat);
                }
                else
                {
                    LengthInBytes = NextDefaultLengthInBytes;
                }
            }

            if (0 == LengthInBytes)
            {
                LengthInBytes = _GetDefaultReadSize(DefaultDisplayFormat);
            }

            // Okay, we've got a length + display format, but one or the other may be
            // defaulted. In that case, we want to make sure that the LengthInBytes is
            // compatible with the display format. (And actually, even if they were both
            // explicitly specified, we /still/ want to make sure they are compatible.)
            //
            // For instance, if the LengthInBytes was explicitly specified as 4, and the
            // display format got defaulted to PointersWithAscii, on a 64-bit target, we
            // are not going to be able to display anything (because we won't have read
            // even a single full pointer)--we need to downgrade the display format to fit
            // the size requested, if possible.

            if (!_IsDisplayFormatCompatibleWithReadSize(LengthInBytes, DefaultDisplayFormat, Debugger.PointerSize))
            {
                var compatibleDisplayFormat = _GetDefaultDisplayFormatForSize(LengthInBytes, Debugger.PointerSize);

                if (MyInvocation.BoundParameters.ContainsKey("DefaultDisplayFormat"))
                {
                    SafeWriteWarning("The specified display format ({0}) is not compatible with the byte length requested ({1}). The {2} format will be used instead.",
                                     DefaultDisplayFormat,
                                     LengthInBytes,
                                     compatibleDisplayFormat);
                }
                // else just silently fix it up.

                DefaultDisplayFormat = compatibleDisplayFormat;
            }

            if (!MyInvocation.BoundParameters.ContainsKey("DefaultDisplayColumns"))
            {
                DefaultDisplayColumns = NextDefaultNumColumns;
            }

            var raw = Debugger.ReadMem(Address, LengthInBytes, false);

            if (raw.Length != LengthInBytes)
            {
                WriteWarning(Util.Sprintf("Actual memory read (0x{0:x} bytes) is less than requested (0x{1:x} bytes).",
                                          raw.Length,
                                          LengthInBytes));
            }
            var mem = new DbgMemory(Address,
                                    raw,
                                    Debugger.TargetIs32Bit,
                                    false,  // TODO: actually determine endianness
                                    Debugger);

            mem.DefaultDisplayFormat  = DefaultDisplayFormat;
            mem.DefaultDisplayColumns = DefaultDisplayColumns;

            NextAddressToDump        = Address + (ulong)raw.Length;
            NextDefaultFormat        = DefaultDisplayFormat;
            NextDefaultLengthInBytes = LengthInBytes;
            NextDefaultNumColumns    = DefaultDisplayColumns;

            WriteObject(mem);

            DbgProvider.SetAutoRepeatCommand(Util.Sprintf("{0}", MyInvocation.InvocationName));
        } // end ProcessRecord()
Exemplo n.º 5
0
        protected override void ProcessRecord()
        {
            using (SetDebuggerAndContextAndUpdateCallbacks())
            {
                EnsureTargetCanStep(Debugger);

                // In the native debugger, if you are in some other frame, your scope
                // is reset (to the top frame), but not your thread.
                Debugger.SetCurrentScopeFrame(0);

                switch (ResumeType)
                {
                case Dbg.ResumeType.ReverseStepBranch:
                case Dbg.ResumeType.ReverseStepInto:
                case Dbg.ResumeType.ReverseStepOver:
                case Dbg.ResumeType.StepBranch:
                case Dbg.ResumeType.StepInto:
                case Dbg.ResumeType.StepOver:
                case Dbg.ResumeType.StepOut:
                case Dbg.ResumeType.StepToCall:
                    m_baselineRegisters = DbgRegisterSetBase.GetRegisterSet(Debugger);
                    break;
                }

                if (ResumeType.Passive != ResumeType)
                {
                    try
                    {
                        Debugger.ResumeExecution(ResumeType);
                    }
                    catch (DbgEngAlreadyRunningException)
                    {
                        SafeWriteWarning("Target has already been resumed.");
                        //
                        // We'll just proceed, then, to wait...
                        //
                    }
                }

                bool noException = false;
                try
                {
                    Debugger.BreakpointHit += Debugger_BreakpointHit;

                    if (DbgProvider.IsInBreakpointCommand)
                    {
                        Util.Assert(DbgProvider.EntryDepth > 0);

                        // If we are executing as a breakpoint command, and someone is
                        // resuming execution, we have to handle it specially:
                        //
                        // 1. We need to cancel the rest of the pipeline. This is the same
                        //    way that dbgeng breakpoint commands work (if your bp command
                        //    is "!foo;g;!bar", then !bar will not ever be executed.
                        //
                        //    At first glance you might think that you are getting robbed
                        //    of some cool power by canceling any remaining commands, but
                        //    if you think a little more about it, you realize it would be
                        //    very difficult to reason about what should happen. For
                        //    example, consider:
                        //
                        //       bp myDll!Foo "!stuff ; g ; !otherStuff"
                        //
                        //    The first time you hit the breakpoint, "!stuff" is run, then
                        //    execution is resumed. The seocnd time the breakpoint is
                        //    hit... what should be run first--"!otherStuff", or "!stuff"?
                        //    And you could get nested much further. So we'll take the
                        //    same easy out as dbgeng, and treat "g" as an "exit" in a
                        //    breakpoint command.
                        //
                        //    TODO: we could run the script through the parser and warn
                        //    about unreachable code after a "g" command.
                        //
                        // 2. When a breakpoint hits and a breakpoint command is run, the
                        //    dbgeng thread is blocked, waiting for the breakpoint command
                        //    to finish. If we want to resume execution from within a
                        //    breakpoint command, we can tell dbgeng to resume, but if we
                        //    then turn around and call WaitForEvent (which is what we
                        //    normally do), then you're deadlocked--WaitForEvent can never
                        //    return, because before dbgeng can let the target resume,
                        //    your breakpoint command has to return, but it can't return
                        //    because it's waiting for WaitForEvent.
                        //
                        //    So in this case, once we've instructed dbgeng to execute, we
                        //    need to return from the command and let dbgeng let the
                        //    target resume. We will depend on the "host" (whether it be
                        //    windbg or DbgShell or something else) to do the
                        //    WaitForEvent. Fortunately, "exit" should get us what we want
                        //    for this case, too.
                        //
                        //    TODO: what if we are nested a few levels deep? i.e.
                        //
                        //       bp myDll!foo "!dbgshell -Bp !dbgshell write-host 'so nested!' -fore Yellow , g"
                        //
                        //    I'm not sure how we'd get the "exit" to propagate out from
                        //    the inner !dbgshell, through the outer one, so that we could
                        //    return to the host.
                        //
                        //    Also, if we are nested, and multiple levels use -Bp, we're
                        //    definitely broken--I'd need to change inBreakpointCommand to
                        //    be a count instead of a bool, for one thing.
                        //

                        if (null != m_baselineRegisters)  // <-- shortcut for determining if we are stepping
                        {
                            // If someone is trying to step while inside a breakpoint
                            // command, let's let them know what's going on.
                            this.InvokeCommand.InvokeScript("Write-Host 'Resuming execution from within a breakpoint " +
                                                            "command necessarily returns control to the host, for it " +
                                                            "to perform the wait.' -Fore Cyan");
                            this.InvokeCommand.InvokeScript("Write-Host '(it also acts like an 'exit'; terminating the " +
                                                            "current pipeline and discarding any remaining commands)' " +
                                                            " -Fore Cyan");
                            this.InvokeCommand.InvokeScript("Write-Host '(if you want to step in DbgShell instead of " +
                                                            "the host, just run !dbgshell again from the host and then " +
                                                            "step)' -Fore Cyan");

                            // Give them a chance to notice that a message was printed out
                            // before we switch the foreground window:
                            this.InvokeCommand.InvokeScript("Start-Sleep -Milliseconds 500");
                        }

                        if (!DbgProvider.IsInGuestMode)
                        {
                            // If DbgShell.exe is the host, then we need to let it know
                            // that it shouldn't exit all the way; we're just trying to
                            // terminate the current breakpoint script.
                            DbgProvider.DontExitAllTheWay = true;
                        }

                        // Throwing an ExitException would be much more direct, but there
                        // are no public constructors for it.
                        //throw new ExitException();
                        this.InvokeCommand.InvokeScript("exit");
                    }

                    base.ProcessRecord(); // sets up ctrl-c interception, performs wait.
                    noException = true;
                }
                finally
                {
                    Debugger.BreakpointHit -= Debugger_BreakpointHit;

                    _TryRemoveSpecialBp();

                    // We check NoTarget before setting the auto-repeat command, because
                    // if -skipFinalBreakpoint was used, the target might be completely
                    // gone (leaving you back with a working dir of "Dbg:\"), and it would
                    // be nice if hitting [ENTER] for a newline right there didn't try to
                    // auto-repeat your last "g" command (which would blow up with a "no
                    // target!" error).
                    if (noException && !Debugger.NoTarget)
                    {
                        DbgProvider.SetAutoRepeatCommand(MyInvocation.Line.Trim());
                    }
                }
                if (null != m_bea)
                {
                    // if( m_bea.Breakpoint.IsValid )
                    //     Console.WriteLine( "Breakpoint hit. The command was: {0}", m_bea.Breakpoint.Command );
                    // else
                    //     Console.WriteLine( "Breakpoint hit. (breakpoint no longer valid)" );

                    // TODO: Idea: I could accept ScriptBlocks as commands to be executed, and store
                    // them with dbgeng in the form of a string identifier, like "ScriptBlock_NNNN",
                    // or probably better, "!dbgshell ScriptBlock_NNNN". I need to figure out what
                    // happens with the breakpoint command when I'm just a debugger client.
                }
            }
        } // end ProcessRecord()
Exemplo n.º 6
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            if (0 == Address)
            {
                Address = NextAddressToDump;
            }

            if (!MyInvocation.BoundParameters.ContainsKey("DefaultDisplayFormat"))
            {
                DefaultDisplayFormat = NextDefaultFormat;
            }

            if (!MyInvocation.BoundParameters.ContainsKey("LengthInBytes"))
            {
                if (DefaultDisplayFormat != NextDefaultFormat)
                {
                    // We're switching formats; may need to also switch the default size.
                    LengthInBytes = _GetDefaultReadSize(DefaultDisplayFormat);
                }
                else
                {
                    LengthInBytes = NextDefaultLengthInBytes;
                }
            }

            if (0 == LengthInBytes)
            {
                LengthInBytes = _GetDefaultReadSize(DefaultDisplayFormat);
            }

            if (!MyInvocation.BoundParameters.ContainsKey("DefaultDisplayColumns"))
            {
                DefaultDisplayColumns = NextDefaultNumColumns;
            }

            var raw = Debugger.ReadMem(Address, LengthInBytes, false);

            if (raw.Length != LengthInBytes)
            {
                WriteWarning(Util.Sprintf("Actual memory read (0x{0:x} bytes) is less than requested (0x{1:x} bytes).",
                                          raw.Length,
                                          LengthInBytes));
            }
            var mem = new DbgMemory(Address,
                                    raw,
                                    Debugger.TargetIs32Bit,
                                    false,  // TODO: actually determine endianness
                                    Debugger);

            mem.DefaultDisplayFormat  = DefaultDisplayFormat;
            mem.DefaultDisplayColumns = DefaultDisplayColumns;

            NextAddressToDump        = Address + (ulong)raw.Length;
            NextDefaultFormat        = DefaultDisplayFormat;
            NextDefaultLengthInBytes = LengthInBytes;
            NextDefaultNumColumns    = DefaultDisplayColumns;

            WriteObject(mem);

            DbgProvider.SetAutoRepeatCommand(Util.Sprintf("{0}", MyInvocation.InvocationName));
        } // end ProcessRecord()