📄 dbg.py
字号:
#!/usr/bin/env pythonimport Serial, Disassembler, Screenimport sys, curses#Modem.test_modem()#Disassembler.test_disasm()# Global function debug(msg)class SerialDebug: def __init__(self, ser): self.serial = ser # Converts a hex digit into a number def hex2int(self, x): if ord(x) >= ord('0') and ord(x) <= ord('9'): return ord(x) - ord('0') if ord(x) >= ord('a') and ord(x) <= ord('f'): return ord(x) - ord('a') + 10 if ord(x) >= ord('A') and ord(x) <= ord('F'): return ord(x) - ord('A') + 10 return 0 # Converts a single byte string into a number def byte2int(self, x): return self.hex2int(x[0]) * 16 + self.hex2int(x[1]) # Converts a four byte string into a number def long2int(self, x): return (self.byte2int(x[:2])) \ | (self.byte2int(x[2:4]) << 8) \ | (self.byte2int(x[4:6]) << 16) \ | (self.byte2int(x[6:8]) << 24) # Ported from sh-stub.c, sans run-length encoding def packet_send(self, packet):# debug("send packet: " + packet) ser = self.serial # Retry until we get a positive response while 1: ser.putch('$') checksum = 0 for i in list(packet): ser.putch(i) checksum = checksum + ord(i) ser.putch('#') ser.putch("%02x" % (checksum & 0xff)) resp = ser.getch() if resp == '+': break # Ported from sh-stub.c def packet_recv(self): ser = self.serial # Wait around for start char, ignore all others while 1: ch = ser.getch() if ch == '$': break # Retry until we get a good checksum while 1: checksum = 0 xmitcsum = -1 # Read until a # buffer = "" while 1: ch = ser.getch() if ch == '$': break if ch == '#': break checksum = checksum + ord(ch) buffer = buffer + ch # If we find another packet start, make another go if ch == '$': continue # Otherwise it's probably a checksum if ch != '#': continue # Get the transmitted checksum c1 = ser.getch() c2 = ser.getch() #debug("read chars " + c1 + c2) xmitcsum = self.byte2int(c1 + c2) #debug("checksums are " + str(checksum) + "/" + str(xmitcsum)) # If it doesn't match, try again if xmitcsum != (checksum & 0xff): ser.putch('-') continue else: ser.putch('+')# debug("got packet: " + buffer) return buffer # Connect to the remote host def connect_to_remote(self): self.serial.putch('+') # Acknowledge any signal packets self.packet_send("?") # Ask for what happened init = self.packet_recv() # Get the init packet if init[0] == 'S' and init[1] == '0' and (init[2] == '5' or init[2] == '7'): return 1 return None # Read bytes from the host's memory def read_memory(self, addr, ln): # Request memory read packet = "m%08x,%04x" % (addr, ln) self.packet_send(packet) # Process the returned info packet = self.packet_recv() rv = "" while len(packet) > 0: rv = rv + chr(self.byte2int(packet)) packet = packet[2:] return rv # Reads the registers and stores their values into a dictionary by name def read_regs(self): # Request register read self.packet_send("g") # Process the returned info packet = self.packet_recv() regs = { } for i in range(16): regs['R%d' % i] = self.long2int(packet[i*8:(i+1)*8]) regs['PC'] = self.long2int(packet[16*8:17*8]) regs['PR'] = self.long2int(packet[17*8:18*8]) regs['GBR'] = self.long2int(packet[18*8:19*8]) regs['VBR'] = self.long2int(packet[19*8:20*8]) regs['MACH'] = self.long2int(packet[20*8:21*8]) regs['MACL'] = self.long2int(packet[21*8:22*8]) regs['SR'] = self.long2int(packet[22*8:23*8]) return regs # Single-step the program def single_step(self): # Send a single-step command self.packet_send("s") # Wait for a response (should be another signal packet) packet = self.packet_recv() # Make sure that's what we expected if packet[0] == 'S' and packet[1] == '0' and packet[2] == '5': return None else: return packet class RemoteDisasm(Disassembler.Disassembler): def __init__(self, dbg): self.dbg = dbg Disassembler.Disassembler.__init__(self) # We override the read function to read from the remote host def read(self, addr, len): return self.dbg.read_memory(addr, len)def main(argv): global debug ser = Serial.Serial(57600) dbg = SerialDebug(ser) scr = Screen.Screen() dis = RemoteDisasm(dbg) debug = scr.msgswnd.write_message scr.msgswnd.write_message("Welcome to Dan's DC Debugger v0.1") if scr.scrn_w < 86 or scr.scrn_h < 40: scr.msgswnd.write_message("Your screen is less than 86x40 -- you probly can't see everything") scr.msgswnd.write_message("Connecting to host machine...") if dbg.connect_to_remote() is not None: scr.msgswnd.write_message("Success! Host is online.") else: scr.msgswnd.write_message("Could not connect to host.") scr.codewnd.disasm = dis debug("Reading register state") regs = dbg.read_regs() scr.regswnd.doodle(regs) debug("Reading & translating binary code") scr.codewnd.set_display_params(regs['PC'] - 8, regs['PC'], regs['PC']) scr.codewnd.refresh() debug("Ready") while 1: k = scr.scrn.getch() if k == curses.KEY_UP: scr.codewnd.move_cursor_up() elif k == curses.KEY_DOWN: scr.codewnd.move_cursor_down() elif k == curses.KEY_F7: debug("Stepping") dbg.single_step() regs = dbg.read_regs() scr.regswnd.doodle(regs) scr.codewnd.update_pc(regs['PC']) scr.codewnd.repaint() debug("Ready") elif k < 256: k = chr(k) scr.msgswnd.write_message("Got key " + k) else: k = repr(k) scr.msgswnd.write_message("Unknown key " + k) if k == 'q': break scr.shutdown()if __name__=='__main__': sys.exit(main(sys.argv))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -