## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## stage0 is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with stage0. If not, see .
import subprocess
import ctypes
import re
import sys, getopt
vm = ctypes.CDLL('./libvm.so')
vm.initialize_lilith.argtype = (ctypes.c_uint, ctypes.c_uint)
vm.get_memory.argtype = ctypes.c_uint
vm.get_memory.restype = ctypes.c_char_p
vm.step_lilith.restype = ctypes.c_uint
vm.set_register.argtype = (ctypes.c_uint, ctypes.c_uint)
vm.set_memory.argtype = (ctypes.c_uint, ctypes.c_ubyte)
vm.get_register.argtype = ctypes.c_uint
vm.get_register.restype = ctypes.c_uint
POSIX_MODE = False
def Reset_lilith():
global Memory_Size
if 0 <= Memory_Size < 1024:
unit = 'Bytes'
chunks = Memory_Size
elif 1024 <= Memory_Size < (1024 * 1024):
unit = 'KB'
chunks = Memory_Size / 1024
elif (1024 * 1024) <= Memory_Size < (1024 * 1024 * 1024):
unit = 'MB'
chunks = Memory_Size / (1024 * 1024)
else:
unit = 'GB'
chunks = Memory_Size / (1024 * 1024 * 1024)
print("Current Memory Size is: " + str(chunks) + unit)
vm.initialize_lilith(Memory_Size, POSIX_MODE)
global Current_IP
Current_IP = 0
global Watchpoints
Watchpoints = {0}
global ROM_Name
size = vm.load_lilith(ctypes.create_string_buffer(ROM_Name.encode('ascii')))
print ("Size of loaded ROM image: " + str(size) + " bytes\n")
if(POSIX_MODE):
Set_Register(15, size)
def Step_lilith():
global Current_IP
Current_IP = vm.step_lilith()
global Count
Count = Count + 1
return
def Set_Memory(address, value):
vm.set_memory(address, value)
return
def Set_Register(register, value):
vm.set_register(register, value)
return
def returnPage():
return get_header() + (vm.get_memory(Current_Page)).decode('utf-8') + get_spacer1() + get_registers(0) + get_registers(9) + get_spacer2() + get_Window_shortcut() + get_disassembled() + get_footer()
hexlookup = { 0 : '0', 1 : '1', 2 : '2', 3 : '3', 4 : '4', 5 : '5', 6 : '6', 7 : '7', 8 : '8', 9 : '9', 10 : 'A', 11 : 'B', 12 : 'C', 13 : 'D', 14 : 'E', 15 : 'F' }
def formatByte(a):
first = a >> 4
second = a % 16
return str(hexlookup[first]+hexlookup[second])
def formatAddress(a):
first = a >> 24
second = (a % 16777216) >> 16
third = (a % 65536) >> 8
fourth = a % 256
myreturn = formatByte(first) + formatByte(second) + formatByte(third) + formatByte(fourth)
return myreturn[:-1] + "x"
def formatRegister(a):
first = a >> 24
second = (a % 16777216) >> 16
third = (a % 65536) >> 8
fourth = a % 256
return formatByte(first) + formatByte(second) + formatByte(third) + formatByte(fourth)
def get_header():
return """
Knight CPU Debugger
Index
0
1
2
3
4
5
6
7
8
8
A
B
C
D
E
F
"""
def get_spacer1():
return """
"""
def get_registers(index):
temp = """
Register
Value
Name
"""
if (0 == index):
for i in range(0,9):
temp = temp + """
"""
for line in f:
pieces = re.split(r'\t+', line)
i = int(pieces[0], 16)
if (i < Current_IP):
temp = temp + ""
elif (i == Current_IP):
temp = temp + """
""" + pieces[0] + "
" + pieces[1] + "
" + pieces[2] + "
\n"
elif i in Watchpoints:
temp = temp + """
""" + pieces[0] + "
" + pieces[1] + "
" + pieces[2] + "
\n"
else:
temp = temp + "
" + pieces[0] + "
" + pieces[1] + "
" + pieces[2] + "
\n"
f.close()
return temp + "
"
def get_footer():
return """
"""
def main(argv):
global Debug_Point
help_string = 'Knight.py --ROM=$NAME [--DEBUG=$NUMBER] [--WINDOW=$NUMBER] [--MEMORY=$SIZE]\n'
try:
opts, args = getopt.getopt(argv,"R:D:W:M:P:",["ROM=","DEBUG=","WINDOW=", "MEMORY=", "POSIX-MODE"])
except getopt.GetoptError:
print (help_string)
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print (help_string)
sys.exit()
elif opt in ("-R", "--ROM"):
global ROM_Name
ROM_Name = arg
elif opt in ("-D", "--DEBUG"):
global Debug_Point
Debug_Point = int(arg)
elif opt in ("-W", "--WINDOW"):
global Current_Page
Current_Page = int(arg, 16)
elif opt in ("-M", "--MEMORY"):
global Memory_Size
if arg.endswith('K'):
Memory_Size = (int(arg[:-1]) * 1024)
elif arg.endswith('M'):
Memory_Size = (int(arg[:-1]) * 1024 * 1024)
elif arg.endswith('G'):
Memory_Size = (int(arg[:-1]) * 1024 * 1024 * 1024)
elif opt in ("-P", "--POSIX-MODE"):
global POSIX_MODE
POSIX_MODE = True
subprocess.call("./bin/dis " + ROM_Name + " >| z_disassembled", shell=True)
Reset_lilith()
Current_IP = 0
Memory_Size = 16 * 1024
Current_Page = 0
Watchpoints = {0}
Count=0
Debug_Point = 0
ROM_Name = "rom"