Ejemplo n.º 1
0
class ExitCommand(DebuggerCommand):
    """**exit** [*exitcode*]

    Hard exit of the debugged program.

    The program being debugged is exited via *sys.exit()*. If a return code
    is given, that is the return code passed to *sys.exit()*, the
    return code that will be passed back to the OS.

    See also:
    ---------

    See `quit` and `kill`."""

    short_help = "Exit program via sys.exit()"

    DebuggerCommand.setup(locals(), category="support", max_args=1)

    def run(self, args):
        self.core.stop()
        self.core.execution_status = "Exit command"
        if len(args) <= 1:
            exit_code = 0
        else:
            exit_code = self.proc.get_int(args[1], default=0, cmdname="exit")
            if exit_code is None:
                return False
            pass
        # FIXME: allow setting a return code.
        import sys

        sys.exit(int(exit_code))
        # Not reached
        return True
Ejemplo n.º 2
0
class EnableCommand(DebuggerCommand):
    """**enable** *bpnumber* [*bpnumber* ...]

    Enables the breakpoints given as a space separated list of breakpoint
    numbers. To enable all breakpoints, give no argument. See also `info break` to get a list.

    See also:
    ---------
    `disable`"""

    aliases = ("en", )
    short_help = "Enable some breakpoints"

    complete = complete_bpnumber

    DebuggerCommand.setup(locals(), category="breakpoints")

    def run(self, args):
        if len(args) == 1:
            self.msg(
                self.core.bpmgr.en_disable_all_breakpoints(do_enable=True))
            return
        #         if args[1] == 'display':
        #             self.display_enable(args[2:], 0)
        #             return
        for i in args[1:]:
            success, msg = self.core.bpmgr.en_disable_breakpoint_by_number(
                i, do_enable=True)
            if not success:
                self.errmsg(msg)
            else:
                self.msg("Breakpoint %s enabled." % i)
                pass
            pass
        return
Ejemplo n.º 3
0
class UnaliasCommand(DebuggerCommand):
    """**unalias** *alias-name*

    Remove alias *alias-name*

    See also:
    ---------

    'alias'"""

    min_args = 1
    short_help = "Remove an alias"

    DebuggerCommand.setup(locals(), category="support", max_args=1)

    def complete(self, prefix):
        return complete_token(self.proc.aliases.keys(), prefix)

    # Run command.
    def run(self, args):
        for arg in args[1:]:
            if arg in self.proc.aliases:
                del self.proc.aliases[arg]
                self.msg("Alias for %s removed." % arg)
            else:
                self.msg("No alias found for %s" % arg)
                pass
            pass
        return

    pass
Ejemplo n.º 4
0
class CDCommand(DebuggerCommand):
    """**cd** *directory*

Set working directory to *directory* for debugger and program
being debugged. """

    aliases = ("chdir", )
    short_help = ("Set working directory to DIR for debugger "
                  "and program being debugged")

    DebuggerCommand.setup(
        locals(),
        category="files",
        max_args=1,
        min_args=1,
    )

    def run(self, args):
        try:
            os.chdir(args[1])
            self.msg("Working directory %s." % os.getcwd())
        except OSError:
            self.errmsg("cd: %s." % sys.exc_info()[1])
            pass
        return

    pass
Ejemplo n.º 5
0
class PrettyPrintCommand(DebuggerCommand):
    """**pp** *expression*

Pretty-print the value of the expression.

Simple arrays are shown columnized horizontally. Other values are printed
via *pprint.pformat()*.

See also:
---------

`pr` and `examine` for commands which do more in the way of
formatting.
"""

    short_help = "Pretty print value of expression EXP"

    complete = complete_identifier

    DebuggerCommand.setup(locals(), category="data", min_args=1)

    def run(self, args):
        arg = " ".join(args[1:])
        val = self.proc.eval(arg)
        pp(val, self.settings["width"], self.msg_nocr, self.msg)
        return False

    pass
Ejemplo n.º 6
0
class UpCommand(DebuggerCommand):

    signum = -1  # This is what distinguishes us from "down"

    DebuggerCommand.setup(locals(),
                          category="stack",
                          need_stack=True,
                          max_args=1)

    short_help = ("Move frame in the direction of the caller of "
                  "the last-selected frame")

    def complete(self, prefix):
        proc_obj = self.proc
        return frame_complete(proc_obj, prefix, self.signum)

    def run(self, args):
        """**up** [*count*]

        Move the current frame up in the stack trace (to an older frame). 0 is
        the most recent frame. If no count is given, move up 1.

        See also:
        ---------

        `down` and `frame`."""
        adjust_relative(self.proc, self.name, args, self.signum)
        return False
Ejemplo n.º 7
0
class RunCommand(DebuggerCommand):
    """**run**

    Soft restart debugger and program via a *DebuggerRestart*
    exception.

    See also:
    ---------

    `restart` for another way to restart the debugged program.

    See `quit`, `exit` or `kill` for termination commands."""

    aliases = ("R", )
    short_help = "(Soft) restart program via a DebuggerRestart exception"

    DebuggerCommand.setup(locals(), category="support", max_args=0)

    def run(self, args):
        confirmed = self.confirm("Soft restart", False)
        if confirmed:
            self.core.step_ignore = 0
            self.core.step_events = None
            raise DebuggerRestart(self.core.debugger.restart_argv())
        pass

    pass
