blob: 2c20ffb923696036136992162d534fccbe1485b0 [file] [log] [blame]
Sean Callanand1817302012-04-06 00:04:36 +00001#!/usr/bin/python
2
Kate Stoneb9c1b512016-09-06 20:57:50 +00003import argparse
4import datetime
5import re
6import subprocess
7import sys
8import time
Sean Callanand1817302012-04-06 00:04:36 +00009
Kate Stoneb9c1b512016-09-06 20:57:50 +000010parser = argparse.ArgumentParser(
11 description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")
Sean Callananf5c87882012-04-14 01:06:06 +000012
Kate Stoneb9c1b512016-09-06 20:57:50 +000013parser.add_argument(
14 '--arch',
15 required=True,
16 action='store',
17 help='The architecture whose disassembler is to be tested')
18parser.add_argument(
19 '--bytes',
20 required=True,
21 action='store',
22 type=int,
23 help='The byte width of instructions for that architecture')
24parser.add_argument(
25 '--random',
26 required=False,
27 action='store_true',
28 help='Enables non-sequential testing')
29parser.add_argument(
30 '--start',
31 required=False,
32 action='store',
33 type=int,
34 help='The first instruction value to test')
35parser.add_argument(
36 '--skip',
37 required=False,
38 action='store',
39 type=int,
40 help='The interval between instructions to test')
41parser.add_argument(
42 '--log',
43 required=False,
44 action='store',
45 help='A log file to write the most recent instruction being tested')
46parser.add_argument(
47 '--time',
48 required=False,
49 action='store_true',
50 help='Every 100,000 instructions, print an ETA to standard out')
51parser.add_argument(
52 '--lldb',
53 required=False,
54 action='store',
55 help='The path to LLDB.framework, if LLDB should be overridden')
Sean Callananf5c87882012-04-14 01:06:06 +000056
57arguments = sys.argv[1:]
58
59arg_ns = parser.parse_args(arguments)
60
Kate Stoneb9c1b512016-09-06 20:57:50 +000061
Sean Callanand1817302012-04-06 00:04:36 +000062def AddLLDBToSysPathOnMacOSX():
63 def GetLLDBFrameworkPath():
64 lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
65 re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 if re_result is None:
Sean Callanand1817302012-04-06 00:04:36 +000067 return None
68 xcode_contents_path = re_result.group(1)
69 return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
Kate Stoneb9c1b512016-09-06 20:57:50 +000070
Sean Callanand1817302012-04-06 00:04:36 +000071 lldb_framework_path = GetLLDBFrameworkPath()
Kate Stoneb9c1b512016-09-06 20:57:50 +000072
73 if lldb_framework_path is None:
Sean Callanand1817302012-04-06 00:04:36 +000074 print "Couldn't find LLDB.framework"
75 sys.exit(-1)
Kate Stoneb9c1b512016-09-06 20:57:50 +000076
Sean Callanand1817302012-04-06 00:04:36 +000077 sys.path.append(lldb_framework_path + "/Resources/Python")
78
Kate Stoneb9c1b512016-09-06 20:57:50 +000079if arg_ns.lldb is None:
Sean Callananf5c87882012-04-14 01:06:06 +000080 AddLLDBToSysPathOnMacOSX()
81else:
82 sys.path.append(arg_ns.lldb + "/Resources/Python")
Sean Callanand1817302012-04-06 00:04:36 +000083
84import lldb
85
Sean Callanand1817302012-04-06 00:04:36 +000086debugger = lldb.SBDebugger.Create()
87
88if debugger.IsValid() == False:
89 print "Couldn't create an SBDebugger"
90 sys.exit(-1)
91
92target = debugger.CreateTargetWithFileAndArch(None, arg_ns.arch)
93
94if target.IsValid() == False:
95 print "Couldn't create an SBTarget for architecture " + arg_ns.arch
96 sys.exit(-1)
97
Kate Stoneb9c1b512016-09-06 20:57:50 +000098
Sean Callananceabd2d2012-04-06 20:53:23 +000099def ResetLogFile(log_file):
100 if log_file != sys.stdout:
101 log_file.seek(0)
Sean Callananceabd2d2012-04-06 20:53:23 +0000102
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103
Sean Callananceabd2d2012-04-06 20:53:23 +0000104def PrintByteArray(log_file, byte_array):
105 for byte in byte_array:
106 print >>log_file, hex(byte) + " ",
107 print >>log_file
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108
109
Sean Callanand1817302012-04-06 00:04:36 +0000110class SequentialInstructionProvider:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111
Sean Callananceabd2d2012-04-06 20:53:23 +0000112 def __init__(self, byte_width, log_file, start=0, skip=1):
Sean Callanand1817302012-04-06 00:04:36 +0000113 self.m_byte_width = byte_width
Sean Callananceabd2d2012-04-06 20:53:23 +0000114 self.m_log_file = log_file
Sean Callanand1817302012-04-06 00:04:36 +0000115 self.m_start = start
116 self.m_skip = skip
117 self.m_value = start
118 self.m_last = (1 << (byte_width * 8)) - 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119
Sean Callananceabd2d2012-04-06 20:53:23 +0000120 def PrintCurrentState(self, ret):
121 ResetLogFile(self.m_log_file)
122 print >>self.m_log_file, self.m_value
123 PrintByteArray(self.m_log_file, ret)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124
Sean Callanand1817302012-04-06 00:04:36 +0000125 def GetNextInstruction(self):
Sean Callanand1817302012-04-06 00:04:36 +0000126 if self.m_value > self.m_last:
127 return None
128 ret = bytearray(self.m_byte_width)
129 for i in range(self.m_byte_width):
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130 ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255
Sean Callananceabd2d2012-04-06 20:53:23 +0000131 self.PrintCurrentState(ret)
Sean Callanand1817302012-04-06 00:04:36 +0000132 self.m_value += self.m_skip
133 return ret
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134
Sean Callananceabd2d2012-04-06 20:53:23 +0000135 def GetNumInstructions(self):
Sean Callanan11064342012-04-06 23:00:31 +0000136 return (self.m_last - self.m_start) / self.m_skip
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137
Sean Callanand1817302012-04-06 00:04:36 +0000138 def __iter__(self):
139 return self
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140
Sean Callanand1817302012-04-06 00:04:36 +0000141 def next(self):
142 ret = self.GetNextInstruction()
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 if ret is None:
Sean Callanand1817302012-04-06 00:04:36 +0000144 raise StopIteration
145 return ret
146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147
Sean Callanand1817302012-04-06 00:04:36 +0000148class RandomInstructionProvider:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149
Sean Callananceabd2d2012-04-06 20:53:23 +0000150 def __init__(self, byte_width, log_file):
Sean Callanand1817302012-04-06 00:04:36 +0000151 self.m_byte_width = byte_width
Sean Callananceabd2d2012-04-06 20:53:23 +0000152 self.m_log_file = log_file
Sean Callanand1817302012-04-06 00:04:36 +0000153 self.m_random_file = open("/dev/random", 'r')
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154
Sean Callananceabd2d2012-04-06 20:53:23 +0000155 def PrintCurrentState(self, ret):
156 ResetLogFile(self.m_log_file)
157 PrintByteArray(self.m_log_file, ret)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158
Sean Callanand1817302012-04-06 00:04:36 +0000159 def GetNextInstruction(self):
160 ret = bytearray(self.m_byte_width)
161 for i in range(self.m_byte_width):
162 ret[i] = self.m_random_file.read(1)
Sean Callananceabd2d2012-04-06 20:53:23 +0000163 self.PrintCurrentState(ret)
Sean Callanand1817302012-04-06 00:04:36 +0000164 return ret
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165
Sean Callanand1817302012-04-06 00:04:36 +0000166 def __iter__(self):
167 return self
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168
Sean Callanand1817302012-04-06 00:04:36 +0000169 def next(self):
170 ret = self.GetNextInstruction()
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171 if ret is None:
Sean Callanand1817302012-04-06 00:04:36 +0000172 raise StopIteration
173 return ret
174
Sean Callananceabd2d2012-04-06 20:53:23 +0000175log_file = None
176
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177
Sean Callanand1817302012-04-06 00:04:36 +0000178def GetProviderWithArguments(args):
Sean Callananceabd2d2012-04-06 20:53:23 +0000179 global log_file
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 if args.log is not None:
Sean Callananceabd2d2012-04-06 20:53:23 +0000181 log_file = open(args.log, 'w')
182 else:
183 log_file = sys.stdout
Sean Callanand1817302012-04-06 00:04:36 +0000184 instruction_provider = None
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 if args.random:
Sean Callananceabd2d2012-04-06 20:53:23 +0000186 instruction_provider = RandomInstructionProvider(args.bytes, log_file)
Sean Callanand1817302012-04-06 00:04:36 +0000187 else:
188 start = 0
189 skip = 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190 if args.start is not None:
Sean Callanand1817302012-04-06 00:04:36 +0000191 start = args.start
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192 if args.skip is not None:
Sean Callanand1817302012-04-06 00:04:36 +0000193 skip = args.skip
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194 instruction_provider = SequentialInstructionProvider(
195 args.bytes, log_file, start, skip)
Sean Callanand1817302012-04-06 00:04:36 +0000196 return instruction_provider
197
198instruction_provider = GetProviderWithArguments(arg_ns)
199
200fake_address = lldb.SBAddress()
201
Sean Callananceabd2d2012-04-06 20:53:23 +0000202actually_time = arg_ns.time and not arg_ns.random
203
204if actually_time:
205 num_instructions_logged = 0
206 total_num_instructions = instruction_provider.GetNumInstructions()
207 start_time = time.time()
208
Sean Callanand1817302012-04-06 00:04:36 +0000209for inst_bytes in instruction_provider:
Sean Callananceabd2d2012-04-06 20:53:23 +0000210 if actually_time:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000211 if (num_instructions_logged != 0) and (
212 num_instructions_logged % 100000 == 0):
Sean Callananceabd2d2012-04-06 20:53:23 +0000213 curr_time = time.time()
214 elapsed_time = curr_time - start_time
Kate Stoneb9c1b512016-09-06 20:57:50 +0000215 remaining_time = float(
216 total_num_instructions - num_instructions_logged) * (
217 float(elapsed_time) / float(num_instructions_logged))
Sean Callananceabd2d2012-04-06 20:53:23 +0000218 print str(datetime.timedelta(seconds=remaining_time))
219 num_instructions_logged = num_instructions_logged + 1
Sean Callanand1817302012-04-06 00:04:36 +0000220 inst_list = target.GetInstructions(fake_address, inst_bytes)
221 if not inst_list.IsValid():
Sean Callananceabd2d2012-04-06 20:53:23 +0000222 print >>log_file, "Invalid instruction list"
Sean Callanand1817302012-04-06 00:04:36 +0000223 continue
224 inst = inst_list.GetInstructionAtIndex(0)
225 if not inst.IsValid():
Sean Callananceabd2d2012-04-06 20:53:23 +0000226 print >>log_file, "Invalid instruction"
Sean Callanand1817302012-04-06 00:04:36 +0000227 continue
228 instr_output_stream = lldb.SBStream()
229 inst.GetDescription(instr_output_stream)
Sean Callananceabd2d2012-04-06 20:53:23 +0000230 print >>log_file, instr_output_stream.GetData()