1
0

Added a new painter, for drawing emulation to terminal.

This commit is contained in:
Jon Michael Aanes 2018-01-03 18:58:53 +01:00
parent daad0a3062
commit 49ff6506e6
4 changed files with 109 additions and 8 deletions

97
AsciiPainter.py Normal file
View 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[]'

View File

@ -5,7 +5,7 @@ import Junk
from opcodes import OPCODES
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):
@ -158,3 +158,4 @@ class Emulator:
def getUsedRegisters (self):
return [reg_name for reg_name, reg_val in self.registers.iteritems() if not isinstance(reg_val, Junk.Junk)]

View File

@ -58,7 +58,7 @@ class TikzPainter:
pos -= 0.5
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
self.pos_x += 1
@ -114,13 +114,14 @@ class TikzPainter:
self.addText("\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n",
x, pos, index)
def to_string (self):
def to_string (self, emu):
PRE = """ \\documentclass{standalone}
\\usepackage{tikz}
\\begin{document}
\\begin{tikzpicture}["""+self.options+"]"
POST = """\\end{tikzpicture}
\\end{document}"""
self.drawNames(emu)
return PRE + "".join(self.text) + POST
def __str__ (self):

12
main.py
View File

@ -7,6 +7,7 @@ import argparse
from Emulator import Emulator, CodeParseException, REGISTERS
from TikzPainter import TikzPainter
from AsciiPainter import AsciiPainter
import Junk
def parse_args ():
@ -64,16 +65,17 @@ def main ():
emu.setRegs(**registers_init)
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.
painter.drawState(emu)
painter.saveState(emu)
for line_nr in emu:
painter.drawState(emu, line_nr)
painter.drawNames(emu)
painter.saveState(emu, line_nr)
# Display result
output_file.write(painter.to_string())
output_file.write(painter.to_string(emu))
output_file.close()
if __name__ == "__main__":