Top

miasm2.analysis.debugging module

import cmd
from miasm2.core.utils import hexdump
from miasm2.core.interval import interval
import miasm2.jitter.csts as csts
from miasm2.jitter.jitload import ExceptionHandle


class DebugBreakpoint:

    "Debug Breakpoint parent class"
    pass


class DebugBreakpointSoft(DebugBreakpoint):

    "Stand for software breakpoint"

    def __init__(self, addr):
        self.addr = addr

    def __str__(self):
        return "Soft BP @0x%08x" % self.addr


class DebugBreakpointTerminate(DebugBreakpoint):
    "Stand for an execution termination"

    def __init__(self, status):
        self.status = status

    def __str__(self):
        return "Terminate with %s" % self.status


class DebugBreakpointMemory(DebugBreakpoint):

    "Stand for memory breakpoint"

    type2str = {csts.BREAKPOINT_READ: "R",
                csts.BREAKPOINT_WRITE: "W"}

    def __init__(self, addr, size, access_type):
        self.addr = addr
        self.access_type = access_type
        self.size = size

    def __str__(self):
        bp_type = ""
        for k, v in self.type2str.items():
            if k & self.access_type != 0:
                bp_type += v
        return "Memory BP @0x%08x, Size 0x%08x, Type %s" % (self.addr,
                                                            self.size,
                                                            bp_type)

    @classmethod
    def get_access_type(cls, read=False, write=False):
        value = 0
        for k, v in cls.type2str.items():
            if v == "R" and read is True:
                value += k
            if v == "W" and write is True:
                value += k
        return value


class Debugguer(object):

    "Debugguer linked with a Jitter instance"

    def __init__(self, myjit):
        "myjit : jitter instance"
        self.myjit = myjit
        self.bp_list = []     # DebugBreakpointSoft list
        self.hw_bp_list = []  # DebugBreakpointHard list
        self.mem_watched = []  # Memory areas watched

    def init_run(self, addr):
        self.myjit.init_run(addr)

    def add_breakpoint(self, addr):
        "Add bp @addr"
        bp = DebugBreakpointSoft(addr)
        func = lambda x: bp
        bp.func = func
        self.bp_list.append(bp)
        self.myjit.add_breakpoint(addr, func)

    def init_memory_breakpoint(self):
        "Set exception handler on EXCEPT_BREAKPOINT_MEMORY"
        raise NotImplementedError("Not implemented")

    def add_memory_breakpoint(self, addr, size, read=False, write=False):
        "add mem bp @[addr, addr + size], on read/write/both"
        access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                            write=write)
        dbm = DebugBreakpointMemory(addr, size, access_type)
        self.hw_bp_list.append(dbm)
        self.myjit.vm.add_memory_breakpoint(addr, size, access_type)

    def remove_breakpoint(self, dbs):
        "remove the DebugBreakpointSoft instance"
        self.bp_list.remove(dbs)
        self.myjit.remove_breakpoints_by_callback(dbs.func)

    def remove_breakpoint_by_addr(self, addr):
        "remove breakpoints @ addr"
        for bp in self.get_breakpoint_by_addr(addr):
            self.remove_breakpoint(bp)

    def remove_memory_breakpoint(self, dbm):
        "remove the DebugBreakpointMemory instance"
        self.hw_bp_list.remove(dbm)
        self.myjit.vm.remove_memory_breakpoint(dbm.addr, dbm.access_type)

    def remove_memory_breakpoint_by_addr_access(self, addr, read=False,
                                                write=False):
        "remove breakpoints @ addr"
        access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                            write=write)
        for bp in self.hw_bp_list:
            if bp.addr == addr and bp.access_type == access_type:
                self.remove_memory_breakpoint(bp)

    def get_breakpoint_by_addr(self, addr):
        ret = []
        for dbgsoft in self.bp_list:
            if dbgsoft.addr == addr:
                ret.append(dbgsoft)
        return ret

    def get_breakpoints(self):
        return self.bp_list

    def active_trace(self, mn=None, regs=None, newbloc=None):
        if mn is not None:
            self.myjit.jit.log_mn = mn
        if regs is not None:
            self.myjit.jit.log_regs = regs
        if newbloc is not None:
            self.myjit.jit.log_newbloc = newbloc

    def handle_exception(self, res):
        if not res:
            # A breakpoint has stopped the execution
            return DebugBreakpointTerminate(res)

        if isinstance(res, DebugBreakpointSoft):
            print "Breakpoint reached @0x%08x" % res.addr
        elif isinstance(res, ExceptionHandle):
            if res == ExceptionHandle.memoryBreakpoint():
                print "Memory breakpoint reached!"

                # Remove flag
                except_flag = self.myjit.vm.get_exception()
                self.myjit.vm.set_exception(except_flag ^ res.except_flag)

            else:
                raise NotImplementedError("Unknown Except")
        else:
            raise NotImplementedError("type res")

        # Repropagate res
        return res

    def step(self):
        "Step in jit"

        self.myjit.jit.set_options(jit_maxline=1)
        # Reset all jitted blocks
        self.myjit.jit.clear_jitted_blocks()

        res = self.myjit.continue_run(step=True)
        self.handle_exception(res)

        self.myjit.jit.set_options(jit_maxline=50)
        self.on_step()

        return res

    def run(self):
        status = self.myjit.continue_run()
        return self.handle_exception(status)

    def get_mem(self, addr, size=0xF):
        "hexdump @addr, size"

        hexdump(self.myjit.vm.get_mem(addr, size))

    def get_mem_raw(self, addr, size=0xF):
        "hexdump @addr, size"
        return self.myjit.vm.get_mem(addr, size)

    def watch_mem(self, addr, size=0xF):
        self.mem_watched.append((addr, size))

    def on_step(self):
        for addr, size in self.mem_watched:
            print "@0x%08x:" % addr
            self.get_mem(addr, size)

    def get_reg_value(self, reg_name):
        return getattr(self.myjit.cpu, reg_name)

    def set_reg_value(self, reg_name, value):

        # Handle PC case
        if reg_name == self.myjit.ir_arch.pc.name:
            self.init_run(value)

        setattr(self.myjit.cpu, reg_name, value)

    def get_gpreg_all(self):
        "Return general purposes registers"
        return self.myjit.cpu.get_gpreg()


