blob: ac6b6ff5b4822a4210ff30262cc6e84b2e3729d7 [file] [log] [blame]
Sean Callanand1817302012-04-06 00:04:36 +00001#!/usr/bin/python
2
Sean Callananceabd2d2012-04-06 20:53:23 +00003import argparse, datetime, re, subprocess, sys, time
Sean Callanand1817302012-04-06 00:04:36 +00004
5def AddLLDBToSysPathOnMacOSX():
6 def GetLLDBFrameworkPath():
7 lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
8 re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
9 if re_result == None:
10 return None
11 xcode_contents_path = re_result.group(1)
12 return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
13
14 lldb_framework_path = GetLLDBFrameworkPath()
15
16 if lldb_framework_path == None:
17 print "Couldn't find LLDB.framework"
18 sys.exit(-1)
19
20 sys.path.append(lldb_framework_path + "/Resources/Python")
21
22AddLLDBToSysPathOnMacOSX()
23
24import lldb
25
Sean Callanand1817302012-04-06 00:04:36 +000026parser = argparse.ArgumentParser(description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")
27
28parser.add_argument('--arch', required=True, action='store', help='The architecture whose disassembler is to be tested')
29parser.add_argument('--bytes', required=True, action='store', type=int, help='The byte width of instructions for that architecture')
30parser.add_argument('--random', required=False, action='store_true', help='Enables non-sequential testing')
31parser.add_argument('--start', required=False, action='store', type=int, help='The first instruction value to test')
32parser.add_argument('--skip', required=False, action='store', type=int, help='The interval between instructions to test')
Sean Callananceabd2d2012-04-06 20:53:23 +000033parser.add_argument('--log', required=False, action='store', help='A log file to write the most recent instruction being tested')
34parser.add_argument('--time', required=False, action='store_true', help='Every 100,000 instructions, print an ETA to standard out')
Sean Callanand1817302012-04-06 00:04:36 +000035
36arguments = sys.argv[1:]
37
38arg_ns = parser.parse_args(arguments)
39
40debugger = lldb.SBDebugger.Create()
41
42if debugger.IsValid() == False:
43 print "Couldn't create an SBDebugger"
44 sys.exit(-1)
45
46target = debugger.CreateTargetWithFileAndArch(None, arg_ns.arch)
47
48if target.IsValid() == False:
49 print "Couldn't create an SBTarget for architecture " + arg_ns.arch
50 sys.exit(-1)
51
Sean Callananceabd2d2012-04-06 20:53:23 +000052def ResetLogFile(log_file):
53 if log_file != sys.stdout:
54 log_file.seek(0)
Sean Callananceabd2d2012-04-06 20:53:23 +000055
56def PrintByteArray(log_file, byte_array):
57 for byte in byte_array:
58 print >>log_file, hex(byte) + " ",
59 print >>log_file
60
Sean Callanand1817302012-04-06 00:04:36 +000061class SequentialInstructionProvider:
Sean Callananceabd2d2012-04-06 20:53:23 +000062 def __init__(self, byte_width, log_file, start=0, skip=1):
Sean Callanand1817302012-04-06 00:04:36 +000063 self.m_byte_width = byte_width
Sean Callananceabd2d2012-04-06 20:53:23 +000064 self.m_log_file = log_file
Sean Callanand1817302012-04-06 00:04:36 +000065 self.m_start = start
66 self.m_skip = skip
67 self.m_value = start
68 self.m_last = (1 << (byte_width * 8)) - 1
Sean Callananceabd2d2012-04-06 20:53:23 +000069 def PrintCurrentState(self, ret):
70 ResetLogFile(self.m_log_file)
71 print >>self.m_log_file, self.m_value
72 PrintByteArray(self.m_log_file, ret)
Sean Callanand1817302012-04-06 00:04:36 +000073 def GetNextInstruction(self):
Sean Callanand1817302012-04-06 00:04:36 +000074 if self.m_value > self.m_last:
75 return None
76 ret = bytearray(self.m_byte_width)
77 for i in range(self.m_byte_width):
78 ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255
Sean Callananceabd2d2012-04-06 20:53:23 +000079 self.PrintCurrentState(ret)
Sean Callanand1817302012-04-06 00:04:36 +000080 self.m_value += self.m_skip
81 return ret
Sean Callananceabd2d2012-04-06 20:53:23 +000082 def GetNumInstructions(self):
83 return self.m_last / self.m_skip
Sean Callanand1817302012-04-06 00:04:36 +000084 def __iter__(self):
85 return self
86 def next(self):
87 ret = self.GetNextInstruction()
88 if ret == None:
89 raise StopIteration
90 return ret
91
92class RandomInstructionProvider:
Sean Callananceabd2d2012-04-06 20:53:23 +000093 def __init__(self, byte_width, log_file):
Sean Callanand1817302012-04-06 00:04:36 +000094 self.m_byte_width = byte_width
Sean Callananceabd2d2012-04-06 20:53:23 +000095 self.m_log_file = log_file
Sean Callanand1817302012-04-06 00:04:36 +000096 self.m_random_file = open("/dev/random", 'r')
Sean Callananceabd2d2012-04-06 20:53:23 +000097 def PrintCurrentState(self, ret):
98 ResetLogFile(self.m_log_file)
99 PrintByteArray(self.m_log_file, ret)
Sean Callanand1817302012-04-06 00:04:36 +0000100 def GetNextInstruction(self):
101 ret = bytearray(self.m_byte_width)
102 for i in range(self.m_byte_width):
103 ret[i] = self.m_random_file.read(1)
Sean Callananceabd2d2012-04-06 20:53:23 +0000104 self.PrintCurrentState(ret)
Sean Callanand1817302012-04-06 00:04:36 +0000105 return ret
106 def __iter__(self):
107 return self
108 def next(self):
109 ret = self.GetNextInstruction()
110 if ret == None:
111 raise StopIteration
112 return ret
113
Sean Callananceabd2d2012-04-06 20:53:23 +0000114log_file = None
115
Sean Callanand1817302012-04-06 00:04:36 +0000116def GetProviderWithArguments(args):
Sean Callananceabd2d2012-04-06 20:53:23 +0000117 global log_file
118 if args.log != None:
119 log_file = open(args.log, 'w')
120 else:
121 log_file = sys.stdout
Sean Callanand1817302012-04-06 00:04:36 +0000122 instruction_provider = None
123 if args.random == True:
Sean Callananceabd2d2012-04-06 20:53:23 +0000124 instruction_provider = RandomInstructionProvider(args.bytes, log_file)
Sean Callanand1817302012-04-06 00:04:36 +0000125 else:
126 start = 0
127 skip = 1
128 if args.start != None:
129 start = args.start
130 if args.skip != None:
131 skip = args.skip
Sean Callananceabd2d2012-04-06 20:53:23 +0000132 instruction_provider = SequentialInstructionProvider(args.bytes, log_file, start, skip)
Sean Callanand1817302012-04-06 00:04:36 +0000133 return instruction_provider
134
135instruction_provider = GetProviderWithArguments(arg_ns)
136
137fake_address = lldb.SBAddress()
138
Sean Callananceabd2d2012-04-06 20:53:23 +0000139actually_time = arg_ns.time and not arg_ns.random
140
141if actually_time:
142 num_instructions_logged = 0
143 total_num_instructions = instruction_provider.GetNumInstructions()
144 start_time = time.time()
145
Sean Callanand1817302012-04-06 00:04:36 +0000146for inst_bytes in instruction_provider:
Sean Callananceabd2d2012-04-06 20:53:23 +0000147 if actually_time:
148 if (num_instructions_logged != 0) and (num_instructions_logged % 100000 == 0):
149 curr_time = time.time()
150 elapsed_time = curr_time - start_time
151 remaining_time = float(total_num_instructions - num_instructions_logged) * (float(elapsed_time) / float(num_instructions_logged))
152 print str(datetime.timedelta(seconds=remaining_time))
153 num_instructions_logged = num_instructions_logged + 1
Sean Callanand1817302012-04-06 00:04:36 +0000154 inst_list = target.GetInstructions(fake_address, inst_bytes)
155 if not inst_list.IsValid():
Sean Callananceabd2d2012-04-06 20:53:23 +0000156 print >>log_file, "Invalid instruction list"
Sean Callanand1817302012-04-06 00:04:36 +0000157 continue
158 inst = inst_list.GetInstructionAtIndex(0)
159 if not inst.IsValid():
Sean Callananceabd2d2012-04-06 20:53:23 +0000160 print >>log_file, "Invalid instruction"
Sean Callanand1817302012-04-06 00:04:36 +0000161 continue
162 instr_output_stream = lldb.SBStream()
163 inst.GetDescription(instr_output_stream)
Sean Callananceabd2d2012-04-06 20:53:23 +0000164 print >>log_file, instr_output_stream.GetData()