[ELF,test] Improve duplicate "symbol not found" error tests
[llvm-project.git] / lldb / examples / python / disasm-stress-test.py
blob2d3314ee8e8ff248b555635cbb6f3f2287b10616
1 #!/usr/bin/env python
3 import argparse
4 import datetime
5 import re
6 import subprocess
7 import sys
8 import time
10 parser = argparse.ArgumentParser(
11 description="Run an exhaustive test of the LLDB disassembler for a specific architecture."
14 parser.add_argument(
15 "--arch",
16 required=True,
17 action="store",
18 help="The architecture whose disassembler is to be tested",
20 parser.add_argument(
21 "--bytes",
22 required=True,
23 action="store",
24 type=int,
25 help="The byte width of instructions for that architecture",
27 parser.add_argument(
28 "--random",
29 required=False,
30 action="store_true",
31 help="Enables non-sequential testing",
33 parser.add_argument(
34 "--start",
35 required=False,
36 action="store",
37 type=int,
38 help="The first instruction value to test",
40 parser.add_argument(
41 "--skip",
42 required=False,
43 action="store",
44 type=int,
45 help="The interval between instructions to test",
47 parser.add_argument(
48 "--log",
49 required=False,
50 action="store",
51 help="A log file to write the most recent instruction being tested",
53 parser.add_argument(
54 "--time",
55 required=False,
56 action="store_true",
57 help="Every 100,000 instructions, print an ETA to standard out",
59 parser.add_argument(
60 "--lldb",
61 required=False,
62 action="store",
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)
75 if re_result is None:
76 return None
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")
84 sys.exit(-1)
86 sys.path.append(lldb_framework_path + "/Resources/Python")
89 if arg_ns.lldb is None:
90 AddLLDBToSysPathOnMacOSX()
91 else:
92 sys.path.append(arg_ns.lldb + "/Resources/Python")
94 import lldb
96 debugger = lldb.SBDebugger.Create()
98 if debugger.IsValid() == False:
99 print("Couldn't create an SBDebugger")
100 sys.exit(-1)
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)
106 sys.exit(-1)
109 def ResetLogFile(log_file):
110 if log_file != sys.stdout:
111 log_file.seek(0)
114 def PrintByteArray(log_file, byte_array):
115 for byte in byte_array:
116 print(hex(byte) + " ", end=" ", file=log_file)
117 print(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
124 self.m_start = start
125 self.m_skip = skip
126 self.m_value = start
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:
136 return None
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
142 return ret
144 def GetNumInstructions(self):
145 return (self.m_last - self.m_start) / self.m_skip
147 def __iter__(self):
148 return self
150 def next(self):
151 ret = self.GetNextInstruction()
152 if ret is None:
153 raise StopIteration
154 return ret
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)
172 return ret
174 def __iter__(self):
175 return self
177 def next(self):
178 ret = self.GetNextInstruction()
179 if ret is None:
180 raise StopIteration
181 return ret
184 log_file = None
187 def GetProviderWithArguments(args):
188 global log_file
189 if args.log is not None:
190 log_file = open(args.log, "w")
191 else:
192 log_file = sys.stdout
193 instruction_provider = None
194 if args.random:
195 instruction_provider = RandomInstructionProvider(args.bytes, log_file)
196 else:
197 start = 0
198 skip = 1
199 if args.start is not None:
200 start = args.start
201 if args.skip is not None:
202 skip = args.skip
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
215 if actually_time:
216 num_instructions_logged = 0
217 total_num_instructions = instruction_provider.GetNumInstructions()
218 start_time = time.time()
220 for inst_bytes in instruction_provider:
221 if actually_time:
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)
233 continue
234 inst = inst_list.GetInstructionAtIndex(0)
235 if not inst.IsValid():
236 print("Invalid instruction", file=log_file)
237 continue
238 instr_output_stream = lldb.SBStream()
239 inst.GetDescription(instr_output_stream)
240 print(instr_output_stream.GetData(), file=log_file)