Added a new painter, for drawing emulation to terminal.
This commit is contained in:
parent
daad0a3062
commit
49ff6506e6
97
AsciiPainter.py
Normal file
97
AsciiPainter.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
NORMAL_COLOR = '\033[0m'
|
||||||
|
|
||||||
|
REG_STATUS_TO_COLOR = {
|
||||||
|
"insert": '\033[32m',
|
||||||
|
"change": '\033[33m',
|
||||||
|
"remove": '\033[31m',
|
||||||
|
"none": '\033[0m',
|
||||||
|
"jump": '\033[36m'
|
||||||
|
}
|
||||||
|
|
||||||
|
class AsciiPainter:
|
||||||
|
|
||||||
|
def __init__ (self, registers=None, max_stack_size=8, stack_draw_mode="up"):
|
||||||
|
self.registers = registers if registers else REGISTERS
|
||||||
|
self.states = []
|
||||||
|
self.max_stack_size = max_stack_size
|
||||||
|
self.stack_draw_mode = stack_draw_mode
|
||||||
|
|
||||||
|
def saveState (self, emu, line_nr=None):
|
||||||
|
# Init state
|
||||||
|
state = []
|
||||||
|
self.states.append(state)
|
||||||
|
# Write opcode to state
|
||||||
|
if line_nr != None:
|
||||||
|
signature = emu.getLineSignature(line_nr)
|
||||||
|
for token in signature:
|
||||||
|
state.append({ 'state': 'none', 'val': token })
|
||||||
|
#
|
||||||
|
for i in range(3-len(state)): state.append({'state':'none', 'val': ''})
|
||||||
|
for i in range(len(state)-3): state.pop()
|
||||||
|
state.append({'state':'none', 'val':''})
|
||||||
|
# Write registers to state
|
||||||
|
for reg_name in self.registers:
|
||||||
|
if reg_name =="":
|
||||||
|
state.append({'state':'none', 'val':''})
|
||||||
|
continue
|
||||||
|
reg_state = emu.regState(reg_name)
|
||||||
|
state.append({ 'state': reg_state, 'val': emu.getVal(reg_name) })
|
||||||
|
# Write stack to state
|
||||||
|
stack_base_pointer = emu.getVal('%rbp')
|
||||||
|
print(emu.last_sp, emu.getVal('%rsp'))
|
||||||
|
base_sp = emu.getVal('%rsp')
|
||||||
|
assert(isinstance(emu.getVal('%rsp'), (int, long)))
|
||||||
|
state.append({'state':'none', 'val': ''})
|
||||||
|
if emu.regState('m'+str(base_sp-1)) == 'remove':
|
||||||
|
state.append({'state': emu.regState('m'+str(base_sp-1)), 'val': emu.stack[base_sp-1]})
|
||||||
|
else:
|
||||||
|
state.append({'state': 'none', 'val': ''})
|
||||||
|
for index in range(0, self.max_stack_size):
|
||||||
|
stack_i = base_sp + index
|
||||||
|
print(index, stack_i)
|
||||||
|
if stack_i < emu.max_stack_size:
|
||||||
|
state.append({ 'state': emu.regState("m"+str(stack_i)), 'val': emu.stack[stack_i] })
|
||||||
|
if stack_base_pointer == index:
|
||||||
|
stack_base_pointer = emu.stack[base_pointer]
|
||||||
|
# TODO: Draw stack frame seperators
|
||||||
|
else:
|
||||||
|
state.append({'state':'none', 'val': ''})
|
||||||
|
|
||||||
|
def to_string (self, emu):
|
||||||
|
number_states = len(self.states)
|
||||||
|
number_state_vars = len(self.states[0])
|
||||||
|
|
||||||
|
term_width = int(subprocess.check_output(['tput', 'cols']))
|
||||||
|
number_states_pr_block = term_width / (10+2) - 1
|
||||||
|
separator = '-' * term_width
|
||||||
|
l = []
|
||||||
|
|
||||||
|
for base_state in range(0, number_states, number_states_pr_block):
|
||||||
|
l.append(separator)
|
||||||
|
for var_i in range(0, number_state_vars):
|
||||||
|
l.append('{:10}'.format(self.nameOfVar(var_i-4)))
|
||||||
|
for state_i in range(0, min(number_states_pr_block, number_states - base_state)):
|
||||||
|
var = self.states[base_state+state_i][var_i]
|
||||||
|
l.append('{}{:>10}{} '.format(REG_STATUS_TO_COLOR[var['state']], var['val'], NORMAL_COLOR))
|
||||||
|
l.append('\n')
|
||||||
|
l.append(separator)
|
||||||
|
|
||||||
|
return ''.join(l)
|
||||||
|
|
||||||
|
def nameOfVar (self, i):
|
||||||
|
if i < 0: return ''
|
||||||
|
if i < len(self.registers):
|
||||||
|
return self.registers[i]
|
||||||
|
elif i != len(self.registers):
|
||||||
|
state_i = i-len(self.registers) - 2
|
||||||
|
return 'TOS{}{}'.format('+' if state_i < 0 else '-', abs(state_i))
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def __str__ (self):
|
||||||
|
return 'TikzPainter[]'
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Junk
|
||||||
from opcodes import OPCODES
|
from opcodes import OPCODES
|
||||||
|
|
||||||
REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi",
|
REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi",
|
||||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"]
|
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"]
|
||||||
|
|
||||||
class CodeParseException (BaseException):
|
class CodeParseException (BaseException):
|
||||||
|
|
||||||
|
@ -158,3 +158,4 @@ class Emulator:
|
||||||
|
|
||||||
def getUsedRegisters (self):
|
def getUsedRegisters (self):
|
||||||
return [reg_name for reg_name, reg_val in self.registers.iteritems() if not isinstance(reg_val, Junk.Junk)]
|
return [reg_name for reg_name, reg_val in self.registers.iteritems() if not isinstance(reg_val, Junk.Junk)]
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class TikzPainter:
|
||||||
pos -= 0.5
|
pos -= 0.5
|
||||||
return pos, x
|
return pos, x
|
||||||
|
|
||||||
def drawState (self, emu, line_nr=None):
|
def saveState (self, emu, line_nr=None):
|
||||||
x = (self.pos_x+1)*2.5-0.5
|
x = (self.pos_x+1)*2.5-0.5
|
||||||
self.pos_x += 1
|
self.pos_x += 1
|
||||||
|
|
||||||
|
@ -114,13 +114,14 @@ class TikzPainter:
|
||||||
self.addText("\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n",
|
self.addText("\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n",
|
||||||
x, pos, index)
|
x, pos, index)
|
||||||
|
|
||||||
def to_string (self):
|
def to_string (self, emu):
|
||||||
PRE = """ \\documentclass{standalone}
|
PRE = """ \\documentclass{standalone}
|
||||||
\\usepackage{tikz}
|
\\usepackage{tikz}
|
||||||
\\begin{document}
|
\\begin{document}
|
||||||
\\begin{tikzpicture}["""+self.options+"]"
|
\\begin{tikzpicture}["""+self.options+"]"
|
||||||
POST = """\\end{tikzpicture}
|
POST = """\\end{tikzpicture}
|
||||||
\\end{document}"""
|
\\end{document}"""
|
||||||
|
self.drawNames(emu)
|
||||||
return PRE + "".join(self.text) + POST
|
return PRE + "".join(self.text) + POST
|
||||||
|
|
||||||
def __str__ (self):
|
def __str__ (self):
|
||||||
|
|
12
main.py
12
main.py
|
@ -7,6 +7,7 @@ import argparse
|
||||||
|
|
||||||
from Emulator import Emulator, CodeParseException, REGISTERS
|
from Emulator import Emulator, CodeParseException, REGISTERS
|
||||||
from TikzPainter import TikzPainter
|
from TikzPainter import TikzPainter
|
||||||
|
from AsciiPainter import AsciiPainter
|
||||||
import Junk
|
import Junk
|
||||||
|
|
||||||
def parse_args ():
|
def parse_args ():
|
||||||
|
@ -64,16 +65,17 @@ def main ():
|
||||||
emu.setRegs(**registers_init)
|
emu.setRegs(**registers_init)
|
||||||
emu.setStack(Junk.Junk("junk..."), Junk.Junk("calling eip"))
|
emu.setStack(Junk.Junk("junk..."), Junk.Junk("calling eip"))
|
||||||
|
|
||||||
painter = TikzPainter(registers_to_draw)
|
painter_class = TikzPainter # AsciiPainter
|
||||||
|
|
||||||
|
painter = painter_class(registers_to_draw)
|
||||||
|
|
||||||
# Iteratively draw states.
|
# Iteratively draw states.
|
||||||
painter.drawState(emu)
|
painter.saveState(emu)
|
||||||
for line_nr in emu:
|
for line_nr in emu:
|
||||||
painter.drawState(emu, line_nr)
|
painter.saveState(emu, line_nr)
|
||||||
painter.drawNames(emu)
|
|
||||||
|
|
||||||
# Display result
|
# Display result
|
||||||
output_file.write(painter.to_string())
|
output_file.write(painter.to_string(emu))
|
||||||
output_file.close()
|
output_file.close()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in New Issue
Block a user