Ejemplo n.º 8
0
class AliasCommand(DebuggerCommand):
    """**alias** *alias-name* *debugger-command*

Add alias *alias-name* for a debugger command *debugger-command*.  You
might do this if you want shorter command names or more commands that
have more familiar meanings.

Another related use is as a command abbreviation for a command that
would otherwise be ambiguous. For example, by default we make `s` be
an alias of `step` to force it to be used. Without the alias, `s`
might be `step`, `show`, or `set` among others.

Examples:
--------

    alias cat list   # "cat prog.py" is the same as "list prog.py"
    alias s   step   # "s" is now an alias for "step".
                     # The above example is done by default.

See also:
---------

`unalias` and `show alias`.
    """

    name = "alias"
    short_help = "Add an alias for a debugger command"

    DebuggerCommand.setup(locals(),
                          category="support",
                          max_args=2,
                          need_stack=True)

    # Run command.
    def run(self, args):
        if len(args) == 1:
            self.proc.commands["show"].run(["show", "alias"])
        elif len(args) == 2:
            self.proc.commands["show"].run(["show", "alias", args[1]])
        else:
            junk, al, command = args
            if command in self.proc.commands:
                if al in self.proc.aliases:
                    old_command = self.proc.aliases[al]
                    self.msg(("Alias '%s#' for command '%s'replaced old " +
                              "alias for '%s'.") % (al, command, old_command))
                else:
                    self.msg("New alias '%s' for command '%s' created." %
                             (al, command))
                    pass
                self.proc.aliases[al] = command
            else:
                self.errmsg(("You must alias to a command name, and '%s' " +
                             "and is not one.") % command)
                pass
            return
        pass

    pass
Ejemplo n.º 9
0
class EvalCommand(DebuggerCommand):
    """**eval** *python-statement*

    Run *python-statement* in the context of the current frame.

    If no string is given, we run the string from the current source code
    about to be run. If the command ends `?` (via an alias) and no string is
    given, the following translations occur:

       assert = <expr>       => <expr>
       {if|elif} <expr> :    => <expr>
       while <expr> :        => <expr>
       return <expr>         => <expr>
       for <var> in <expr> : => <expr>
       and <expr>            => <expr>
       or <expr>             => <expr>
       <var> = <expr>        => <expr>

    The above is done via regular expression matching. No fancy parsing is
    done, say, to look to see if *expr* is split across a line or whether
    var an assignment might have multiple variables on the left-hand side.

    Examples:
    ---------

        eval 1+2  # 3
        eval      # Run current source-code line
        eval?     # but strips off leading 'if', 'while', ..
                  # from command

    See also:
    ---------

    `deval`, `set autoeval`, `pr`, `pp` and `examine`."""

    aliases = ("eval?", "?")
    short_help = "Print value of expression EXP"

    DebuggerCommand.setup(locals(), category="data", need_stack=True)

    def run(self, args):
        if 1 == len(args):
            if self.proc.current_source_text:
                text = self.proc.current_source_text.rstrip("\n")
                if "?" == args[0][-1]:
                    text = extract_expression(text)
                    self.msg("eval: %s" % text)
                    pass
            else:
                self.errmsg("Don't have program source text")
                return
        else:
            text = self.proc.current_command[len(self.proc.cmd_name):]
            pass
        text = text.strip()
        try:
            self.proc.exec_line(text)
        except:
            pass
Ejemplo n.º 10
0
class DisplayCommand(DebuggerCommand):
    """**display** [*format*] *expression*

    Print value of expression *expression* each time the program stops.
    *format* may be used before *expression* and may be one of `/c` for
    char, `/x` for hex, `/o` for octal, `/f` for float or `/s` for string.

    For now, display expressions are only evaluated when in the same
    code as the frame that was in effect when the display expression
    was set.  This is a departure from gdb and we may allow for more
    flexibility in the future to specify whether this should be the
    case or not.

    With no argument, evaluate and display all currently requested
    auto-display expressions.  Use `undisplay` to cancel display
    requests previously made."""

    short_help = "Display expressions when entering debugger"

    format_specs = ("/c", "/x", "/o", "/f", "/s")

    DebuggerCommand.setup(locals(), category="data")

    def complete(self, prefix):
        return DisplayCommand.format_specs + complete_id_and_builtins(
            self, prefix)

    def run_eval_display(self, args=None):
        for line in self.proc.display_mgr.display(self.proc.curframe):
            self.msg(line)
        return

    def run(self, args):
        if len(args) == 1:
            # Display anything active
            self.run_eval_display(self)
        else:
            if args[1] in DisplayCommand.format_specs:
                if len(args) == 2:
                    self.errmsg("Expecting an expression after the format")
                    return
                format = args[1]
                expr = " ".join(args[2:])
            else:
                format = None
                expr = " ".join(args[1:])
                pass
            dp = self.proc.display_mgr.add(self.proc.curframe, expr, format)
            if dp is None:
                self.errmsg('Error evaluating "%s" in the current frame' %
                            expr)
                return
            self.msg(dp.format(show_enabled=False))
            self.proc.add_preloop_hook(self.run_eval_display)
            self.msg(dp.to_s(self.proc.curframe))
        return False

    pass