class DebugCmd(cmd.Cmd, object):

    "CommandLineInterpreter for Debugguer instance"

    color_g = '\033[92m'
    color_e = '\033[0m'
    color_b = '\033[94m'
    color_r = '\033[91m'

    intro = color_g + "=== Miasm2 Debugging shell ===\nIf you need help, "
    intro += "type 'help' or '?'" + color_e
    prompt = color_b + "$> " + color_e

    def __init__(self, dbg):
        "dbg : Debugguer"
        self.dbg = dbg
        super(DebugCmd, self).__init__()

    # Debug methods

    def print_breakpoints(self):
        bp_list = self.dbg.bp_list
        if len(bp_list) == 0:
            print "No breakpoints."
        else:
            for i, b in enumerate(bp_list):
                print "%d\t0x%08x" % (i, b.addr)

    def print_watchmems(self):
        watch_list = self.dbg.mem_watched
        if len(watch_list) == 0:
            print "No memory watchpoints."
        else:
            print "Num\tAddress  \tSize"
            for i, w in enumerate(watch_list):
                addr, size = w
                print "%d\t0x%08x\t0x%08x" % (i, addr, size)

    def print_registers(self):
        regs = self.dbg.get_gpreg_all()

        # Display settings
        title1 = "Registers"
        title2 = "Values"
        max_name_len = max(map(len, regs.keys() + [title1]))

        # Print value table
        s = "%s%s    |    %s" % (
            title1, " " * (max_name_len - len(title1)), title2)
        print s
        print "-" * len(s)
        for name, value in sorted(regs.items(), key=lambda x: x[0]):
            print "%s%s    |    %s" % (name,
                                       " " * (max_name_len - len(name)),
                                       hex(value).replace("L", ""))

    def add_breakpoints(self, bp_addr):
        for addr in bp_addr:
            addr = int(addr, 0)

            good = True
            for i, dbg_obj in enumerate(self.dbg.bp_list):
                if dbg_obj.addr == addr:
                    good = False
                    break
            if good is False:
                print "Breakpoint 0x%08x already set (%d)" % (addr, i)
            else:
                l = len(self.dbg.bp_list)
                self.dbg.add_breakpoint(addr)
                print "Breakpoint 0x%08x successfully added ! (%d)" % (addr, l)

    display_mode = {"mn": None,
                    "regs": None,
                    "newbloc": None}

    def update_display_mode(self):
        self.display_mode = {"mn": self.dbg.myjit.jit.log_mn,
                             "regs": self.dbg.myjit.jit.log_regs,
                             "newbloc": self.dbg.myjit.jit.log_newbloc}

    # Command line methods
    def print_warning(self, s):
        print self.color_r + s + self.color_e

    def onecmd(self, line):
        cmd_translate = {"h": "help",
                         "q": "exit",
                         "e": "exit",
                         "!": "exec",
                         "r": "run",
                         "i": "info",
                         "b": "breakpoint",
                         "s": "step",
                         "d": "dump"}

        if len(line) >= 2 and \
           line[1] == " " and \
           line[:1] in cmd_translate:
            line = cmd_translate[line[:1]] + line[1:]

        if len(line) == 1 and line in cmd_translate:
            line = cmd_translate[line]

        r = super(DebugCmd, self).onecmd(line)
        return r

    def can_exit(self):
        return True

    def do_display(self, arg):
        if arg == "":
            self.help_display()
            return

        args = arg.split(" ")
        if args[-1].lower() not in ["on", "off"]:
            self.print_warning("/!\ %s not in 'on' / 'off'" % args[-1])
            return
        mode = args[-1].lower() == "on"
        d = {}
        for a in args[:-1]:
            d[a] = mode
        self.dbg.active_trace(**d)
        self.update_display_mode()

    def help_display(self):
        print "Enable/Disable tracing."
        print "Usage: display <mode1> <mode2> ... on|off"
        print "Available modes are:"
        for k in self.display_mode:
            print "\t%s" % k
        print "Use 'info display' to get current values"

    def do_watchmem(self, arg):
        if arg == "":
            self.help_watchmem()
            return

        args = arg.split(" ")
        if len(args) >= 2:
            size = int(args[1], 0)
        else:
            size = 0xF

        addr = int(args[0], 0)

        self.dbg.watch_mem(addr, size)

    def help_watchmem(self):
        print "Add a memory watcher."
        print "Usage: watchmem <addr> [size]"
        print "Use 'info watchmem' to get current memory watchers"

    def do_info(self, arg):
        av_info = ["registers",
                   "display",
                   "breakpoints",
                   "watchmem"]

        if arg == "":
            print "'info' must be followed by the name of an info command."
            print "List of info subcommands:"
            for k in av_info:
                print "\t%s" % k

        if arg.startswith("b"):
            # Breakpoint
            self.print_breakpoints()

        if arg.startswith("d"):
            # Display
            self.update_display_mode()
            for k, v in self.display_mode.items():
                print "%s\t\t%s" % (k, v)

        if arg.startswith("w"):
            # Watchmem
            self.print_watchmems()

        if arg.startswith("r"):
            # Registers
            self.print_registers()

    def help_info(self):
        print "Generic command for showing things about the program being"
        print "debugged. Use 'info' without arguments to get the list of"
        print "available subcommands."

    def do_breakpoint(self, arg):
        if arg == "":
            self.help_breakpoint()
        else:
            addrs = arg.split(" ")
            self.add_breakpoints(addrs)

    def help_breakpoint(self):
        print "Add breakpoints to argument addresses."
        print "Example:"
        print "\tbreakpoint 0x11223344"
        print "\tbreakpoint 1122 0xabcd"

    def do_step(self, arg):
        if arg == "":
            nb = 1
        else:
            nb = int(arg)
        for _ in xrange(nb):
            self.dbg.step()

    def help_step(self):
        print "Step program until it reaches a different source line."
        print "Argument N means do this N times (or till program stops"
        print "for another reason)."

    def do_dump(self, arg):
        if arg == "":
            self.help_dump()
        else:
            args = arg.split(" ")
            if len(args) >= 2:
                size = int(args[1], 0)
            else:
                size = 0xF
            addr = int(args[0], 0)

            self.dbg.get_mem(addr, size)

    def help_dump(self):
        print "Dump <addr> [size]. Dump size bytes at addr."

    def do_run(self, _):
        self.dbg.run()

    def help_run(self):
        print "Launch or continue the current program"

    def do_exit(self, _):
        return True

    def do_exec(self, line):
        try:
            print eval(line)
        except Exception, error:
            print "*** Error: %s" % error

    def help_exec(self):
        print "Exec a python command."
        print "You can also use '!' shortcut."

    def help_exit(self):
        print "Exit the interpreter."
        print "You can also use the Ctrl-D shortcut."

    def help_help(self):
        print "Print help"

    def postloop(self):
        print '\nGoodbye !'
        super(DebugCmd, self).postloop()

    do_EOF = do_exit
    help_EOF = help_exit

