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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: src/trusted/validator/x86/testing/tf/tf.py
diff --git a/src/trusted/validator/x86/testing/tf/tf.py b/src/trusted/validator/x86/testing/tf/tf.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2ca97e9222537db880bf9ee60fafb22db8f95ee
--- /dev/null
+++ b/src/trusted/validator/x86/testing/tf/tf.py
@@ -0,0 +1,238 @@
+# Copyright (c) 2012 The Native Client Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import re
+
+import asm
+import utils
+import val_runner
+
+
+class Instruction(object):
+ __slots__ = [
+ 'offset',
+ 'asm',
+ 'hex',
+ 'data',
+ 'outs', # {validator: [message, ...], ...}
+ ]
+
+ def __init__(self):
+ self.offset = None
+ self.hex = None
+ self.asm = None
+ self.outs = dict((v, []) for v in val_runner.VALIDATORS)
+
+ @property
+ def size(self):
+ return len(self.data)
+
+ @property
+ def end_offset(self):
+ return self.offset + self.size
+
+ def CheckAsm(self, bits):
+ if self.asm is None:
+ return
+ asm_data = asm.Assemble(bits, self.asm)
+ assert self.data == asm_data, (utils.DataToReadableHex(asm_data),
+ utils.DataToReadableHex(self.data))
+
+ def __repr__(self):
+ return 'Instr(%s)@0x%x' % (self.asm or self.hex, self.offset)
+
+ _out_suffix = '_out'
+
+ @staticmethod
+ def Parse(bits, lines):
+ instr = Instruction()
+ for line in lines:
+ 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.
+ field, value = line.split(':', 1)
+ field = field.strip()
+
+ if field.endswith(Instruction._out_suffix):
+ validator = field[:-len(Instruction._out_suffix)]
+ instr.outs[validator].append(value.strip())
+ else:
+ assert getattr(instr, field) is None, 'field %s is already set' % field
+ setattr(instr, field, value.strip())
+
+ if instr.hex is not None:
+ instr.data = utils.ReadableHexToData(instr.hex)
+ else:
+ instr.data = asm.Assemble(bits, instr.asm)
+ instr.hex = utils.DataToReadableHex(instr.data)
+ return instr
+
+ def ToLines(self, offset=None):
+ lines = []
+ if self.offset != offset:
+ lines.append('offset: %s' % self.offset)
+ if self.asm is not None:
+ lines.append('asm: %s' % self.asm)
+ if self.hex is not None:
+ lines.append('hex: %s' % self.hex)
+
+ for validator in val_runner.VALIDATORS:
+ for msg in self.outs[validator]:
+ lines.append('%s%s: %s' % (validator, Instruction._out_suffix, msg))
+
+ return lines
+
+
+class Test(object):
+ __slots__ = [
+ 'bits',
+ 'separators',
+ 'sections',
+ 'instructions',
+ 'safe',
+ ]
+
+ # Each separator/section is a list of strings.
+ # Number of separators always exceeds number of sections by one, because
+ # they interleave, starting and finishing with (possibly empty) separator.
+
+ @staticmethod
+ def Parse(lines):
+ test = Test()
+ test.safe = None
+ test.separators = [[]]
+ test.sections = []
+
+ # Parser state: whether we are currently parsing
+ # separator (comments/whitelines) or section.
+ in_section = False
+
+ for line in lines:
+ line = line.strip()
+ is_sep = line == '' or line.startswith('#')
+
+ if is_sep:
+ if in_section:
+ test.separators.append([line])
+ else:
+ test.separators[-1].append(line)
+ else:
+ if in_section:
+ test.sections[-1].append(line)
+ else:
+ test.sections.append([line])
+
+ in_section = not is_sep
+
+ if in_section:
+ test.separators.append([])
+
+ assert len(test.separators) == len(test.sections) + 1
+
+ # header section is required; it specifies BITS and OUTCOME
+ assert len(test.sections) >= 1
+
+ for line in test.sections[0]:
+ m = re.match(r'(.*):\s*(.*)$', line)
+ field, value = m.groups()
+ if field == 'BITS':
+ test.bits = int(value)
+ elif field == 'OUTCOME':
+ assert value in ['valid', 'invalid']
+ test.safe = value == 'valid'
+ else:
+ assert False, 'Unrecognized field %s in special section' % field
+
+ test.instructions = []
+ offset = 0
+ for section in test.sections[1:]:
+ instr = Instruction.Parse(test.bits, section)
+
+ if instr.hex is None:
+ code = asm.Assemble(test.bits, instr.asm)
+ instr.hex = utils.DataToReadableHex(code)
+
+ if instr.offset is not None:
+ instr.offset = int(instr.offset)
+ else:
+ instr.offset = offset
+ test.instructions.append(instr)
+ offset = instr.end_offset
+
+ return test
+
+ def Print(self, fout):
+ self.sections[0] = ['BITS: %s' % self.bits]
+ if self.safe is not None:
+ self.sections[0].append(
+ 'OUTCOME: valid' if self.safe else 'OUTCOME: invalid')
+
+ offset = 0
+ for i, instr in enumerate(self.instructions):
+ self.sections[i+1] = instr.ToLines(offset)
+ offset = instr.end_offset
+
+ assert len(self.separators) == len(self.sections) + 1
+ groups = []
+ for sep, sec in zip(self.separators, self.sections):
+ groups.append(sep)
+ groups.append(sec)
+ groups.append(self.separators[-1])
+
+ for group in groups:
+ for line in group:
+ fout.write('%s\n' % line)
+
+ def PrepareCode(self):
+ code_size = max(i.end_offset for i in self.instructions)
+ code_size = ((code_size - 1) // 32 + 1) * 32
+ code = ['\x90'] * code_size
+
+ for i in self.instructions:
+ code[i.offset : i.end_offset] = list(i.data)
+
+ return ''.join(code)
+
+ def RunValidator(self, validator):
+ assert validator in val_runner.VALIDATORS
+ if validator == 'nc':
+ return val_runner.RunValidator(validator, self.bits, self.PrepareCode())
+
+ test2 = copy.deepcopy(self)
+
+ errors = set()
+ safe = True
+
+ while True:
+ res = val_runner.RunValidator(validator, test2.bits, test2.PrepareCode())
+ safe = safe and res.safe
+ errors.update(res.errors)
+
+ patched = False
+ for loc, msg in res.errors:
+ if msg == 'DFA error in validator':
+ for i in test2.instructions:
+ if i.offset == loc:
+ 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
+ if i.data != nops:
+ i.data = nops
+ patched = True
+ if not patched:
+ break
+
+ return val_runner.ValidationResults(safe=safe, errors=sorted(errors))
+
+ def ExpectedErrors(self, validator):
+ errors = []
+ for i in self.instructions:
+ for msg in i.outs[validator]:
+ # Check if message has the form
+ # [at +<delta>] <error message>
+ m = re.match(r'\[at \+(\d+)\]\s(.*)$', msg)
+ if m is not None:
+ delta = int(m.group(1))
+ msg = m.group(2)
+ else:
+ delta = 0
+ errors.append((i.offset + delta, msg))
+ return errors

Powered by Google App Engine
This is Rietveld 408576698