Ejemplo n.º 11
0
    def __init__(self, proc, name=None, base="trepan"):
        """Initialize show subcommands. Note: instance variable name
        has to be setcmds ('set' + 'cmds') for subcommand completion
        to work."""

        DebuggerCommand.__init__(self, proc)

        # Name is set in testing
        if name is None:
            name = self.__module__.split(".")[-1]
        self.__class__.name = name

        self.cmds = Subcmd(name, self)
        self.name = name
        self._load_debugger_subcommands(name, base)
        self.proc = proc

        return
Ejemplo n.º 12
0
class DEvalCommand(DebuggerCommand):
    """**deval**
        **deval?**

    Run a the current deparsed expression in the context of the current
    frame. Normally we are stopped before an expression so the thing that
    corresponds to the `eval` command is running the parent
    construct. `deval?` will run just the command associated with the next
    piece of code to be run.

    Examples:
    ---------

        deval   # Run *parent* of current deparsed code
        deval?  # Run current deparsed code

    See also:
    ---------

    `eval`

    """

    aliases = ("deval?",)
    short_help = "Print value of deparsed expression"

    DebuggerCommand.setup(locals(), category="data", need_stack=True, max_args=0)

    def run(self, args):
        co = self.proc.curframe.f_code
        name = co.co_name
        last_i = self.proc.curframe.f_lasti
        if last_i == -1:
            last_i = 0

        sys_version = version_info[0] + (version_info[1] / 10.0)
        try:
            deparsed = deparse_code(sys_version, co, is_pypy=IS_PYPY)
            nodeInfo = deparsed_find((name, last_i), deparsed, co)
            if not nodeInfo:
                self.errmsg("Can't find exact offset %d" % last_i)
                return
        except:
            self.errmsg("error in deparsing code")
            return
        if "?" == args[0][-1]:
            extractInfo = deparsed.extract_node_info(nodeInfo.node)
        else:
            extractInfo, _ = deparsed.extract_parent_info(nodeInfo.node)
        text = extractInfo.selectedText
        text = text.strip()
        self.msg("Evaluating: %s" % text)
        try:
            self.proc.exec_line(text)
        except:
            pass
Ejemplo n.º 13
0
class ContinueCommand(DebuggerCommand):
    """**continue**

Leave the debugger read-eval print loop and continue
execution. Subsequent entry to the debugger however may occur via
breakpoints or explicit calls, or exceptions.

Examples:
---------

    continue          # Continue execution
    continue 5        # Continue with a one-time breakpoint at line 5
    continue basename # Go to os.path.basename if we have basename imported
    continue /usr/lib/python3.8/posixpath.py:110 # Possibly the same as
                                                 # the above using file
                                                 # and line number

See also:
---------

`step` `jump`, `next`, `finish` and `help syntax location`
"""

    aliases = ("c", "continue!")
    execution_set = ["Running"]
    short_help = "Continue execution of debugged program"

    DebuggerCommand.setup(locals(),
                          category="running",
                          max_args=1,
                          need_stack=True)

    def run(self, args):
        proc = self.proc
        if len(args) > 1:
            # FIXME: DRY this code. Better is to hook into tbreak.
            func, filename, lineno, condition = parse_break_cmd(proc, args)

            if not set_break(self, func, filename, lineno, condition, True,
                             args):
                return False
        elif args[0][-1] == "!":
            proc.vm.frame.event_flags = proc.vm.event_flags = 0  # ignore all events
        else:
            # Until we hook in breakpoints into the debugger proper, we'll
            # treat continue like step in the VM interpreter but not
            # from our filtering process
            proc.vm.frame.event_flags = PyVMEVENT_ALL
            proc.core.event_flags = (PyVMEVENT_LINE | PyVMEVENT_INSTRUCTION
                                     | PyVMEVENT_CALL | PyVMEVENT_FATAL)

        self.core.step_ignore = -1
        self.proc.continue_running = True  # Break out of command read loop
        self.return_status = "continue"  # Tell interpreter to continue running

    pass
Ejemplo n.º 14
0
class EditCommand(DebuggerCommand):
    """**edit** *location*

    Edit specified file or module.
    With no argument, edits file containing most recent line listed.

    See also:
    ---------

    `list`"""

    aliases = ("ed",)
    short_help = "Edit specified file or module"

    DebuggerCommand.setup(
        locals(),
        category="files",
        max_args=1,
    )

    def run(self, args):
        curframe = self.proc.curframe
        if len(args) == 1:
            if curframe is None:
                self.errmsg(
                    "edit: no stack to pick up position from. "
                    "Use edit FILE:LINE form."
                )
                return
            filename = curframe.f_code.co_filename
            lineno = curframe.f_lineno
        elif len(args) > 1:
            location = parse_location(self.proc, args)
            if not location:
                return
            if not location.path:
                return
            filename = location.path
            if not location.line_number:
                return
            lineno = location.line_number
        editor = "ex"
        if "EDITOR" in os.environ:
            editor = os.environ["EDITOR"]
            pass
        if os.path.exists(filename):
            os.system("%s +%d %s" % (editor, lineno, filename))
        else:
            self.errmsg("edit: file %s doesn't exist" % filename)
            pass
        return

    pass
