#!/usr/bin/python

import argparse, datetime, re, subprocess, sys, time

parser = argparse.ArgumentParser(description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")

parser.add_argument('--arch', required=True, action='store', help='The architecture whose disassembler is to be tested')
parser.add_argument('--bytes', required=True, action='store', type=int, help='The byte width of instructions for that architecture')
parser.add_argument('--random', required=False, action='store_true', help='Enables non-sequential testing')
parser.add_argument('--start', required=False, action='store', type=int, help='The first instruction value to test')
parser.add_argument('--skip', required=False, action='store', type=int, help='The interval between instructions to test')
parser.add_argument('--log', required=False, action='store', help='A log file to write the most recent instruction being tested')
parser.add_argument('--time', required=False, action='store_true', help='Every 100,000 instructions, print an ETA to standard out')
parser.add_argument('--lldb', required=False, action='store', help='The path to LLDB.framework, if LLDB should be overridden')

arguments = sys.argv[1:]

arg_ns = parser.parse_args(arguments)

def AddLLDBToSysPathOnMacOSX():
    def GetLLDBFrameworkPath():
        lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
        re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
        if re_result == None:
            return None
        xcode_contents_path = re_result.group(1)
        return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
    
    lldb_framework_path = GetLLDBFrameworkPath()
    
    if lldb_framework_path == None:
        print "Couldn't find LLDB.framework"
        sys.exit(-1)
    
    sys.path.append(lldb_framework_path + "/Resources/Python")

if arg_ns.lldb == None:
    AddLLDBToSysPathOnMacOSX()
else:
    sys.path.append(arg_ns.lldb + "/Resources/Python")

import lldb

debugger = lldb.SBDebugger.Create()

if debugger.IsValid() == False:
    print "Couldn't create an SBDebugger"
    sys.exit(-1)

target = debugger.CreateTargetWithFileAndArch(None, arg_ns.arch)

if target.IsValid() == False:
    print "Couldn't create an SBTarget for architecture " + arg_ns.arch
    sys.exit(-1)

def ResetLogFile(log_file):
    if log_file != sys.stdout:
        log_file.seek(0)

def PrintByteArray(log_file, byte_array):
    for byte in byte_array:
        print >>log_file, hex(byte) + " ",
    print >>log_file
    
class SequentialInstructionProvider:
    def __init__(self, byte_width, log_file, start=0, skip=1):
        self.m_byte_width = byte_width
        self.m_log_file = log_file
        self.m_start = start
        self.m_skip = skip
        self.m_value = start
        self.m_last = (1 << (byte_width * 8)) - 1
    def PrintCurrentState(self, ret):
        ResetLogFile(self.m_log_file)
        print >>self.m_log_file, self.m_value
        PrintByteArray(self.m_log_file, ret)
    def GetNextInstruction(self):
        if self.m_value > self.m_last:
            return None
        ret = bytearray(self.m_byte_width)
        for i in range(self.m_byte_width):
            ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255 
        self.PrintCurrentState(ret)
        self.m_value += self.m_skip
        return ret
    def GetNumInstructions(self):
        return (self.m_last - self.m_start) / self.m_skip
    def __iter__(self):
        return self
    def next(self):
        ret = self.GetNextInstruction()
        if ret == None:
            raise StopIteration
        return ret

class RandomInstructionProvider:
    def __init__(self, byte_width, log_file):
        self.m_byte_width = byte_width
        self.m_log_file = log_file
        self.m_random_file = open("/dev/random", 'r')
    def PrintCurrentState(self, ret):
        ResetLogFile(self.m_log_file)
        PrintByteArray(self.m_log_file, ret)
    def GetNextInstruction(self):
        ret = bytearray(self.m_byte_width)
        for i in range(self.m_byte_width):
            ret[i] = self.m_random_file.read(1)
        self.PrintCurrentState(ret)
        return ret
    def __iter__(self):
        return self
    def next(self):
        ret = self.GetNextInstruction()
        if ret == None:
            raise StopIteration
        return ret

log_file = None

def GetProviderWithArguments(args):
    global log_file
    if args.log != None:
        log_file = open(args.log, 'w')
    else:
        log_file = sys.stdout
    instruction_provider = None
    if args.random == True:
        instruction_provider = RandomInstructionProvider(args.bytes, log_file)
    else:
        start = 0
        skip = 1
        if args.start != None:
            start = args.start
        if args.skip != None:
            skip = args.skip
        instruction_provider = SequentialInstructionProvider(args.bytes, log_file, start, skip)
    return instruction_provider

instruction_provider = GetProviderWithArguments(arg_ns)

fake_address = lldb.SBAddress()

actually_time = arg_ns.time and not arg_ns.random

if actually_time:
    num_instructions_logged = 0
    total_num_instructions = instruction_provider.GetNumInstructions()
    start_time = time.time()

for inst_bytes in instruction_provider:
    if actually_time:
        if (num_instructions_logged != 0) and (num_instructions_logged % 100000 == 0):
            curr_time = time.time()
            elapsed_time = curr_time - start_time
            remaining_time = float(total_num_instructions - num_instructions_logged) * (float(elapsed_time) / float(num_instructions_logged))
            print str(datetime.timedelta(seconds=remaining_time))
        num_instructions_logged = num_instructions_logged + 1
    inst_list = target.GetInstructions(fake_address, inst_bytes)
    if not inst_list.IsValid():
        print >>log_file, "Invalid instruction list"
        continue
    inst = inst_list.GetInstructionAtIndex(0)
    if not inst.IsValid():
        print >>log_file, "Invalid instruction"
        continue
    instr_output_stream = lldb.SBStream()
    inst.GetDescription(instr_output_stream)
    print >>log_file, instr_output_stream.GetData()