Classes

class DebugBreakpoint

Debug Breakpoint parent class

class DebugBreakpoint:

    "Debug Breakpoint parent class"
    pass

Ancestors (in MRO)

class DebugBreakpointMemory

Stand for memory breakpoint

class DebugBreakpointMemory(DebugBreakpoint):

    "Stand for memory breakpoint"

    type2str = {csts.BREAKPOINT_READ: "R",
                csts.BREAKPOINT_WRITE: "W"}

    def __init__(self, addr, size, access_type):
        self.addr = addr
        self.access_type = access_type
        self.size = size

    def __str__(self):
        bp_type = ""
        for k, v in self.type2str.items():
            if k & self.access_type != 0:
                bp_type += v
        return "Memory BP @0x%08x, Size 0x%08x, Type %s" % (self.addr,
                                                            self.size,
                                                            bp_type)

    @classmethod
    def get_access_type(cls, read=False, write=False):
        value = 0
        for k, v in cls.type2str.items():
            if v == "R" and read is True:
                value += k
            if v == "W" and write is True:
                value += k
        return value

Ancestors (in MRO)

Class variables

var type2str

Instance variables

var access_type

var addr

var size

Methods

def __init__(

self, addr, size, access_type)

def __init__(self, addr, size, access_type):
    self.addr = addr
    self.access_type = access_type
    self.size = size

def get_access_type(

cls, read=False, write=False)

@classmethod
def get_access_type(cls, read=False, write=False):
    value = 0
    for k, v in cls.type2str.items():
        if v == "R" and read is True:
            value += k
        if v == "W" and write is True:
            value += k
    return value

class DebugBreakpointSoft

Stand for software breakpoint

class DebugBreakpointSoft(DebugBreakpoint):

    "Stand for software breakpoint"

    def __init__(self, addr):
        self.addr = addr

    def __str__(self):
        return "Soft BP @0x%08x" % self.addr

Ancestors (in MRO)

Instance variables

var addr

Methods

def __init__(

self, addr)

def __init__(self, addr):
    self.addr = addr

class DebugBreakpointTerminate

Stand for an execution termination

class DebugBreakpointTerminate(DebugBreakpoint):
    "Stand for an execution termination"

    def __init__(self, status):
        self.status = status

    def __str__(self):
        return "Terminate with %s" % self.status

Ancestors (in MRO)

Instance variables

var status

Methods

def __init__(

self, status)

def __init__(self, status):
    self.status = status

class DebugCmd

CommandLineInterpreter for Debugguer instance