Ejemplo n.º 15
0
class SourceCommand(DebuggerCommand):
    """**source** [**-v**][**-Y**|**-N**][**-c**] *file*

    Read debugger commands from a file named *file*.  Optional *-v* switch
    (before the filename) causes each command in *file* to be echoed as it
    is executed.  Option *-Y* sets the default value in any confirmation
    command to be "yes" and *-N* sets the default value to "no".

    Note that the command startup file `.trepan3krc` is read automatically
    via a *source* command the debugger is started.

    An error in any command terminates execution of the command file
    unless option `-c` is given."""

    short_help = "Read and run debugger commands from a file"

    DebuggerCommand.setup(locals(), category="support", max_args=1)

    def complete(self, prefix):
        # files = Readline::FILENAME_COMPLETION_PROC.call(prefix) || []
        opts = ["-v", "-Y", "-N", "-c"]  # + files
        return complete_token(opts, prefix)

    def run(self, args):
        parms = args[1:-1]
        opts = {}
        for arg in parms:
            if arg == "-v":
                opts["verbose"] = True
            elif arg == "-Y":
                opts["confirm_val"] = True
            elif arg == "-N":
                opts["confirm_val"] = False
            elif arg == "-c":
                opts["abort_on_error"] = False
            pass
        filename = args[-1]

        expanded_file = osp.expanduser(filename)
        if not readable(expanded_file):
            self.errmsg("Debugger command file '%s' is not a readable file" %
                        filename)
            return False

        # Push a new interface.
        script_intf = ScriptInterface(expanded_file,
                                      opts=opts,
                                      out=self.debugger.intf[-1].output)
        self.debugger.intf.append(script_intf)
        return False
Ejemplo n.º 16
0
class TempBreakCommand(DebuggerCommand):
    """**tbreak** [*location*] [**if** *condition*]

    Sets a temporary breakpoint, i.e. one that is removed the after
    the first time it is encountered.

    See the help for location for what can be specified there.

    Without arguments or an empty *location*, the temporary breakpoint is
    set at the current stopped location.

    If the word `if` is given after *location*, subsequent arguments given
    a boolean condition which must evaluate to True before the breakpoint
    is honored.

    Examples:
    ---------

       tbreak                # Break where we are current stopped at
       tbreak if i < j       # Break at current line if i < j
       tbreak 10             # Break on line 10 of the file we are
                             # currently stopped at
       tbreak os.path.join() # Break in function os.path.join
       tbreak x[i].fn() if x # break in function specified by x[i].fn
                             # if x is set
       tbreak os.path:45     # Break on line 45 file holding module os.path
       tbreak myfile.py:45   # Break on line 45 of myfile.py
       break '''c:\\foo.bat''':1"  # One way to specify a Windows file name,
       break '''/My Docs/foo.py''':1"  # One way to specify path with blanks in it

    See also:
    ---------

    `break`, `condition` and `help syntax location`."""

    aliases = ("tb", "tbreak!", "tb!")
    min_args = 0
    short_help = "Set temporary breakpoint at specified line or function"

    DebuggerCommand.setup(locals(), category="breakpoints", need_stack=True)

    complete = complete_break_linenumber

    def run(self, args):
        func, filename, lineno, condition, offset = parse_break_cmd(
            self.proc, args)
        if not (func == None and filename == None):
            set_break(self, func, filename, lineno, condition, True, args)
        return
Ejemplo n.º 17
0
class FinishCommand(DebuggerCommand):
    """**finish** [*level*]

    Continue execution until leaving the current function. When *level* is
    specified, that many frame levels need to be popped. Note that *yield*
    and exceptions raised my reduce the number of stack frames. Also, if a
    thread is switched, we stop ignoring levels.

    See the `break` command if you want to stop at a particular point in a

    See also:
    ---------

    `continue`, `step`, `next`."""

    # FIXME: add finish [levels|fn]
    # If fn is given, that's a short-hand way of looking up how many levels
    # until that frame. However the same provisions regarding stopping,
    # exceptions, 'yield'ing and so on still apply.

    aliases = ("fin", )
    execution_set = ["Running"]
    max_args = 1
    short_help = "Execute until selected stack frame returns"
    DebuggerCommand.setup(locals(),
                          category="running",
                          max_args=1,
                          need_stack=True)

    def run(self, args):
        if self.proc.stack is None:
            return False
        if len(args) <= 1:
            levels = 1
        else:
            levels = self.proc.get_int(args[1], default=1, cmdname="finish")
            if levels is None:
                return False
            pass

        # print "+++ %d" % levels
        self.core.step_events = ["return"]
        self.core.stop_on_finish = True
        self.core.stop_level = count_frames(self.proc.frame) - levels
        self.core.last_frame = self.proc.frame
        self.proc.continue_running = True  # Break out of command read loop
        return True

    pass
