1
0

Added Junk value, for which all operations are

defined to produce junk.
Any comparison involving junk triggers the i status register.
Any conditional jump triggered when the i register is true,
triggers a python level exception.
This commit is contained in:
Jon Michael Aanes 2015-12-19 16:55:14 +01:00
parent 6d7de5ae75
commit 8b146efe68
5 changed files with 145 additions and 33 deletions

View File

@ -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"] = val1<val2
self.status["e"] = val1==val2
self.status["i"] = False
def changedRegisters (self, *args):
for reg, val in args:
@ -63,7 +76,7 @@ class Emulator:
def processSourceLine(self, line_text, index):
tokens = re.findall(r'[^\s,]+', line_text)
if len(tokens) <= 0:
if len(tokens) <= 0 or tokens[0][0] == '#':
return index
if tokens[0][-1] == ':':
self.labels[tokens[0][:-1]] = index
@ -96,6 +109,21 @@ class Emulator:
self.registers['%rsp'] += 1
return temp
def jump (self, label, cond_op="or", **conditions):
if len(conditions)>0 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]

27
Junk.py Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,7 @@
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)
except BaseException as e:
if not isinstance(e, result):
error_tests += 1
printf("Encountered error in {}: {}",name,e)
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.
""")
################################################################################