diff --git a/Emulator.py b/Emulator.py index 61bccf3..c204975 100644 --- a/Emulator.py +++ b/Emulator.py @@ -1,24 +1,33 @@ import re +import Junk from opcodes import OPCODES REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"] +JUNK_VALUE = Junk.Junk() + +class CodeParseException (BaseException): + + def __init__ (self, line_nr, string): + self.line_nr = line_nr + self.string = string class Emulator: def __init__ (self, source_text, max_stack_size=1000): + self.source = source_text self.registers = {} for reg_name in REGISTERS: - self.registers[reg_name] = "Junk" + self.registers[reg_name] = JUNK_VALUE self.stack = {} for i in range(max_stack_size): - self.stack[i] = 0 + self.stack[i] = JUNK_VALUE self.code = [] self.labels = {} self.changes = {} - self.status = {} + self.status = {'i':True} self.last_sp = 0 self.max_stack_size = 0 index = 0 @@ -48,14 +57,18 @@ class Emulator: elif val_text[0] == "%": return self.registers[val_text] else: - raise "NOT A VALUE! UGHGUIHGUE!" + raise ValueError('{} is not an usable value name'.format(val_text)) def compareVal (self, valT1, valT2): val1 = self.getVal(valT2) val2 = self.getVal(valT1) + if isinstance(val1,Junk.Junk) or isinstance(val2,Junk.Junk): + self.status["i"] = (True,) + return self.status["g"] = val1>val2 self.status["l"] = val10 and self.status["i"]: + raise Junk.JunkComparisonException(*self.status['i']) + and_, or_ = True, False + for cnd_name, cnd_val in conditions.iteritems(): + if self.status[cnd_name] == cnd_val: + or_ = True + else: + and_ = False + if or_ if cond_op=="or" else and_: + self.registers['%rip'] = self.labels[label] + return True + else: + return False + def iterate (self): old_rip = self.registers['%rip'] self.last_sp = self.registers['%rsp'] @@ -123,3 +151,6 @@ class Emulator: raise StopIteration() else: return output + + def getUsedRegisters (self): + return [reg_name for reg_name, reg_val in self.registers.iteritems() if reg_val!=JUNK_VALUE] diff --git a/Junk.py b/Junk.py new file mode 100644 index 0000000..7ecc07c --- /dev/null +++ b/Junk.py @@ -0,0 +1,27 @@ + +class JunkComparisonException (BaseException): + + pass + +class Junk: + + def __init__ (self): + pass + + def __str__ (self): + return "[Junk]" + + def __repr__ (self): + return "[Junk]" + + def __add__ (self, other): + return self + + def __radd__ (self, other): + return self + + def __sub__ (self, other): + return self + + def __rsub__ (self, other): + return self diff --git a/infernal.py b/infernal.py index 6989c7c..dc1026b 100644 --- a/infernal.py +++ b/infernal.py @@ -2,8 +2,9 @@ import sys import getopt -from Emulator import Emulator +from Emulator import Emulator, CodeParseException from TikzPainter import TikzPainter +from Junk import Junk, JunkComparisonException if __name__ == "__main__": pass diff --git a/opcodes.py b/opcodes.py index 48d0e2f..aa77aab 100644 --- a/opcodes.py +++ b/opcodes.py @@ -45,33 +45,27 @@ def comp(emu, val1, val2): @add_opcode("jg") def jg(emu, label): - if emu.status["g"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, g=True) @add_opcode("jl") def jl(emu, label): - if emu.status["l"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, l=True) @add_opcode("je") def je(emu, label): - if emu.status["e"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, e=True) @add_opcode("jge") def jge(emu, label): - if emu.status["g"] or emu.status["e"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, "or", g=True, e=True) @add_opcode("jle") def jle(emu, label): - if emu.status["l"] or emu.status["e"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, "or", l=True, e=True) @add_opcode("jne") def jne(emu, label): - if not emu.status["e"]: - emu.registers['%rip'] = emu.labels[label] + emu.jump(label, e=False) # Unconditional Jumping diff --git a/tests/tests.py b/tests/tests.py index 3603d64..4822a3c 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,5 +1,7 @@ -import os,sys,inspect +import os, sys, inspect +import traceback sys.path.insert(1, os.path.join(sys.path[0], '..')) + import infernal ################################################################################ @@ -9,16 +11,6 @@ tests = [] def add_test(name, result, register, code): tests.append((name, result, register, code)) -def execute_test (register, code): - emu = infernal.Emulator(code) - emu.setStack("junk...", "calling eip") - emu.setRegs( rip = 0, rbp = 'old bp') - - for line_nr in emu: - pass - - return emu.getVal(register) - def printf (str, *args): print(str.format(*args)) @@ -29,15 +21,32 @@ def execute_tests(): error_tests = 0 for name, result, register, code in tests: total_tests += 1 + line_nr = None try: - output = execute_test(register, code) + emu = infernal.Emulator(code) + emu.setStack("junk...", "calling eip") + emu.setRegs( rip = 0, rbp = 'old bp') + except infernal.CodeParseException as e: + error_tests += 1 + printf("Encountered error when parsing {}, at line {}: {}", + name, e.line_nr, e.str) + try: + for line_nr in emu: + pass + if isinstance(result, BaseException): + printf("Error should have happened in {}, but did not", name) + failed_tests += 1 + output = emu.getVal(register) if output != result: failed_tests += 1 printf("Failed in {}. {} was {}, should be {}", - name, register, result, output) + name, register, result, output) except BaseException as e: - error_tests += 1 - printf("Encountered error in {}: {}",name,e) + if not isinstance(e, result): + error_tests += 1 + printf("Encountered error in {}, at operation {}: {}", + name, emu.getVal('%rip'), e) + traceback.print_exc() printf("Tests done! {}/{}.", total_tests - failed_tests - error_tests, total_tests) printf("{} failed, and {} encountered a python error", @@ -60,6 +69,56 @@ movq $20, %rax addq %rax, %rsi """) +################################################################################ + +add_test("invalid comparison 1", infernal.JunkComparisonException, "None", """ +start: movq $100, %rsp # Set stack pointer to a random position. + popq %rsi # Move a Junk value into %rsi + cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp + # virtual register. + jg start # Attempt to do a jump to the start, if (Junk-10)>0, + # which makes no sense, and thus throws an error. +""") + +add_test("invalid addition 1", infernal.JunkComparisonException, "None", """ +start: movq $100, %rsp # Set stack pointer to a random position. + popq %rsi # Move a Junk value into %rsi + addq %rsi, %rsp # Adds Junk to 101, which produces Junk. + cmpq $10, %rsp # Do a Junk comparison, which triggers the `i` comp + # virtual register. + jg start # Attempt to do a jump to the start, if (Junk-10)>0, + # which makes no sense, and thus throws an error. +""") + +add_test("invalid addition 2", infernal.JunkComparisonException, "None", """ +start: movq $100, %rsp # Set stack pointer to a random position. + popq %rsi # Move a Junk value into %rsi + addq %rsp, %rsi # Adds 101 to Junk, which produces Junk. + cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp + # virtual register. + jg start # Attempt to do a jump to the start, if (Junk-10)>0, + # which makes no sense, and thus throws an error. +""") + +add_test("invalid subtraction 1", infernal.JunkComparisonException, "None", """ +start: movq $100, %rsp # Set stack pointer to a random position. + popq %rsi # Move a Junk value into %rsi + subq %rsi, %rsp # Adds Junk to 101, which produces Junk. + cmpq $10, %rsp # Do a Junk comparison, which triggers the `i` comp + # virtual register. + jg start # Attempt to do a jump to the start, if (Junk-10)>0, + # which makes no sense, and thus throws an error. +""") + +add_test("invalid subtraction 2", infernal.JunkComparisonException, "None", """ +start: movq $100, %rsp # Set stack pointer to a random position. + popq %rsi # Move a Junk value into %rsi + subq %rsp, %rsi # Adds 101 to Junk, which produces Junk. + cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp + # virtual register. + jg start # Attempt to do a jump to the start, if (Junk-10)>0, + # which makes no sense, and thus throws an error. +""") ################################################################################