class DebugCmd(cmd.Cmd, object):

    "CommandLineInterpreter for Debugguer instance"

    color_g = '\033[92m'
    color_e = '\033[0m'
    color_b = '\033[94m'
    color_r = '\033[91m'

    intro = color_g + "=== Miasm2 Debugging shell ===\nIf you need help, "
    intro += "type 'help' or '?'" + color_e
    prompt = color_b + "$> " + color_e

    def __init__(self, dbg):
        "dbg : Debugguer"
        self.dbg = dbg
        super(DebugCmd, self).__init__()

    # Debug methods

    def print_breakpoints(self):
        bp_list = self.dbg.bp_list
        if len(bp_list) == 0:
            print "No breakpoints."
        else:
            for i, b in enumerate(bp_list):
                print "%d\t0x%08x" % (i, b.addr)

    def print_watchmems(self):
        watch_list = self.dbg.mem_watched
        if len(watch_list) == 0:
            print "No memory watchpoints."
        else:
            print "Num\tAddress  \tSize"
            for i, w in enumerate(watch_list):
                addr, size = w
                print "%d\t0x%08x\t0x%08x" % (i, addr, size)

    def print_registers(self):
        regs = self.dbg.get_gpreg_all()

        # Display settings
        title1 = "Registers"
        title2 = "Values"
        max_name_len = max(map(len, regs.keys() + [title1]))

        # Print value table
        s = "%s%s    |    %s" % (
            title1, " " * (max_name_len - len(title1)), title2)
        print s
        print "-" * len(s)
        for name, value in sorted(regs.items(), key=lambda x: x[0]):
            print "%s%s    |    %s" % (name,
                                       " " * (max_name_len - len(name)),
                                       hex(value).replace("L", ""))

    def add_breakpoints(self, bp_addr):
        for addr in bp_addr:
            addr = int(addr, 0)

            good = True
            for i, dbg_obj in enumerate(self.dbg.bp_list):
                if dbg_obj.addr == addr:
                    good = False
                    break
            if good is False:
                print "Breakpoint 0x%08x already set (%d)" % (addr, i)
            else:
                l = len(self.dbg.bp_list)
                self.dbg.add_breakpoint(addr)
                print "Breakpoint 0x%08x successfully added ! (%d)" % (addr, l)

    display_mode = {"mn": None,
                    "regs": None,
                    "newbloc": None}

    def update_display_mode(self):
        self.display_mode = {"mn": self.dbg.myjit.jit.log_mn,
                             "regs": self.dbg.myjit.jit.log_regs,
                             "newbloc": self.dbg.myjit.jit.log_newbloc}

    # Command line methods
    def print_warning(self, s):
        print self.color_r + s + self.color_e

    def onecmd(self, line):
        cmd_translate = {"h": "help",
                         "q": "exit",
                         "e": "exit",
                         "!": "exec",
                         "r": "run",
                         "i": "info",
                         "b": "breakpoint",
                         "s": "step",
                         "d": "dump"}

        if len(line) >= 2 and \
           line[1] == " " and \
           line[:1] in cmd_translate:
            line = cmd_translate[line[:1]] + line[1:]

        if len(line) == 1 and line in cmd_translate:
            line = cmd_translate[line]

        r = super(DebugCmd, self).onecmd(line)
        return r

    def can_exit(self):
        return True

    def do_display(self, arg):
        if arg == "":
            self.help_display()
            return

        args = arg.split(" ")
        if args[-1].lower() not in ["on", "off"]:
            self.print_warning("/!\ %s not in 'on' / 'off'" % args[-1])
            return
        mode = args[-1].lower() == "on"
        d = {}
        for a in args[:-1]:
            d[a] = mode
        self.dbg.active_trace(**d)
        self.update_display_mode()

    def help_display(self):
        print "Enable/Disable tracing."
        print "Usage: display <mode1> <mode2> ... on|off"
        print "Available modes are:"
        for k in self.display_mode:
            print "\t%s" % k
        print "Use 'info display' to get current values"

    def do_watchmem(self, arg):
        if arg == "":
            self.help_watchmem()
            return

        args = arg.split(" ")
        if len(args) >= 2:
            size = int(args[1], 0)
        else:
            size = 0xF

        addr = int(args[0], 0)

        self.dbg.watch_mem(addr, size)

    def help_watchmem(self):
        print "Add a memory watcher."
        print "Usage: watchmem <addr> [size]"
        print "Use 'info watchmem' to get current memory watchers"

    def do_info(self, arg):
        av_info = ["registers",
                   "display",
                   "breakpoints",
                   "watchmem"]

        if arg == "":
            print "'info' must be followed by the name of an info command."
            print "List of info subcommands:"
            for k in av_info:
                print "\t%s" % k

        if arg.startswith("b"):
            # Breakpoint
            self.print_breakpoints()

        if arg.startswith("d"):
            # Display
            self.update_display_mode()
            for k, v in self.display_mode.items():
                print "%s\t\t%s" % (k, v)

        if arg.startswith("w"):
            # Watchmem
            self.print_watchmems()

        if arg.startswith("r"):
            # Registers
            self.print_registers()

    def help_info(self):
        print "Generic command for showing things about the program being"
        print "debugged. Use 'info' without arguments to get the list of"
        print "available subcommands."

    def do_breakpoint(self, arg):
        if arg == "":
            self.help_breakpoint()
        else:
            addrs = arg.split(" ")
            self.add_breakpoints(addrs)

    def help_breakpoint(self):
        print "Add breakpoints to argument addresses."
        print "Example:"
        print "\tbreakpoint 0x11223344"
        print "\tbreakpoint 1122 0xabcd"

    def do_step(self, arg):
        if arg == "":
            nb = 1
        else:
            nb = int(arg)
        for _ in xrange(nb):
            self.dbg.step()

    def help_step(self):
        print "Step program until it reaches a different source line."
        print "Argument N means do this N times (or till program stops"
        print "for another reason)."

    def do_dump(self, arg):
        if arg == "":
            self.help_dump()
        else:
            args = arg.split(" ")
            if len(args) >= 2:
                size = int(args[1], 0)
            else:
                size = 0xF
            addr = int(args[0], 0)

            self.dbg.get_mem(addr, size)

    def help_dump(self):
        print "Dump <addr> [size]. Dump size bytes at addr."

    def do_run(self, _):
        self.dbg.run()

    def help_run(self):
        print "Launch or continue the current program"

    def do_exit(self, _):
        return True

    def do_exec(self, line):
        try:
            print eval(line)
        except Exception, error:
            print "*** Error: %s" % error

    def help_exec(self):
        print "Exec a python command."
        print "You can also use '!' shortcut."

    def help_exit(self):
        print "Exit the interpreter."
        print "You can also use the Ctrl-D shortcut."

    def help_help(self):
        print "Print help"

    def postloop(self):
        print '\nGoodbye !'
        super(DebugCmd, self).postloop()

    do_EOF = do_exit
    help_EOF = help_exit

Ancestors (in MRO)

Class variables

var color_b

var color_e

var color_g

var color_r

var display_mode

var doc_header

var doc_leader

var identchars

var intro

var lastcmd

var misc_header

var nohelp

var prompt

var ruler

var undoc_header

var use_rawinput

Instance variables

var dbg

Methods

def __init__(

self, dbg)

dbg : Debugguer

def __init__(self, dbg):
    "dbg : Debugguer"
    self.dbg = dbg
    super(DebugCmd, self).__init__()

def add_breakpoints(

self, bp_addr)

def add_breakpoints(self, bp_addr):
    for addr in bp_addr:
        addr = int(addr, 0)
        good = True
        for i, dbg_obj in enumerate(self.dbg.bp_list):
            if dbg_obj.addr == addr:
                good = False
                break
        if good is False:
            print "Breakpoint 0x%08x already set (%d)" % (addr, i)
        else:
            l = len(self.dbg.bp_list)
            self.dbg.add_breakpoint(addr)
            print "Breakpoint 0x%08x successfully added ! (%d)" % (addr, l)

def can_exit(

self)

def can_exit(self):
    return True

def cmdloop(

self, intro=None)

Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument.

def cmdloop(self, intro=None):
    """Repeatedly issue a prompt, accept input, parse an initial prefix
    off the received input, and dispatch to action methods, passing them
    the remainder of the line as argument.
    """
    self.preloop()
    if self.use_rawinput and self.completekey:
        try:
            import readline
            self.old_completer = readline.get_completer()
            readline.set_completer(self.complete)
            readline.parse_and_bind(self.completekey+": complete")
        except ImportError:
            pass
    try:
        if intro is not None:
            self.intro = intro
        if self.intro:
            self.stdout.write(str(self.intro)+"\n")
        stop = None
        while not stop:
            if self.cmdqueue:
                line = self.cmdqueue.pop(0)
            else:
                if self.use_rawinput:
                    try:
                        line = raw_input(self.prompt)
                    except EOFError:
                        line = 'EOF'
                else:
                    self.stdout.write(self.prompt)
                    self.stdout.flush()
                    line = self.stdin.readline()
                    if not len(line):
                        line = 'EOF'
                    else:
                        line = line.rstrip('\r\n')
            line = self.precmd(line)
            stop = self.onecmd(line)
            stop = self.postcmd(stop, line)
        self.postloop()
    finally:
        if self.use_rawinput and self.completekey:
            try:
                import readline
                readline.set_completer(self.old_completer)
            except ImportError:
                pass

