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)
- DebugCmd
- cmd.Cmd
- __builtin__.object
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_
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)
- Debugguer
- __builtin__.object
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))