diff --git a/Emulator.py b/Emulator.py new file mode 100644 index 0000000..223a70e --- /dev/null +++ b/Emulator.py @@ -0,0 +1,122 @@ + +import re + +from opcodes import OPCODES + +REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"] + +class Emulator: + + def __init__ (self, source_text): + self.registers = {} + for reg_name in REGISTERS: + self.registers[reg_name] = "Junk" + self.stack = {} + self.code = [] + self.labels = {} + self.changes = {} + self.status = {} + self.last_sp = 0 + self.max_stack_size = 0 + index = 0 + for line in iter(source_text.splitlines()): + index = self.processSourceLine(line, index) + + def setStack (self, *stack_list, **kwargs): + """ + Sets various stack elements, starting from 0 and going up. + Automatically sets rsp. This can be disabled by passing set_rsp=False. + """ + i = -1 + for element in stack_list: + i += 1 + self.stack[i] = element + if (not 'set_rsp' in kwargs) or kwargs['set_rsp']: + self.setRegs(rsp=i) + + def setRegs (self, **reg_dict): + for reg_name, reg_val in reg_dict.iteritems(): + self.registers["%"+reg_name] = reg_val + + def getVal (self, val_text): + if val_text[0] == "$": + return int(val_text[1:]) + elif val_text[0] == "%": + return self.registers[val_text] + else: + raise "NOT A VALUE! UGHGUIHGUE!" + + def compareVal (self, valT1, valT2): + val1 = self.getVal(valT2) + val2 = self.getVal(valT1) + self.status["g"] = val1>val2 + self.status["l"] = val1= len(self.code): + return None + instruct = self.code[self.registers['%rip']] + opcode = instruct[0] + self.changes = {} + + OPCODES[opcode](self, *instruct[1:]) + + if self.registers['%rip'] == old_rip: + self.registers['%rip'] += 1 + else: + self.changedRegisters(('%rip',"jump")) + + return old_rip + + def __iter__(self): + return self + + def next(self): + output = self.iterate() + if output is None: + raise StopIteration() + else: + return output diff --git a/TikzPainter.py b/TikzPainter.py new file mode 100644 index 0000000..5db1655 --- /dev/null +++ b/TikzPainter.py @@ -0,0 +1,75 @@ + +REG_STATUS_TO_COLOR = { + "insert": "green", + "change": "yellow", + "remove": "red", + "none": "black", + "jump": "orange" +} + +class TikzPainter: + + def __init__ (self, registers=None, max_stack_size=8): + self.registers = registers if registers else REGISTERS + self.text = [] + self.pos_x = 0 + self.max_stack_size = max_stack_size + + def addText (self, str, *args): + self.text.append(str.format(*args)) + + def getRegColor (self, reg_state): + return REG_STATUS_TO_COLOR[reg_state] + + def drawState (self, emu, line_nr=None): + x = (self.pos_x+1)*2.5-0.5 + self.pos_x += 1 + + # Draw register cells + pos = 0.5 + for reg_name in self.registers: + pos -= 0.5 + if reg_name =="": + continue + reg_state = emu.regState(reg_name) + reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10" + self.addText("\t\\node[{}]() at ({}, {}){{{}}};\n", + reg_dect, x, pos, emu.getVal(reg_name)) + + # Draw stack + pos -= 1.5 + base_sp = max(emu.last_sp, emu.getVal('%rsp')) + if emu.last_sp - 1 == emu.getVal('%rsp'): + pos += 0.5 + for index in range(base_sp, max(-1, base_sp-self.max_stack_size),-1): + reg_state = emu.regState("m"+str(index)) + reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10" + self.addText("\t\\node[{}]() at ({}, {}){{{}}};\n", + reg_dect, x, pos, emu.stack[index]) + pos -= 0.5 + + # Draw line signature + if line_nr == None: + return + pos = 2 + signature = emu.getLineSignature(line_nr) + for token in signature: + self.addText("\t\\node[text_node]() at ({}, {}){{{}}};\n", x-1.25, pos, token) + pos -= 0.5 + + def drawNames (self, emu): + x = 0 + pos = 0 + for reg_name in self.registers: + self.addText("\t\\node[text_node]() at ({}, {}){{{}}};\n", x, pos, reg_name[1:]) + pos -= 0.5 + + self.addText("\t\\node[text_node]() at ({}, {}){{TOS+1}};\n", x, pos-0.5) + self.addText("\t\\node[text_node]() at ({}, {}){{TOS}};\n", x, pos-1.0) + pos -= 1 + for index in range(1,self.max_stack_size): + pos -= 0.5 + self.addText("\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n", x, pos, index) + + def __str__ (self): + return "".join(self.text) diff --git a/infernal.py b/infernal.py index f4d5afe..6989c7c 100644 --- a/infernal.py +++ b/infernal.py @@ -1,198 +1,9 @@ -import re import sys +import getopt -from opcodes import OPCODES +from Emulator import Emulator +from TikzPainter import TikzPainter -REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"] -REG_STATUS_TO_COLOR = { - "insert": "green", - "change": "yellow", - "remove": "red", - "none": "black", - "jump": "orange" -} - -class TikzPainter: - - def __init__ (self, registers=None, max_stack_size=8): - self.registers = registers if registers else REGISTERS - self.text = [] - self.pos_x = 0 - self.max_stack_size = max_stack_size - - def addText (self, str, *args): - self.text.append(str.format(*args)) - - def getRegColor (self, reg_state): - return REG_STATUS_TO_COLOR[reg_state] - - def drawState (self, emu, line_nr=None): - x = (self.pos_x+1)*2.5-0.5 - self.pos_x += 1 - - # Draw register cells - pos = 0.5 - for reg_name in self.registers: - pos -= 0.5 - if reg_name =="": - continue - reg_state = emu.regState(reg_name) - reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10" - self.addText("\t\\node[{}]() at ({}, {}){{{}}};\n", - reg_dect, x, pos, emu.getVal(reg_name)) - - # Draw stack - pos -= 1.5 - base_sp = max(emu.last_sp, emu.getVal('%rsp')) - if emu.last_sp - 1 == emu.getVal('%rsp'): - pos += 0.5 - for index in range(base_sp, max(-1, base_sp-self.max_stack_size),-1): - reg_state = emu.regState("m"+str(index)) - reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10" - self.addText("\t\\node[{}]() at ({}, {}){{{}}};\n", - reg_dect, x, pos, emu.stack[index]) - pos -= 0.5 - - # Draw line signature - if line_nr == None: - return - pos = 2 - signature = emu.getLineSignature(line_nr) - for token in signature: - self.addText("\t\\node[text_node]() at ({}, {}){{{}}};\n", x-1.25, pos, token) - pos -= 0.5 - - def drawNames (self, emu): - x = 0 - pos = 0 - for reg_name in self.registers: - self.addText("\t\\node[text_node]() at ({}, {}){{{}}};\n", x, pos, reg_name[1:]) - pos -= 0.5 - - self.addText("\t\\node[text_node]() at ({}, {}){{TOS+1}};\n", x, pos-0.5) - self.addText("\t\\node[text_node]() at ({}, {}){{TOS}};\n", x, pos-1.0) - pos -= 1 - for index in range(1,self.max_stack_size): - pos -= 0.5 - self.addText("\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n", x, pos, index) - - def __str__ (self): - return "".join(self.text) - - -class Emulator: - - def __init__ (self, source_text): - self.registers = {} - for reg_name in REGISTERS: - self.registers[reg_name] = "Junk" - self.stack = {} - self.code = [] - self.labels = {} - self.changes = {} - self.status = {} - self.last_sp = 0 - self.max_stack_size = 0 - index = 0 - for line in iter(source_text.splitlines()): - index = self.processSourceLine(line, index) - - def setStack (self, *stack_list, **kwargs): - """ - Sets various stack elements, starting from 0 and going up. - Automatically sets rsp. This can be disabled by passing set_rsp=False. - """ - i = -1 - for element in stack_list: - i += 1 - self.stack[i] = element - if (not 'set_rsp' in kwargs) or kwargs['set_rsp']: - self.setRegs(rsp=i) - - def setRegs (self, **reg_dict): - for reg_name, reg_val in reg_dict.iteritems(): - self.registers["%"+reg_name] = reg_val - - def getVal (self, val_text): - if val_text[0] == "$": - return int(val_text[1:]) - elif val_text[0] == "%": - return self.registers[val_text] - else: - raise "NOT A VALUE! UGHGUIHGUE!" - - def compareVal (self, valT1, valT2): - val1 = self.getVal(valT2) - val2 = self.getVal(valT1) - self.status["g"] = val1>val2 - self.status["l"] = val1= len(self.code): - return None - instruct = self.code[self.registers['%rip']] - opcode = instruct[0] - self.changes = {} - - OPCODES[opcode](self, *instruct[1:]) - - if self.registers['%rip'] == old_rip: - self.registers['%rip'] += 1 - else: - self.changedRegisters(('%rip',"jump")) - - return old_rip - - def __iter__(self): - return self - - def next(self): - output = self.iterate() - if output is None: - raise StopIteration() - else: - return output +if __name__ == "__main__": + pass