def columnize(

self, list, displaywidth=80)

Display a list of strings as a compact set of columns.

Each column is only as wide as necessary. Columns are separated by two spaces (one was not legible enough).

def columnize(self, list, displaywidth=80):
    """Display a list of strings as a compact set of columns.
    Each column is only as wide as necessary.
    Columns are separated by two spaces (one was not legible enough).
    """
    if not list:
        self.stdout.write("<empty>\n")
        return
    nonstrings = [i for i in range(len(list))
                    if not isinstance(list[i], str)]
    if nonstrings:
        raise TypeError, ("list[i] not a string for i in %s" %
                          ", ".join(map(str, nonstrings)))
    size = len(list)
    if size == 1:
        self.stdout.write('%s\n'%str(list[0]))
        return
    # Try every row count from 1 upwards
    for nrows in range(1, len(list)):
        ncols = (size+nrows-1) // nrows
        colwidths = []
        totwidth = -2
        for col in range(ncols):
            colwidth = 0
            for row in range(nrows):
                i = row + nrows*col
                if i >= size:
                    break
                x = list[i]
                colwidth = max(colwidth, len(x))
            colwidths.append(colwidth)
            totwidth += colwidth + 2
            if totwidth > displaywidth:
                break
        if totwidth <= displaywidth:
            break
    else:
        nrows = len(list)
        ncols = 1
        colwidths = [0]
    for row in range(nrows):
        texts = []
        for col in range(ncols):
            i = row + nrows*col
            if i >= size:
                x = ""
            else:
                x = list[i]
            texts.append(x)
        while texts and not texts[-1]:
            del texts[-1]
        for col in range(len(texts)):
            texts[col] = texts[col].ljust(colwidths[col])
        self.stdout.write("%s\n"%str("  ".join(texts)))

def complete(

self, text, state)

Return the next possible completion for 'text'.

If a command has not been entered, then complete against command list. Otherwise try to call complete_ to get list of completions.

def complete(self, text, state):
    """Return the next possible completion for 'text'.
    If a command has not been entered, then complete against command list.
    Otherwise try to call complete_<command> to get list of completions.
    """
    if state == 0:
        import readline
        origline = readline.get_line_buffer()
        line = origline.lstrip()
        stripped = len(origline) - len(line)
        begidx = readline.get_begidx() - stripped
        endidx = readline.get_endidx() - stripped
        if begidx>0:
            cmd, args, foo = self.parseline(line)
            if cmd == '':
                compfunc = self.completedefault
            else:
                try:
                    compfunc = getattr(self, 'complete_' + cmd)
                except AttributeError:
                    compfunc = self.completedefault
        else:
            compfunc = self.completenames
        self.completion_matches = compfunc(text, line, begidx, endidx)
    try:
        return self.completion_matches[state]
    except IndexError:
        return None

def complete_help(

self, *args)

def complete_help(self, *args):
    commands = set(self.completenames(*args))
    topics = set(a[5:] for a in self.get_names()
                 if a.startswith('help_' + args[0]))
    return list(commands | topics)

def completedefault(

self, *ignored)

Method called to complete an input line when no command-specific complete_*() method is available.

By default, it returns an empty list.

def completedefault(self, *ignored):
    """Method called to complete an input line when no command-specific
    complete_*() method is available.
    By default, it returns an empty list.
    """
    return []

def completenames(

self, text, *ignored)

def completenames(self, text, *ignored):
    dotext = 'do_'+text
    return [a[3:] for a in self.get_names() if a.startswith(dotext)]

def default(

self, line)

Called on an input line when the command prefix is not recognized.

If this method is not overridden, it prints an error message and returns.

def default(self, line):
    """Called on an input line when the command prefix is not recognized.
    If this method is not overridden, it prints an error message and
    returns.
    """
    self.stdout.write('*** Unknown syntax: %s\n'%line)

def do_EOF(

self, _)

def do_exit(self, _):
    return True

def do_breakpoint(

self, arg)

def do_breakpoint(self, arg):
    if arg == "":
        self.help_breakpoint()
    else:
        addrs = arg.split(" ")
        self.add_breakpoints(addrs)

def do_display(

self, arg)

def do_display(self, arg):
    if arg == "":
        self.help_display()
        return
    args = arg.split(" ")
    if args[-1].lower() not in ["on", "off"]:
        self.print_warning("/!\ %s not in 'on' / 'off'" % args[-1])
        return
    mode = args[-1].lower() == "on"
    d = {}
    for a in args[:-1]:
        d[a] = mode
    self.dbg.active_trace(**d)
    self.update_display_mode()

def do_dump(

self, arg)

def do_dump(self, arg):
    if arg == "":
        self.help_dump()
    else:
        args = arg.split(" ")
        if len(args) >= 2:
            size = int(args[1], 0)
        else:
            size = 0xF
        addr = int(args[0], 0)
        self.dbg.get_mem(addr, size)

def do_exec(

self, line)

def do_exec(self, line):
    try:
        print eval(line)
    except Exception, error:
        print "*** Error: %s" % error

def do_exit(

self, _)

def do_exit(self, _):
    return True

def do_help(

self, arg)

List available commands with "help" or detailed help with "help cmd".

def do_help(self, arg):
    'List available commands with "help" or detailed help with "help cmd".'
    if arg:
        # XXX check arg syntax
        try:
            func = getattr(self, 'help_' + arg)
        except AttributeError:
            try:
                doc=getattr(self, 'do_' + arg).__doc__
                if doc:
                    self.stdout.write("%s\n"%str(doc))
                    return
            except AttributeError:
                pass
            self.stdout.write("%s\n"%str(self.nohelp % (arg,)))
            return
        func()
    else:
        names = self.get_names()
        cmds_doc = []
        cmds_undoc = []
        help = {}
        for name in names:
            if name[:5] == 'help_':
                help[name[5:]]=1
        names.sort()
        # There can be duplicates if routines overridden
        prevname = ''
        for name in names:
            if name[:3] == 'do_':
                if name == prevname:
                    continue
                prevname = name
                cmd=name[3:]
                if cmd in help:
                    cmds_doc.append(cmd)
                    del help[cmd]
                elif getattr(self, name).__doc__:
                    cmds_doc.append(cmd)
                else:
                    cmds_undoc.append(cmd)
        self.stdout.write("%s\n"%str(self.doc_leader))
        self.print_topics(self.doc_header,   cmds_doc,   15,80)
        self.print_topics(self.misc_header,  help.keys(),15,80)
        self.print_topics(self.undoc_header, cmds_undoc, 15,80)