Ejemplo n.º 18
0
class ContinueCommand(DebuggerCommand):
    """**continue** [*location*]

    Leave the debugger read-eval print loop and continue
    execution. Subsequent entry to the debugger however may occur via
    breakpoints or explicit calls, or exceptions.

    If *location* is given, a temporary breakpoint is set at that
    position before continuing.

    Examples:
    ---------

        continue          # Continue execution
        continue 5        # Continue with a one-time breakpoint at line 5
        continue basename # Go to os.path.basename if we have basename imported
        continue /usr/lib/python3.8/posixpath.py:110 # Possibly the same as
                                                     # the above using file
                                                     # and line number

    See also:
    ---------

    `step` `jump`, `next`, `finish` and `help syntax location`"""

    aliases = ("c", )
    execution_set = ["Running"]
    short_help = "Continue execution of debugged program"
    DebuggerCommand.setup(locals(),
                          category="running",
                          max_args=1,
                          need_stack=True)

    def run(self, args):
        if len(args) > 1:
            # FIXME: DRY this code. Better is to hook into tbreak.
            func, filename, lineno, condition, offset = parse_break_cmd(
                self.proc, args)
            if not set_break(self, func, filename, lineno, condition, True,
                             args):
                return False
        self.core.step_events = None  # All events
        self.core.step_ignore = -1
        self.proc.continue_running = True  # Break out of command read loop
        return True

    pass
Ejemplo n.º 19
0
class DeleteCommand(DebuggerCommand):
    """**delete** [*bpnumber* [*bpnumber*...]]

    Delete some breakpoints.

    Arguments are breakpoint numbers with spaces in between.  To delete
    all breakpoints, give no argument.  Without
    arguments, clear all breaks (but first ask for confirmation).

    See also:
    ---------
    `clear`"""

    aliases = ("delete!", )
    short_help = "Delete some breakpoints or auto-display expressions"

    complete = complete_bpnumber

    DebuggerCommand.setup(locals(), category="breakpoints")

    def run(self, args):
        if len(args) <= 1:
            if "!" != args[0][-1]:
                confirmed = self.confirm("Delete all breakpoints", False)
            else:
                confirmed = True

            if confirmed:
                self.msg(self.core.bpmgr.delete_all_breakpoints())
            return

        for arg in args[1:]:
            i = self.proc.get_int(arg,
                                  min_value=1,
                                  default=None,
                                  cmdname="delete")
            if i is None:
                continue

            success, msg = self.core.bpmgr.delete_breakpoint_by_number(i)
            if not success:
                self.errmsg(msg)
            else:
                self.msg("Deleted breakpoint %d" % i)
                pass
            pass
        return
Ejemplo n.º 20
0
class HandleCommand(DebuggerCommand):
    """**handle** [*signal-name* [*action1* *action2* ...]]

Specify how to handle a signal *signal-name*. *signal-name* can be a
signal name like `SIGINT` or a signal number like 2. The absolute
value is used for numbers so -9 is the same as 9 (`SIGKILL`). When
signal names are used, you can drop off the leading "SIG" if you want. Also
letter case is not important either.

Arguments are signals and actions to apply to those signals.
recognized actions include `stop`, `nostop`, `print`, `noprint`,
`pass`, `nopass`, `ignore`, or `noignore`.

`stop` means reenter debugger if this signal happens (implies `print` and
`nopass`).

`Print` means print a message if this signal happens.

`Pass` means let program see this signal; otherwise the program see it.

`Ignore` is a synonym for `nopass`; `noignore` is a synonym for `pass`.

Without any action names the current settings are shown.

**Examples:**

  handle INT         # Show current settings of SIGINT
  handle SIGINT      # same as above
  handle int         # same as above
  handle 2           # Probably the same as above
  handle -2          # the same as above
  handle INT nostop  # Don't stop in the debugger on SIGINT
"""

    short_help = "Specify how to handle a signal"

    DebuggerCommand.setup(locals(), category="running", min_args=1)

    def run(self, args):
        if self.debugger.sigmgr.action(" ".join(args[1:])) and len(args) > 2:
            # Show results of recent change
            self.debugger.sigmgr.info_signal([args[1]])
            pass
        return

    pass
Ejemplo n.º 21
0
class NextCommand(DebuggerCommand):
    """**next**[**+**|**-**] [*count*]

    Execute the current simple statement stopping at the next event but
    ignoring steps into function calls at this level,

    With an integer argument, perform `next` that many times. However if
    an exception occurs at this level, or we *return*, *yield* or the
    thread changes, we stop regardless of count.

    A suffix of `+` on the command or an alias to the command forces to
    move to another line, while a suffix of `-` does the opposite and
    disables the requiring a move to a new line. If no suffix is given,
    the debugger setting 'different-line' determines this behavior.

    See also:
    ---------

    `step`, `skip`, `jump` (there's no `hop` yet), `continue`, and
    `finish` for other ways to progress execution."""

    aliases = ("next+", "next-", "n", "n-", "n+")
    execution_set = ["Running"]
    short_help = "Step over"

    DebuggerCommand.setup(locals(), category="running", need_stack=True, max_args=1)

    def run(self, args):
        if len(args) <= 1:
            step_ignore = 0
        else:
            step_ignore = self.proc.get_int(args[1], default=1, cmdname="next")
            if step_ignore is None:
                return False
            # 0 means stop now or step 1, so we subtract 1.
            step_ignore -= 1
            pass
        self.core.different_line = want_different_line(
            args[0], self.debugger.settings["different"]
        )
        self.core.set_next(self.proc.frame, step_ignore)
        self.proc.continue_running = True  # Break out of command read loop
        return True

    pass
