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

Unified Diff: src/trusted/validator/x86/testing/tf/val_runner.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/val_runner.py
diff --git a/src/trusted/validator/x86/testing/tf/val_runner.py b/src/trusted/validator/x86/testing/tf/val_runner.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ef69a9e91aa72192d45b0cfa8c037570755839c
--- /dev/null
+++ b/src/trusted/validator/x86/testing/tf/val_runner.py
@@ -0,0 +1,221 @@
+# 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 collections
+import os
+import re
+import subprocess
+
+import utils
+
+
+VALIDATORS = ['nc', 'dfa']
+
+
+scons_out = '../../../../../../scons-out'
+ncval32 = os.path.join(scons_out, 'opt-linux-x86-32/staging/ncval')
Mark Seaborn 2012/09/10 19:38:06 You shouldn't hard-code Scons output filenames lik
Vlad Shcherbina 2012/09/11 14:26:00 I was using it to run locally (on bots paths are a
+ncval64 = os.path.join(scons_out, 'opt-linux-x86-64/staging/ncval')
+rdfaval = os.path.join(scons_out, 'opt-linux-x86-32/staging/validator_test')
+
+
+def AddValidatorsOptions(option_parser):
+ option_parser.add_option('--ncval32', dest='ncval32', type='string')
+ option_parser.add_option('--ncval64', dest='ncval64', type='string')
+ option_parser.add_option('--rdfaval', dest='rdfaval', type='string')
+
+
+def ProcessValidatorsOptions(options):
+ global ncval32
Mark Seaborn 2012/09/10 19:38:06 It would be cleaner if you didn't modify global va
Vlad Shcherbina 2012/09/11 14:26:00 Well, I don't like it because it would mean passin
+ global ncval64
+ global rdfaval
+
+ if options.ncval32 is not None:
+ ncval32 = options.ncval32
+
+ if options.ncval64 is not None:
+ ncval64 = options.ncval64
+
+ if options.rdfaval is not None:
+ rdfaval = options.rdfaval
+
+
+def SplitToLines(content):
+ return [line.rstrip() for line in content.rstrip().split('\n')]
+
+
+def RunNcVal32(hex_name):
+ args = [
+ '--hex_text=-',
+ '--max_errors=-1',
+ '--detailed=false',
+ '--cpuid-all'
+ ]
+
+ with open(hex_name) as input:
+ result = utils.CheckOutput([ncval32] + args, stdin=input)
+
+ return SplitToLines(result)
+
+
+def RunNcVal64(hex_name):
+ args = [
+ '--hex_text=-',
+ '--max_errors=-1',
+ '--readwrite_sfi',
+ '--annotate=false',
+ '--cpuid-all',
+ '--detailed=false',
+ ]
+
+ with open(hex_name) as input:
+ result = utils.CheckOutput([ncval64] + args, stdin=input)
+
+ return SplitToLines(result)
+
+
+def ParseNcValVerdict(last_line):
+ m = re.match(r'\*\*\* <input> (is safe|IS UNSAFE) \*\*\*$', last_line)
+ assert m is not None, 'unexpected ncval output "%s"' % last_line
+ return m.group(1) == 'is safe'
+
+
+def ParseNcVal32(lines):
+ assert len(lines) > 0, 'ncval output is empty'
+
+ errors = []
+ for line in lines[:-1]:
+ line = line.strip()
+ if line == '':
+ continue
+ if re.match(r'.+ > .+ \(read overflow of .+ bytes\)', line):
Mark Seaborn 2012/09/10 19:38:06 Why are you dropping this line of output?
Vlad Shcherbina 2012/09/11 14:26:00 Right, this should not happen anyway. It's somethi
+ continue
+ if line == 'ErrorSegmentation':
Mark Seaborn 2012/09/10 19:38:06 Ditto: why drop this?
Vlad Shcherbina 2012/09/11 14:26:00 Same.
+ continue
+ # Parse error message of the form
+ # VALIDATOR: 4: Bad prefix usage
+ m = re.match(r'VALIDATOR: ([0-9a-f]+): (.*)$', line, re.IGNORECASE)
+ offset = int(m.group(1), 16)
+ message = m.group(2)
+ errors.append((offset, message))
+ safe = ParseNcValVerdict(lines[-1])
+ return safe, errors
+
+
+def ParseNcVal64(lines):
+ assert len(lines) > 0, 'ncval output is empty'
+
+ errors = []
+ for i, line in enumerate(lines[:-1]):
+ #print line
Mark Seaborn 2012/09/10 19:38:06 Please remove commented-out code
Vlad Shcherbina 2012/09/11 14:26:00 Done.
+ #if 'Bad basic' in line:
+ # print 'z'*10
+ # print line
+ # raw_input()
+
+ if line.startswith('VALIDATOR: Checking jump targets:'):
+ continue
+ if line.startswith('VALIDATOR: Checking that basic blocks are aligned'):
+ continue
+
+ # Skip disassembler output of the form
+ # VALIDATOR: 0000000000000003: 49 89 14 07 mov [%r15+%rax*1], %rdx
+ m = re.match(r'VALIDATOR: ([0-9a-f]+):', line, re.IGNORECASE)
+ if m is not None:
+ continue
+
+ # Parse error message of the form
+ # VALIDATOR: ERROR: 20: Bad basic block alignment.
+ m = re.match(r'VALIDATOR: ERROR: ([0-9a-f]+): (.*)', line, re.IGNORECASE)
+ if m is not None:
+ offset = int(m.group(1), 16)
+ errors.append((offset, m.group(2)))
+ continue
+
+ # Parse two-line error messages of the form
+ # VALIDATOR: 0000000000000003: 49 89 14 07 mov [%r15+%rax*1], %rdx
+ # VALIDATOR: ERROR: Invalid index register in memory offset
+ m = re.match(r'VALIDATOR: ((?:ERROR|WARNING): .*)$', line, re.IGNORECASE)
+ if m is not None:
+ m2 = re.match(r'VALIDATOR: ([0-9a-f]+):', lines[i-1], re.IGNORECASE)
+ assert m2 is not None, "can't parse line '%s' preceding line '%s'" % (
+ lines[i-1],
+ line
+ )
+ offset = int(m2.group(1), 16)
+ errors.append((offset, m.group(1)))
+ continue
+
+ assert False, "can't parse line '%s'" % line
Mark Seaborn 2012/09/10 19:38:06 Better style would be: raise AssertionError("can
Vlad Shcherbina 2012/09/11 14:26:00 Done.
+
+ safe = ParseNcValVerdict(lines[-1])
+ return safe, errors
+
+
+def MakeElf(bits, data, elf_filename):
+ assert bits in [32, 64]
+
+ with utils.TempFile(mode='w') as asm_file:
+ for c in data:
+ asm_file.write('.byte %d\n' % ord(c))
+ asm_file.flush()
+
+ subprocess.check_call([
+ 'as', '--%s' % bits, asm_file.name, '-o', elf_filename])
+
+
+def RunDfa(bits, data):
+ with utils.TempFile(mode='w') as elf_file:
+ with utils.TempFile(mode='w+') as out_file:
+ MakeElf(bits, data, elf_file.name)
+
+ result = subprocess.call([rdfaval, elf_file.name], stdout=out_file)
+ out_file.seek(0)
+ lines = SplitToLines(out_file.read())
+
+ return result, lines
+
+
+def ParseDfa(lines):
Mark Seaborn 2012/09/10 19:38:06 Please can you take out all of the DFA-validator r
Vlad Shcherbina 2012/09/11 14:26:00 Done.
+ errors = []
+ for line in lines:
+ if re.match(r"file '.*' can not be fully validated$", line):
+ continue
+ m = re.match(r'bad jump to around 0x([0-9a-f]+)$', line, re.IGNORECASE)
+ if m is not None:
+ offset = int(m.group(1), 16)
+ errors.append((offset, 'bad jump to around'))
+ continue
+
+ m = re.match(r'offset 0x([0-9a-f]+): (.*)$', line, re.IGNORECASE)
+ offset = int(m.group(1), 16)
+ message = m.group(2)
+ errors.append((offset, message))
+
+ return errors
+
+
+ValidationResults = collections.namedtuple('ValidationResults', 'safe, errors')
+
+
+def RunValidator(validator, bits, data):
+ assert validator in VALIDATORS
+ assert bits in [32, 64]
+ assert len(data) % 32 == 0
+
+ if validator == 'nc':
+ with utils.TempFile(mode='w') as hex_file:
+ hex_file.write('%s\n' % utils.DataToReadableHex(data))
+ hex_file.flush()
+
+ if bits == 32:
+ safe, errors = ParseNcVal32(RunNcVal32(hex_file.name))
+ elif bits == 64:
+ safe, errors = ParseNcVal64(RunNcVal64(hex_file.name))
+
+ elif validator == 'dfa':
+ code, output = RunDfa(bits, data)
+ safe = (code == 0)
+ errors = ParseDfa(output)
+
+ return ValidationResults(safe=safe, errors=errors)

Powered by Google App Engine
This is Rietveld 408576698