def do_info(

self, arg)

def do_info(self, arg):
    av_info = ["registers",
               "display",
               "breakpoints",
               "watchmem"]
    if arg == "":
        print "'info' must be followed by the name of an info command."
        print "List of info subcommands:"
        for k in av_info:
            print "\t%s" % k
    if arg.startswith("b"):
        # Breakpoint
        self.print_breakpoints()
    if arg.startswith("d"):
        # Display
        self.update_display_mode()
        for k, v in self.display_mode.items():
            print "%s\t\t%s" % (k, v)
    if arg.startswith("w"):
        # Watchmem
        self.print_watchmems()
    if arg.startswith("r"):
        # Registers
        self.print_registers()

def do_run(

self, _)

def do_run(self, _):
    self.dbg.run()

def do_step(

self, arg)

def do_step(self, arg):
    if arg == "":
        nb = 1
    else:
        nb = int(arg)
    for _ in xrange(nb):
        self.dbg.step()

def do_watchmem(

self, arg)

def do_watchmem(self, arg):
    if arg == "":
        self.help_watchmem()
        return
    args = arg.split(" ")
    if len(args) >= 2:
        size = int(args[1], 0)
    else:
        size = 0xF
    addr = int(args[0], 0)
    self.dbg.watch_mem(addr, size)

def emptyline(

self)

Called when an empty line is entered in response to the prompt.

If this method is not overridden, it repeats the last nonempty command entered.

def emptyline(self):
    """Called when an empty line is entered in response to the prompt.
    If this method is not overridden, it repeats the last nonempty
    command entered.
    """
    if self.lastcmd:
        return self.onecmd(self.lastcmd)

def get_names(

self)

def get_names(self):
    # This method used to pull in base class attributes
    # at a time dir() didn't do it yet.
    return dir(self.__class__)

def help_EOF(

self)

def help_exit(self):
    print "Exit the interpreter."
    print "You can also use the Ctrl-D shortcut."

def help_breakpoint(

self)

def help_breakpoint(self):
    print "Add breakpoints to argument addresses."
    print "Example:"
    print "\tbreakpoint 0x11223344"
    print "\tbreakpoint 1122 0xabcd"

def help_display(

self)

def help_display(self):
    print "Enable/Disable tracing."
    print "Usage: display <mode1> <mode2> ... on|off"
    print "Available modes are:"
    for k in self.display_mode:
        print "\t%s" % k
    print "Use 'info display' to get current values"

def help_dump(

self)

def help_dump(self):
    print "Dump <addr> [size]. Dump size bytes at addr."

def help_exec(

self)

def help_exec(self):
    print "Exec a python command."
    print "You can also use '!' shortcut."

def help_exit(

self)

def help_exit(self):
    print "Exit the interpreter."
    print "You can also use the Ctrl-D shortcut."

def help_help(

self)

def help_help(self):
    print "Print help"

def help_info(

self)

def help_info(self):
    print "Generic command for showing things about the program being"
    print "debugged. Use 'info' without arguments to get the list of"
    print "available subcommands."

def help_run(

self)

def help_run(self):
    print "Launch or continue the current program"

def help_step(

self)

def help_step(self):
    print "Step program until it reaches a different source line."
    print "Argument N means do this N times (or till program stops"
    print "for another reason)."

def help_watchmem(

self)

def help_watchmem(self):
    print "Add a memory watcher."
    print "Usage: watchmem <addr> [size]"
    print "Use 'info watchmem' to get current memory watchers"

def onecmd(

self, line)

def onecmd(self, line):
    cmd_translate = {"h": "help",
                     "q": "exit",
                     "e": "exit",
                     "!": "exec",
                     "r": "run",
                     "i": "info",
                     "b": "breakpoint",
                     "s": "step",
                     "d": "dump"}
    if len(line) >= 2 and \
       line[1] == " " and \
       line[:1] in cmd_translate:
        line = cmd_translate[line[:1]] + line[1:]
    if len(line) == 1 and line in cmd_translate:
        line = cmd_translate[line]
    r = super(DebugCmd, self).onecmd(line)
    return r

def parseline(

self, line)

Parse the line into a command name and a string containing the arguments. Returns a tuple containing (command, args, line). 'command' and 'args' may be None if the line couldn't be parsed.

def parseline(self, line):
    """Parse the line into a command name and a string containing
    the arguments.  Returns a tuple containing (command, args, line).
    'command' and 'args' may be None if the line couldn't be parsed.
    """
    line = line.strip()
    if not line:
        return None, None, line
    elif line[0] == '?':
        line = 'help ' + line[1:]
    elif line[0] == '!':
        if hasattr(self, 'do_shell'):
            line = 'shell ' + line[1:]
        else:
            return None, None, line
    i, n = 0, len(line)
    while i < n and line[i] in self.identchars: i = i+1
    cmd, arg = line[:i], line[i:].strip()
    return cmd, arg, line

def postcmd(

self, stop, line)

Hook method executed just after a command dispatch is finished.

def postcmd(self, stop, line):
    """Hook method executed just after a command dispatch is finished."""
    return stop

def postloop(

self)

def postloop(self):
    print '\nGoodbye !'
    super(DebugCmd, self).postloop()

def precmd(

self, line)

Hook method executed just before the command line is interpreted, but after the input prompt is generated and issued.

def precmd(self, line):
    """Hook method executed just before the command line is
    interpreted, but after the input prompt is generated and issued.
    """
    return line

def preloop(

self)

Hook method executed once when the cmdloop() method is called.

def preloop(self):
    """Hook method executed once when the cmdloop() method is called."""
    pass

def print_breakpoints(

self)

def print_breakpoints(self):
    bp_list = self.dbg.bp_list
    if len(bp_list) == 0:
        print "No breakpoints."
    else:
        for i, b in enumerate(bp_list):
            print "%d\t0x%08x" % (i, b.addr)

def print_registers(

self)