Ejemplo n.º 22
0
class PCommand(DebuggerCommand):
    """**print** *expression*

    Print the value of the expression. Variables accessible are those of the
    environment of the selected stack frame, plus globals.

    The expression may be preceded with */fmt* where *fmt* is one of the
    format letters 'c', 'x', 'o', 'f', or 's' for chr, hex, oct,
    float or str respectively.

    If the length output string large, the first part of the value is
    shown and `...` indicates it has been truncated.

    See also:
    ---------

     `pp` and `examine` for commands which do more in the way of formatting."""

    aliases = ("print", "pr")
    short_help = "Print value of expression EXP"

    complete = complete_identifier

    DebuggerCommand.setup(locals(),
                          category="data",
                          need_stack=True,
                          min_args=1)

    def run(self, args):
        if len(args) > 2 and "/" == args[1][0]:
            fmt = args[1]
            del args[1]
        else:
            fmt = None
            pass
        arg = " ".join(args[1:])
        try:
            val = self.proc.eval(arg)
            if fmt:
                val = printf(val, fmt)
                pass
            self.msg(self.proc._saferepr(val))
        except:
            pass
Ejemplo n.º 23
0
class UndisplayCommand(DebuggerCommand):
    """**undisplay** *display-number*...

Cancel some expressions to be displayed when program stops.
Arguments are the code numbers of the expressions to stop displaying.

No argument cancels all automatic-display expressions and is
the same as `delete display`.

See also:
---------

`info display` to see current list of code numbers.
"""

    aliases = ('und', )
    short_help = ('Cancel some expressions to be displayed '
                  'when program stops')

    DebuggerCommand.setup(locals(), category="data", min_args=1)

    def complete(self, prefix):
        completions = [str(disp.number) for disp in self.proc.display_mgr.list]
        return Mcomplete.complete_token(completions, prefix)

    def run(self, args):

        if len(args) == 1:
            self.proc.display_mgr.clear()
            return
        for i in args[1:]:
            i = self.proc.get_an_int(i, '%r must be a display number' % i)
            if i is not None:
                if not self.proc.display_mgr.delete_index(i):
                    self.errmsg("No display number %d." % i)
                    return
                pass
            pass
        return False

    pass
Ejemplo n.º 24
0
class RestartCommand(DebuggerCommand):
    """**restart**

    Restart debugger and program via an *exec()* call. All state is lost,
    and new copy of the debugger is used.

    See also:
    ---------

    `run` for another way to restart the debugged program.

    See `quit`, `exit` or `kill` for termination commands."""

    short_help = "(Hard) restart of program via execv()"

    DebuggerCommand.setup(locals(), category="support", max_args=0)

    def run(self, args):
        sys_argv = self.debugger.restart_argv()
        if sys_argv and len(sys_argv) > 0:
            confirmed = self.confirm("Restart (execv)", False)
            if confirmed:
                self.msg(
                    wrapped_lines("Re exec'ing:", repr(sys_argv),
                                  self.settings["width"]))
                # Run atexit finalize routines. This seems to be Kosher:
                # http://mail.python.org/pipermail/python-dev/2009-February/085791.html # NOQA
                try:
                    atexit._run_exitfuncs()
                except:
                    pass
                os.execvp(sys_argv[0], sys_argv)
                pass
            pass
        else:
            self.errmsg("No executable file and command options recorded.")
            pass
        return

    pass
Ejemplo n.º 25
0
class ClearCommand(DebuggerCommand):
    """**clear** [*linenumber*]

    Clear some breakpoints by line number.

    See also:
    ---------
    `delete`
    """

    short_help = "Delete some breakpoints on a line"

    DebuggerCommand.setup(locals(), category="breakpoints", need_stack=True)

    complete = complete_bpnumber

    def run(self, args):
        proc = self.proc
        curframe = proc.curframe
        filename = proc.list_filename
        if len(args) <= 1:
            lineno = inspect.getlineno(curframe)
        else:
            lineno = proc.get_an_int(
                args[1],
                "The 'clear' command argument when given should be "
                "a line number. Got %s",
                min_value=1,
            )
            if lineno is None:
                return

        linenos = self.core.bpmgr.delete_breakpoints_by_lineno(filename, lineno)
        if len(linenos) == 0:
            self.errmsg("No breakpoint at line %d" % lineno)
        elif len(linenos) == 1:
            self.msg("Deleted breakpoint %d" % linenos[0])
        elif len(linenos) > 1:
            self.msg("Deleted breakpoints %s" % " ".join([str(i) for i in linenos]))
        return
Ejemplo n.º 26
0
class ConditionCommand(DebuggerCommand):
    """**condition** *bp_number* *condition*

*bp_number* is a breakpoint number. *condition* is an expression which
must evaluate to *True* before the breakpoint is honored.  If *condition*
is absent, any existing condition is removed; i.e., the breakpoint is
made unconditional.

Examples:
---------

   condition 5 x > 10  # Breakpoint 5 now has condition x > 10
   condition 5         # Remove above condition

See also:
---------

`break`, `tbreak`."""

    aliases = ("cond", )
    short_help = "Specify breakpoint number N to break only if COND is True"

    DebuggerCommand.setup(locals(), category="breakpoints", min_args=1)

    complete = complete_bpnumber

    def run(self, args):
        success, msg, bp = self.core.bpmgr.get_breakpoint(int(args[1]))
        if not success:
            self.errmsg(msg)
            return
        if len(args) > 2:
            condition = " ".join(args[2:])
        else:
            condition = None
            self.msg("Breakpoint %d is now unconditional." % bp.number)
            pass
        bp.condition = condition
        return
