10 parser
= argparse
.ArgumentParser(
11 description
="Run an exhaustive test of the LLDB disassembler for a specific architecture."
18 help="The architecture whose disassembler is to be tested",
25 help="The byte width of instructions for that architecture",
31 help="Enables non-sequential testing",
38 help="The first instruction value to test",
45 help="The interval between instructions to test",
51 help="A log file to write the most recent instruction being tested",
57 help="Every 100,000 instructions, print an ETA to standard out",
63 help="The path to LLDB.framework, if LLDB should be overridden",
66 arguments
= sys
.argv
[1:]
68 arg_ns
= parser
.parse_args(arguments
)
71 def AddLLDBToSysPathOnMacOSX():
72 def GetLLDBFrameworkPath():
73 lldb_path
= subprocess
.check_output(["xcrun", "-find", "lldb"])
74 re_result
= re
.match("(.*)/Developer/usr/bin/lldb", lldb_path
)
77 xcode_contents_path
= re_result
.group(1)
78 return xcode_contents_path
+ "/SharedFrameworks/LLDB.framework"
80 lldb_framework_path
= GetLLDBFrameworkPath()
82 if lldb_framework_path
is None:
83 print("Couldn't find LLDB.framework")
86 sys
.path
.append(lldb_framework_path
+ "/Resources/Python")
89 if arg_ns
.lldb
is None:
90 AddLLDBToSysPathOnMacOSX()
92 sys
.path
.append(arg_ns
.lldb
+ "/Resources/Python")
96 debugger
= lldb
.SBDebugger
.Create()
98 if debugger
.IsValid() == False:
99 print("Couldn't create an SBDebugger")
102 target
= debugger
.CreateTargetWithFileAndArch(None, arg_ns
.arch
)
104 if target
.IsValid() == False:
105 print("Couldn't create an SBTarget for architecture " + arg_ns
.arch
)
109 def ResetLogFile(log_file
):
110 if log_file
!= sys
.stdout
:
114 def PrintByteArray(log_file
, byte_array
):
115 for byte
in byte_array
:
116 print(hex(byte
) + " ", end
=" ", file=log_file
)
120 class SequentialInstructionProvider
:
121 def __init__(self
, byte_width
, log_file
, start
=0, skip
=1):
122 self
.m_byte_width
= byte_width
123 self
.m_log_file
= log_file
127 self
.m_last
= (1 << (byte_width
* 8)) - 1
129 def PrintCurrentState(self
, ret
):
130 ResetLogFile(self
.m_log_file
)
131 print(self
.m_value
, file=self
.m_log_file
)
132 PrintByteArray(self
.m_log_file
, ret
)
134 def GetNextInstruction(self
):
135 if self
.m_value
> self
.m_last
:
137 ret
= bytearray(self
.m_byte_width
)
138 for i
in range(self
.m_byte_width
):
139 ret
[self
.m_byte_width
- (i
+ 1)] = (self
.m_value
>> (i
* 8)) & 255
140 self
.PrintCurrentState(ret
)
141 self
.m_value
+= self
.m_skip
144 def GetNumInstructions(self
):
145 return (self
.m_last
- self
.m_start
) / self
.m_skip
151 ret
= self
.GetNextInstruction()
157 class RandomInstructionProvider
:
158 def __init__(self
, byte_width
, log_file
):
159 self
.m_byte_width
= byte_width
160 self
.m_log_file
= log_file
161 self
.m_random_file
= open("/dev/random", "r")
163 def PrintCurrentState(self
, ret
):
164 ResetLogFile(self
.m_log_file
)
165 PrintByteArray(self
.m_log_file
, ret
)
167 def GetNextInstruction(self
):
168 ret
= bytearray(self
.m_byte_width
)
169 for i
in range(self
.m_byte_width
):
170 ret
[i
] = self
.m_random_file
.read(1)
171 self
.PrintCurrentState(ret
)
178 ret
= self
.GetNextInstruction()
187 def GetProviderWithArguments(args
):
189 if args
.log
is not None:
190 log_file
= open(args
.log
, "w")
192 log_file
= sys
.stdout
193 instruction_provider
= None
195 instruction_provider
= RandomInstructionProvider(args
.bytes
, log_file
)
199 if args
.start
is not None:
201 if args
.skip
is not None:
203 instruction_provider
= SequentialInstructionProvider(
204 args
.bytes
, log_file
, start
, skip
206 return instruction_provider
209 instruction_provider
= GetProviderWithArguments(arg_ns
)
211 fake_address
= lldb
.SBAddress()
213 actually_time
= arg_ns
.time
and not arg_ns
.random
216 num_instructions_logged
= 0
217 total_num_instructions
= instruction_provider
.GetNumInstructions()
218 start_time
= time
.time()
220 for inst_bytes
in instruction_provider
:
222 if (num_instructions_logged
!= 0) and (num_instructions_logged
% 100000 == 0):
223 curr_time
= time
.time()
224 elapsed_time
= curr_time
- start_time
225 remaining_time
= float(total_num_instructions
- num_instructions_logged
) * (
226 float(elapsed_time
) / float(num_instructions_logged
)
228 print(str(datetime
.timedelta(seconds
=remaining_time
)))
229 num_instructions_logged
= num_instructions_logged
+ 1
230 inst_list
= target
.GetInstructions(fake_address
, inst_bytes
)
231 if not inst_list
.IsValid():
232 print("Invalid instruction list", file=log_file
)
234 inst
= inst_list
.GetInstructionAtIndex(0)
235 if not inst
.IsValid():
236 print("Invalid instruction", file=log_file
)
238 instr_output_stream
= lldb
.SBStream()
239 inst
.GetDescription(instr_output_stream
)
240 print(instr_output_stream
.GetData(), file=log_file
)