def print_registers(self):
    regs = self.dbg.get_gpreg_all()
    # Display settings
    title1 = "Registers"
    title2 = "Values"
    max_name_len = max(map(len, regs.keys() + [title1]))
    # Print value table
    s = "%s%s    |    %s" % (
        title1, " " * (max_name_len - len(title1)), title2)
    print s
    print "-" * len(s)
    for name, value in sorted(regs.items(), key=lambda x: x[0]):
        print "%s%s    |    %s" % (name,
                                   " " * (max_name_len - len(name)),
                                   hex(value).replace("L", ""))

def print_topics(

self, header, cmds, cmdlen, maxcol)

def print_topics(self, header, cmds, cmdlen, maxcol):
    if cmds:
        self.stdout.write("%s\n"%str(header))
        if self.ruler:
            self.stdout.write("%s\n"%str(self.ruler * len(header)))
        self.columnize(cmds, maxcol-1)
        self.stdout.write("\n")

def print_warning(

self, s)

def print_warning(self, s):
    print self.color_r + s + self.color_e

def print_watchmems(

self)

def print_watchmems(self):
    watch_list = self.dbg.mem_watched
    if len(watch_list) == 0:
        print "No memory watchpoints."
    else:
        print "Num\tAddress  \tSize"
        for i, w in enumerate(watch_list):
            addr, size = w
            print "%d\t0x%08x\t0x%08x" % (i, addr, size)

def update_display_mode(

self)

def update_display_mode(self):
    self.display_mode = {"mn": self.dbg.myjit.jit.log_mn,
                         "regs": self.dbg.myjit.jit.log_regs,
                         "newbloc": self.dbg.myjit.jit.log_newbloc}

class Debugguer

Debugguer linked with a Jitter instance

class Debugguer(object):

    "Debugguer linked with a Jitter instance"

    def __init__(self, myjit):
        "myjit : jitter instance"
        self.myjit = myjit
        self.bp_list = []     # DebugBreakpointSoft list
        self.hw_bp_list = []  # DebugBreakpointHard list
        self.mem_watched = []  # Memory areas watched

    def init_run(self, addr):
        self.myjit.init_run(addr)

    def add_breakpoint(self, addr):
        "Add bp @addr"
        bp = DebugBreakpointSoft(addr)
        func = lambda x: bp
        bp.func = func
        self.bp_list.append(bp)
        self.myjit.add_breakpoint(addr, func)

    def init_memory_breakpoint(self):
        "Set exception handler on EXCEPT_BREAKPOINT_MEMORY"
        raise NotImplementedError("Not implemented")

    def add_memory_breakpoint(self, addr, size, read=False, write=False):
        "add mem bp @[addr, addr + size], on read/write/both"
        access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                            write=write)
        dbm = DebugBreakpointMemory(addr, size, access_type)
        self.hw_bp_list.append(dbm)
        self.myjit.vm.add_memory_breakpoint(addr, size, access_type)

    def remove_breakpoint(self, dbs):
        "remove the DebugBreakpointSoft instance"
        self.bp_list.remove(dbs)
        self.myjit.remove_breakpoints_by_callback(dbs.func)

    def remove_breakpoint_by_addr(self, addr):
        "remove breakpoints @ addr"
        for bp in self.get_breakpoint_by_addr(addr):
            self.remove_breakpoint(bp)

    def remove_memory_breakpoint(self, dbm):
        "remove the DebugBreakpointMemory instance"
        self.hw_bp_list.remove(dbm)
        self.myjit.vm.remove_memory_breakpoint(dbm.addr, dbm.access_type)

    def remove_memory_breakpoint_by_addr_access(self, addr, read=False,
                                                write=False):
        "remove breakpoints @ addr"
        access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                            write=write)
        for bp in self.hw_bp_list:
            if bp.addr == addr and bp.access_type == access_type:
                self.remove_memory_breakpoint(bp)

    def get_breakpoint_by_addr(self, addr):
        ret = []
        for dbgsoft in self.bp_list:
            if dbgsoft.addr == addr:
                ret.append(dbgsoft)
        return ret

    def get_breakpoints(self):
        return self.bp_list

    def active_trace(self, mn=None, regs=None, newbloc=None):
        if mn is not None:
            self.myjit.jit.log_mn = mn
        if regs is not None:
            self.myjit.jit.log_regs = regs
        if newbloc is not None:
            self.myjit.jit.log_newbloc = newbloc

    def handle_exception(self, res):
        if not res:
            # A breakpoint has stopped the execution
            return DebugBreakpointTerminate(res)

        if isinstance(res, DebugBreakpointSoft):
            print "Breakpoint reached @0x%08x" % res.addr
        elif isinstance(res, ExceptionHandle):
            if res == ExceptionHandle.memoryBreakpoint():
                print "Memory breakpoint reached!"

                # Remove flag
                except_flag = self.myjit.vm.get_exception()
                self.myjit.vm.set_exception(except_flag ^ res.except_flag)

            else:
                raise NotImplementedError("Unknown Except")
        else:
            raise NotImplementedError("type res")

        # Repropagate res
        return res

    def step(self):
        "Step in jit"

        self.myjit.jit.set_options(jit_maxline=1)
        # Reset all jitted blocks
        self.myjit.jit.clear_jitted_blocks()

        res = self.myjit.continue_run(step=True)
        self.handle_exception(res)

        self.myjit.jit.set_options(jit_maxline=50)
        self.on_step()

        return res

    def run(self):
        status = self.myjit.continue_run()
        return self.handle_exception(status)

    def get_mem(self, addr, size=0xF):
        "hexdump @addr, size"

        hexdump(self.myjit.vm.get_mem(addr, size))

    def get_mem_raw(self, addr, size=0xF):
        "hexdump @addr, size"
        return self.myjit.vm.get_mem(addr, size)

    def watch_mem(self, addr, size=0xF):
        self.mem_watched.append((addr, size))

    def on_step(self):
        for addr, size in self.mem_watched:
            print "@0x%08x:" % addr
            self.get_mem(addr, size)

    def get_reg_value(self, reg_name):
        return getattr(self.myjit.cpu, reg_name)

    def set_reg_value(self, reg_name, value):

        # Handle PC case
        if reg_name == self.myjit.ir_arch.pc.name:
            self.init_run(value)

        setattr(self.myjit.cpu, reg_name, value)

    def get_gpreg_all(self):
        "Return general purposes registers"
        return self.myjit.cpu.get_gpreg()