Ejemplo n.º 27
0
class ExamineCommand(DebuggerCommand):
    """**examine** *expr1* [*expr2* ...]

    Examine value, type and object attributes of an expression.

    In contrast to normal Python expressions, expressions should not have
    blanks which would cause shlex to see them as different tokens.

    Examples:
    ---------

        examine x+1   # ok
        examine x + 1 # not ok

    See also:
    ---------

    `pr`, `pp`, and `whatis`."""

    aliases = ("x", )
    short_help = "Examine value, type, and object attributes " "of an expression"

    DebuggerCommand.setup(
        locals(),
        category="data",
        need_stack=True,
        min_args=1,
    )

    def run(self, args):
        for arg in args[1:]:
            s = print_obj(arg, self.proc.curframe)
            self.msg(s)
            pass
        return

    pass
Ejemplo n.º 28
0
class IPythonCommand(DebuggerCommand):
    """**ipython** [**-d**]

    Run IPython as a command subshell.

    If *-d* is passed, you can access debugger state via local variable *debugger*.

    To issue a debugger command use function *dbgr()*. For example:

      dbgr('info program')

    See also:
    ---------

    `python`, `bpython`"""

    short_help = "Run IPython as a command subshell"

    DebuggerCommand.setup(locals(), category="support", max_args=1)

    def dbgr(self, string):
        """Invoke a debugger command from inside a IPython shell called
        inside the debugger.
        """
        self.proc.cmd_queue.append(string)
        self.proc.process_command()
        return

    def run(self, args):
        # See if python's code module is around

        # Python does it's own history thing.
        # Make sure it doesn't damage ours.
        have_line_edit = self.debugger.intf[-1].input.line_edit
        if have_line_edit:
            try:
                self.proc.write_history_file()
            except IOError:
                pass
            pass

        cfg = Config()
        banner_tmpl = """IPython trepan3k shell%s

Use dbgr(*string*) to issue non-continuing debugger command: *string*"""

        debug = len(args) > 1 and args[1] == "-d"
        if debug:
            banner_tmpl += "\nVariable 'debugger' contains a trepan " "debugger object."
            pass
        try:
            from IPython.terminal.embed import InteractiveShellEmbed
        except ImportError:
            from IPython.frontend.terminal.embed import InteractiveShellEmbed

        # Now create an instance of the embeddable shell. The first
        # argument is a string with options exactly as you would type them
        # if you were starting IPython at the system command line. Any
        # parameters you want to define for configuration can thus be
        # specified here.

        # Add common classes and methods our namespace here so that
        # inside the ipython shell users don't have run imports

        my_locals = {}
        my_globals = None
        if self.proc.curframe:
            my_globals = self.proc.curframe.f_globals
            if self.proc.curframe.f_locals:
                my_locals = self.proc.curframe.f_locals
            pass
        pass

        # Give IPython and the user a way to get access to the debugger.
        if debug:
            my_locals["debugger"] = self.debugger
        my_locals["dbgr"] = self.dbgr
        cfg.TerminalInteractiveShell.confirm_exit = False

        # sys.ps1 = 'trepan3 >>> '
        if len(my_locals):
            banner = banner_tmpl % " with locals"
        else:
            banner = banner_tmpl % ""
            pass

        InteractiveShellEmbed(
            config=cfg,
            banner1=banner,
            user_ns=my_locals,
            module=my_globals,
            exit_msg="IPython exiting to trepan3k...",
        )()

        # restore completion and our history if we can do so.
        if hasattr(self.proc.intf[-1], "complete"):
            try:
                from readline import set_completer, parse_and_bind

                parse_and_bind("tab: complete")
                set_completer(self.proc.intf[-1].complete)
            except ImportError:
                pass
            pass

        if have_line_edit:
            self.proc.read_history_file()
            pass
        return

    pass
Ejemplo n.º 29
0
class WhatisCommand(DebuggerCommand):
    """**whatis** *arg*

Prints the information argument which can be a Python expression.

When possible, we give information about:

* type of argument

* doc string for the argument (if a module, class, or function)

* comments around the definition of the argument (module)

* the module it was defined in

* where the argument was defined

We get this most of this information via the *inspect* module.

See also:
--------

the *inspect* module."""

    aliases = ()
    min_args = 1
    short_help = "Print data type of expression EXP"

    complete = complete_id_and_builtins

    DebuggerCommand.setup(locals(),
                          category="data",
                          min_args=1,
                          need_stack=True)

    def run(self, args):
        proc = self.proc
        arg = proc.cmd_argstr
        try:
            if not proc.curframe:
                # ?? Should we have set up a dummy globals
                # to have persistence?
                value = eval(arg, None, None)
            else:
                value = eval(arg, proc.curframe.f_globals,
                             proc.curframe.f_locals)
        except:
            t, v = sys.exc_info()[:2]
            if type(t) == str:
                exc_type_name = t
            else:
                exc_type_name = t.__name__
            if exc_type_name == "NameError":
                self.errmsg("Name Error: %s" % arg)
            else:
                self.errmsg("%s: %s" % (exc_type_name, proc._saferepr(v)))
            return False

        self.section("What is for %s" % arg)

        get_doc = False
        if inspect.ismethod(value):
            get_doc = True
            self.msg("method %s%s" % (
                value.func_code.co_name,
                inspect.formatargspec(inspect.getargspec(value)),
            ))
        elif inspect.isfunction(value):
            get_doc = True
            self.msg("function %s%s" % (
                value.func_code.co_name,
                inspect.formatargspec(inspect.getargspec(value)),
            ))
        elif (inspect.isabstract(value) or inspect.isbuiltin(value)
              or inspect.isclass(value) or inspect.isgeneratorfunction(value)
              or inspect.ismethoddescriptor(value)):
            get_doc = True

        self.msg(type(value))
        doc = inspect.getdoc(value)
        if get_doc and doc:
            self.msg("  doc:\n%s" % doc)
        comments = inspect.getcomments(value)
        if comments:
            self.msg("  comments:\n%s" % comments)
        try:
            m = inspect.getmodule(value)
            if m:
                self.msg("  module:\t%s" % m)
        except:
            try:
                f = inspect.getfile(value)
                self.msg("  file: %s" % f)
            except:
                pass
            pass
        return False

    pass
