Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: src/trusted/validator/x86/testing/tf/tf.py

Issue 10908137: (abandoned) Validator tests: convert hexes to TFs and run on bots (for prod. validator only) (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: fix for windows (temp files and crlf) Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import copy
6 import re
7
8 import asm
9 import utils
10 import val_runner
11
12
13 class Instruction(object):
14 __slots__ = [
15 'offset',
16 'asm',
17 'hex',
18 'data',
19 'outs', # {validator: [message, ...], ...}
20 ]
21
22 def __init__(self):
23 self.offset = None
24 self.hex = None
25 self.asm = None
26 self.outs = dict((v, []) for v in val_runner.VALIDATORS)
27
28 @property
29 def size(self):
30 return len(self.data)
31
32 @property
33 def end_offset(self):
34 return self.offset + self.size
35
36 def CheckAsm(self, bits):
37 if self.asm is None:
38 return
39 asm_data = asm.Assemble(bits, self.asm)
40 assert self.data == asm_data, (utils.DataToReadableHex(asm_data),
41 utils.DataToReadableHex(self.data))
42
43 def __repr__(self):
44 return 'Instr(%s)@0x%x' % (self.asm or self.hex, self.offset)
45
46 _out_suffix = '_out'
47
48 @staticmethod
49 def Parse(bits, lines):
50 instr = Instruction()
51 for line in lines:
52 assert ':' in line, "can't parse line '%s" % line
Mark Seaborn 2012/09/10 19:38:06 Nit: missing closing '
Vlad Shcherbina 2012/09/11 14:26:00 Done.
53 field, value = line.split(':', 1)
54 field = field.strip()
55
56 if field.endswith(Instruction._out_suffix):
57 validator = field[:-len(Instruction._out_suffix)]
58 instr.outs[validator].append(value.strip())
59 else:
60 assert getattr(instr, field) is None, 'field %s is already set' % field
61 setattr(instr, field, value.strip())
62
63 if instr.hex is not None:
64 instr.data = utils.ReadableHexToData(instr.hex)
65 else:
66 instr.data = asm.Assemble(bits, instr.asm)
67 instr.hex = utils.DataToReadableHex(instr.data)
68 return instr
69
70 def ToLines(self, offset=None):
71 lines = []
72 if self.offset != offset:
73 lines.append('offset: %s' % self.offset)
74 if self.asm is not None:
75 lines.append('asm: %s' % self.asm)
76 if self.hex is not None:
77 lines.append('hex: %s' % self.hex)
78
79 for validator in val_runner.VALIDATORS:
80 for msg in self.outs[validator]:
81 lines.append('%s%s: %s' % (validator, Instruction._out_suffix, msg))
82
83 return lines
84
85
86 class Test(object):
87 __slots__ = [
88 'bits',
89 'separators',
90 'sections',
91 'instructions',
92 'safe',
93 ]
94
95 # Each separator/section is a list of strings.
96 # Number of separators always exceeds number of sections by one, because
97 # they interleave, starting and finishing with (possibly empty) separator.
98
99 @staticmethod
100 def Parse(lines):
101 test = Test()
102 test.safe = None
103 test.separators = [[]]
104 test.sections = []
105
106 # Parser state: whether we are currently parsing
107 # separator (comments/whitelines) or section.
108 in_section = False
109
110 for line in lines:
111 line = line.strip()
112 is_sep = line == '' or line.startswith('#')
113
114 if is_sep:
115 if in_section:
116 test.separators.append([line])
117 else:
118 test.separators[-1].append(line)
119 else:
120 if in_section:
121 test.sections[-1].append(line)
122 else:
123 test.sections.append([line])
124
125 in_section = not is_sep
126
127 if in_section:
128 test.separators.append([])
129
130 assert len(test.separators) == len(test.sections) + 1
131
132 # header section is required; it specifies BITS and OUTCOME
133 assert len(test.sections) >= 1
134
135 for line in test.sections[0]:
136 m = re.match(r'(.*):\s*(.*)$', line)
137 field, value = m.groups()
138 if field == 'BITS':
139 test.bits = int(value)
140 elif field == 'OUTCOME':
141 assert value in ['valid', 'invalid']
142 test.safe = value == 'valid'
143 else:
144 assert False, 'Unrecognized field %s in special section' % field
145
146 test.instructions = []
147 offset = 0
148 for section in test.sections[1:]:
149 instr = Instruction.Parse(test.bits, section)
150
151 if instr.hex is None:
152 code = asm.Assemble(test.bits, instr.asm)
153 instr.hex = utils.DataToReadableHex(code)
154
155 if instr.offset is not None:
156 instr.offset = int(instr.offset)
157 else:
158 instr.offset = offset
159 test.instructions.append(instr)
160 offset = instr.end_offset
161
162 return test
163
164 def Print(self, fout):
165 self.sections[0] = ['BITS: %s' % self.bits]
166 if self.safe is not None:
167 self.sections[0].append(
168 'OUTCOME: valid' if self.safe else 'OUTCOME: invalid')
169
170 offset = 0
171 for i, instr in enumerate(self.instructions):
172 self.sections[i+1] = instr.ToLines(offset)
173 offset = instr.end_offset
174
175 assert len(self.separators) == len(self.sections) + 1
176 groups = []
177 for sep, sec in zip(self.separators, self.sections):
178 groups.append(sep)
179 groups.append(sec)
180 groups.append(self.separators[-1])
181
182 for group in groups:
183 for line in group:
184 fout.write('%s\n' % line)
185
186 def PrepareCode(self):
187 code_size = max(i.end_offset for i in self.instructions)
188 code_size = ((code_size - 1) // 32 + 1) * 32
189 code = ['\x90'] * code_size
190
191 for i in self.instructions:
192 code[i.offset : i.end_offset] = list(i.data)
193
194 return ''.join(code)
195
196 def RunValidator(self, validator):
197 assert validator in val_runner.VALIDATORS
198 if validator == 'nc':
199 return val_runner.RunValidator(validator, self.bits, self.PrepareCode())
200
201 test2 = copy.deepcopy(self)
202
203 errors = set()
204 safe = True
205
206 while True:
207 res = val_runner.RunValidator(validator, test2.bits, test2.PrepareCode())
208 safe = safe and res.safe
209 errors.update(res.errors)
210
211 patched = False
212 for loc, msg in res.errors:
213 if msg == 'DFA error in validator':
214 for i in test2.instructions:
215 if i.offset == loc:
216 nops = '\x90'*i.size
Mark Seaborn 2012/09/10 19:38:06 Nit: put spaces around '*'. Also comment that you
Vlad Shcherbina 2012/09/11 14:26:00 I think the name of the variable suggests it by it
217 if i.data != nops:
218 i.data = nops
219 patched = True
220 if not patched:
221 break
222
223 return val_runner.ValidationResults(safe=safe, errors=sorted(errors))
224
225 def ExpectedErrors(self, validator):
226 errors = []
227 for i in self.instructions:
228 for msg in i.outs[validator]:
229 # Check if message has the form
230 # [at +<delta>] <error message>
231 m = re.match(r'\[at \+(\d+)\]\s(.*)$', msg)
232 if m is not None:
233 delta = int(m.group(1))
234 msg = m.group(2)
235 else:
236 delta = 0
237 errors.append((i.offset + delta, msg))
238 return errors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698