Ancestors (in MRO)

Instance variables

var bp_list

var hw_bp_list

var mem_watched

var myjit

Methods

def __init__(

self, myjit)

myjit : jitter instance

def __init__(self, myjit):
    "myjit : jitter instance"
    self.myjit = myjit
    self.bp_list = []     # DebugBreakpointSoft list
    self.hw_bp_list = []  # DebugBreakpointHard list
    self.mem_watched = []  # Memory areas watched

def active_trace(

self, mn=None, regs=None, newbloc=None)

def active_trace(self, mn=None, regs=None, newbloc=None):
    if mn is not None:
        self.myjit.jit.log_mn = mn
    if regs is not None:
        self.myjit.jit.log_regs = regs
    if newbloc is not None:
        self.myjit.jit.log_newbloc = newbloc

def add_breakpoint(

self, addr)

Add bp @addr

def add_breakpoint(self, addr):
    "Add bp @addr"
    bp = DebugBreakpointSoft(addr)
    func = lambda x: bp
    bp.func = func
    self.bp_list.append(bp)
    self.myjit.add_breakpoint(addr, func)

def add_memory_breakpoint(

self, addr, size, read=False, write=False)

add mem bp @[addr, addr + size], on read/write/both

def add_memory_breakpoint(self, addr, size, read=False, write=False):
    "add mem bp @[addr, addr + size], on read/write/both"
    access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                        write=write)
    dbm = DebugBreakpointMemory(addr, size, access_type)
    self.hw_bp_list.append(dbm)
    self.myjit.vm.add_memory_breakpoint(addr, size, access_type)

def get_breakpoint_by_addr(

self, addr)

def get_breakpoint_by_addr(self, addr):
    ret = []
    for dbgsoft in self.bp_list:
        if dbgsoft.addr == addr:
            ret.append(dbgsoft)
    return ret

def get_breakpoints(

self)

def get_breakpoints(self):
    return self.bp_list

def get_gpreg_all(

self)

Return general purposes registers

def get_gpreg_all(self):
    "Return general purposes registers"
    return self.myjit.cpu.get_gpreg()

def get_mem(

self, addr, size=15)

hexdump @addr, size

def get_mem(self, addr, size=0xF):
    "hexdump @addr, size"
    hexdump(self.myjit.vm.get_mem(addr, size))

def get_mem_raw(

self, addr, size=15)

hexdump @addr, size

def get_mem_raw(self, addr, size=0xF):
    "hexdump @addr, size"
    return self.myjit.vm.get_mem(addr, size)

def get_reg_value(

self, reg_name)

def get_reg_value(self, reg_name):
    return getattr(self.myjit.cpu, reg_name)

def handle_exception(

self, res)

def handle_exception(self, res):
    if not res:
        # A breakpoint has stopped the execution
        return DebugBreakpointTerminate(res)
    if isinstance(res, DebugBreakpointSoft):
        print "Breakpoint reached @0x%08x" % res.addr
    elif isinstance(res, ExceptionHandle):
        if res == ExceptionHandle.memoryBreakpoint():
            print "Memory breakpoint reached!"
            # Remove flag
            except_flag = self.myjit.vm.get_exception()
            self.myjit.vm.set_exception(except_flag ^ res.except_flag)
        else:
            raise NotImplementedError("Unknown Except")
    else:
        raise NotImplementedError("type res")
    # Repropagate res
    return res

def init_memory_breakpoint(

self)

Set exception handler on EXCEPT_BREAKPOINT_MEMORY

def init_memory_breakpoint(self):
    "Set exception handler on EXCEPT_BREAKPOINT_MEMORY"
    raise NotImplementedError("Not implemented")

def init_run(

self, addr)

def init_run(self, addr):
    self.myjit.init_run(addr)

def on_step(

self)

def on_step(self):
    for addr, size in self.mem_watched:
        print "@0x%08x:" % addr
        self.get_mem(addr, size)

def remove_breakpoint(

self, dbs)

remove the DebugBreakpointSoft instance

def remove_breakpoint(self, dbs):
    "remove the DebugBreakpointSoft instance"
    self.bp_list.remove(dbs)
    self.myjit.remove_breakpoints_by_callback(dbs.func)

def remove_breakpoint_by_addr(

self, addr)

remove breakpoints @ addr

def remove_breakpoint_by_addr(self, addr):
    "remove breakpoints @ addr"
    for bp in self.get_breakpoint_by_addr(addr):
        self.remove_breakpoint(bp)

def remove_memory_breakpoint(

self, dbm)

remove the DebugBreakpointMemory instance

def remove_memory_breakpoint(self, dbm):
    "remove the DebugBreakpointMemory instance"
    self.hw_bp_list.remove(dbm)
    self.myjit.vm.remove_memory_breakpoint(dbm.addr, dbm.access_type)

def remove_memory_breakpoint_by_addr_access(

self, addr, read=False, write=False)

remove breakpoints @ addr

def remove_memory_breakpoint_by_addr_access(self, addr, read=False,
                                            write=False):
    "remove breakpoints @ addr"
    access_type = DebugBreakpointMemory.get_access_type(read=read,
                                                        write=write)
    for bp in self.hw_bp_list:
        if bp.addr == addr and bp.access_type == access_type:
            self.remove_memory_breakpoint(bp)

def run(

self)

def run(self):
    status = self.myjit.continue_run()
    return self.handle_exception(status)

def set_reg_value(

self, reg_name, value)

def set_reg_value(self, reg_name, value):
    # Handle PC case
    if reg_name == self.myjit.ir_arch.pc.name:
        self.init_run(value)
    setattr(self.myjit.cpu, reg_name, value)

def step(

self)

Step in jit

def step(self):
    "Step in jit"
    self.myjit.jit.set_options(jit_maxline=1)
    # Reset all jitted blocks
    self.myjit.jit.clear_jitted_blocks()
    res = self.myjit.continue_run(step=True)
    self.handle_exception(res)
    self.myjit.jit.set_options(jit_maxline=50)
    self.on_step()
    return res

def watch_mem(

self, addr, size=15)

def watch_mem(self, addr, size=0xF):
    self.mem_watched.append((addr, size))