#!/usr/bin/env python

import argparse
import datetime
import re
import subprocess
import sys
import 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 is 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 is None:
        print("Couldn't find LLDB.framework")
        sys.exit(-1)

    sys.path.append(lldb_framework_path + "/Resources/Python")


if arg_ns.lldb is 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(hex(byte) + " ", end=" ", file=log_file)
    print(file=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_value, file=self.m_log_file)
        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 is 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 is None:
            raise StopIteration
        return ret


log_file = None


def GetProviderWithArguments(args):
    global log_file
    if args.log is not None:
        log_file = open(args.log, "w")
    else:
        log_file = sys.stdout
    instruction_provider = None
    if args.random:
        instruction_provider = RandomInstructionProvider(args.bytes, log_file)
    else:
        start = 0
        skip = 1
        if args.start is not None:
            start = args.start
        if args.skip is not 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("Invalid instruction list", file=log_file)
        continue
    inst = inst_list.GetInstructionAtIndex(0)
    if not inst.IsValid():
        print("Invalid instruction", file=log_file)
        continue
    instr_output_stream = lldb.SBStream()
    inst.GetDescription(instr_output_stream)
    print(instr_output_stream.GetData(), file=log_file)