Ejemplo n.º 30
0
class DisassembleCommand(DebuggerCommand):
    """**disassemble** [*thing*]

**disassemble** [*address-range*]

Disassembles bytecode. See `help syntax range` for what can go in a list range.

Without arguments, print lines starting from where the last list left off
since the last entry to the debugger. We start off at the location indicated
by the current stack.

in addition you can also use:

  - a '.' for the location of the current frame

  - a '-' for the lines before the last list

  - a '+' for the lines after the last list

With a class, method, function, pyc-file, code or string argument
disassemble that.

Examples:
--------
::

   disassemble    # Possibly current frame
   disassemble +                    # Same as above
   disassemble os.path              # Disassemble all of os.path # xxx
   disassemble os.path.normcase()   # Disaasemble just method os.path.normcase
   disassemble 3                    # Disassemble starting from line 3
   disassemble 3, 10                # Disassemble lines 3 to 10
   disassemble *0, *10              # Disassemble offset 0..10 (10 not included)
   disassemble myprog.pyc           # Disassemble file myprog.pyc

See also:
---------

`help syntax arange`, `deparse`, `list`, `info pc`.
"""

    aliases = ("disasm", )  # Note: we will have disable
    short_help = "Disassemble Python bytecode"

    DebuggerCommand.setup(locals(), category="data", max_args=2)

    def run(self, args):
        proc = self.proc

        # FIXME: add a setting for assembler list size
        listsize = 4

        opts = {
            "highlight": self.settings["highlight"],
            "start_line": 1,
            "end_line": None,
            "start_offset": None,
            "end_offset": None,
            "relative_pos": False,
            "asm_format": self.settings["asmfmt"],
        }

        curframe = proc.curframe
        if curframe:
            line_no = inspect.getlineno(curframe)
            opts["start_line"] = line_no - 1
            opts["end_line"] = line_no + 1

        do_parse = True
        if len(args) == 2:
            if args[1].endswith("()"):
                eval_args = args[1][:-2]
            else:
                eval_args = args[1]
            try:
                obj = self.proc.eval(eval_args, show_error=False)
            except:
                obj = None
            else:
                if (inspect.ismethod(obj) or inspect.isfunction(obj)
                        or inspect.isgeneratorfunction(obj)
                        or inspect.isgenerator(obj) or inspect.isframe(obj)
                        or inspect.iscode(obj)):
                    opts["start_offset"] = 0
                    last_is_offset = is_offset = True
                    start = 0
                    opts["start_line"] = 0
                    opts["end_line"] = last = None
                    do_parse = False
                    bytecode_file = None

        if do_parse:
            (
                bytecode_file,
                start,
                is_offset,
                last,
                last_is_offset,
                obj,
            ) = parse_addr_list_cmd(proc, args, listsize)
            if bytecode_file is None:
                return

        if is_offset:
            opts["start_offset"] = start
        else:
            opts["start_line"] = start
        if last_is_offset:
            opts["end_offset"] = last
        else:
            opts["end_line"] = last

        if not obj and (bytecode_file and (not bytecode_file.endswith(".pyo")
                                           or bytecode_file.endswith("pyc"))):
            # bytecode_file may be a source file. Try to tun it into a bytecode file for diassembly.
            bytecode_file = cache_from_source(bytecode_file)
            if bytecode_file and Mfile.readable(bytecode_file):
                self.msg("Reading %s ..." % bytecode_file)
                (
                    version,
                    timestamp,
                    magic_int,
                    obj,
                    is_pypy,
                    source_size,
                    sip_hash,
                ) = load_module(bytecode_file)
            elif not curframe:
                self.errmsg("No frame selected.")
                return
            else:
                try:
                    obj = self.proc.eval(args[1])
                    opts["start_line"] = -1
                except:
                    self.errmsg(("Object '%s' is not something we can" +
                                 " disassemble.") % args[1])
                    return

        # We now have all  information. Do the listing.
        (obj, proc.list_offset) = dis(self.msg, self.msg_nocr, self.section,
                                      self.errmsg, obj, **opts)
        return False