| Index: src/trusted/validator_ragel/build.scons
|
| diff --git a/src/trusted/validator_ragel/build.scons b/src/trusted/validator_ragel/build.scons
|
| index 4ff6cf850de0238081e2fd7292d6a3f9f6fc66b5..8710d4d732588e725bc2eef182cbd5cfbad1719a 100644
|
| --- a/src/trusted/validator_ragel/build.scons
|
| +++ b/src/trusted/validator_ragel/build.scons
|
| @@ -30,13 +30,60 @@ INST_DEFS = [
|
| 'unreviewed/nops.def'
|
| ]
|
|
|
| +# Generate 32 and 64 bit versions of decoders and validators. Both libraries
|
| +# are used for command-line decoder and validator those detect specific
|
| +# architecture of the ELF file provided.
|
| +env.ComponentLibrary('dfa_validate_x86_32',
|
| + ['gen/validator_x86_32.c'])
|
| +env.ComponentLibrary('dfa_validate_x86_64',
|
| + ['gen/validator_x86_64.c'])
|
| +env.ComponentLibrary('dfa_decode_x86_32',
|
| + ['gen/decoder_x86_32.c'])
|
| +env.ComponentLibrary('dfa_decode_x86_64',
|
| + ['gen/decoder_x86_64.c'])
|
| +
|
| +# Glue library called from service runtime. The source file depends on the
|
| +# target architecture.
|
| +caller_lib_bits = None
|
| +if env.Bit('target_x86_32'):
|
| + caller_lib_bits = '32'
|
| +if env.Bit('target_x86_64'):
|
| + caller_lib_bits = '64'
|
| +if caller_lib_bits:
|
| + # TODO(shcherbina):
|
| + # interpolate env.get('TARGET_FULLARCH') / env.get('TARGET_SUBARCH') instead
|
| + caller_lib = 'dfa_validate_caller_x86_%s' % caller_lib_bits
|
| + env.ComponentLibrary(caller_lib,
|
| + ['unreviewed/dfa_validate_%s.c' % caller_lib_bits])
|
| +
|
| +# Command-line decoder.
|
| +decoder_test = env.ComponentProgram(
|
| + 'decoder_test',
|
| + ['unreviewed/decoder_test.c'],
|
| + EXTRA_LIBS=['dfa_decode_x86_32', 'dfa_decode_x86_64'])
|
| +
|
| +# Command-line validator.
|
| +validator_test_exe = env.ComponentProgram(
|
| + 'validator_test',
|
| + ['unreviewed/validator_test.c'],
|
| + EXTRA_LIBS=['dfa_validate_x86_32', 'dfa_validate_x86_64'])
|
| +
|
| +# Python-based regression test. TODO(pasko): remove it when validator_tests are
|
| +# migrated to be able to run with the new validator.
|
| +if env.Bit('validator_ragel'):
|
| + test_node = env.CommandTest('validator_test_py.out',
|
| + command=['${PYTHON}',
|
| + env.File('unreviewed/validator_test.py'),
|
| + validator_test_exe])
|
| + env.AddNodeToTestSuite(test_node, ['small_tests'], 'run_validator_test_py')
|
| +
|
| # Source generation:
|
| #
|
| # dfagen : Regenerate any autogenerated source files.
|
|
|
| -generate = False
|
| -if 'dfagen' in COMMAND_LINE_TARGETS or 'dfaclean' in COMMAND_LINE_TARGETS:
|
| - generate = True
|
| +dfa_aliases = 'dfagen', 'dfaclean', 'dfacheckdecoder'
|
| +
|
| +generate = any(a in COMMAND_LINE_TARGETS for a in dfa_aliases)
|
|
|
| if generate:
|
| if not env.Bit('host_linux'):
|
| @@ -58,7 +105,7 @@ if generate:
|
| 'gen_dfa',
|
| ['unreviewed/gen_dfa.cc'])
|
|
|
| - # Source generation step 2: Generate decoder automatas.
|
| + # Source generation step 2: Generate decoder automata.
|
| #
|
| # Now we are back to conditionally defining the large automata generated
|
| # by gen_dfa.
|
| @@ -71,13 +118,13 @@ if generate:
|
| # _consts.c file includes constants referenced by .rl file and if .rl
|
| # file is not changed _consts.c is guaranteed to be the same (reverse
|
| # is not true).
|
| +
|
| const_file = '%s/%s_x86_%s_instruction_consts.c' % (
|
| val_src_dir, automaton, bits)
|
|
|
| - exe_path = '${STAGING_DIR}/${PROGPREFIX}gen_dfa${PROGSUFFIX}'
|
| env.Command(
|
| target=rl_file,
|
| - source=[exe_path] + INST_DEFS,
|
| + source=[gen_dfa] + INST_DEFS,
|
| action=(
|
| '${SOURCES[0]} -o ${TARGET} -c %s -m %s -d %s %s') % (
|
| # Const file (-c): not tracked by SCONS (see above)
|
| @@ -87,7 +134,7 @@ if generate:
|
| # (-d):
|
| dfa_gen_actions,
|
| # pass inst defs as remaining parameters
|
| - ' '.join('${SOURCES[%d]}' % (i+1)
|
| + ' '.join('${SOURCES[%d]}' % (i + 1)
|
| for i in range(len(INST_DEFS)))
|
| )
|
| )
|
| @@ -105,20 +152,23 @@ if generate:
|
| target_filename = target[0].get_abspath()
|
| architecture = {'x86_32': 'ia32',
|
| 'x86_64': 'x86-64'}[target_filename[-8:-2]]
|
| +
|
| with open(source_filename, 'r') as source_file:
|
| - with open(target_filename, 'w') as target_file:
|
| - target_file.write(
|
| -"""/* native_client/%s
|
| - * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.
|
| - * Compiled for %s mode.
|
| - */""" % (target_filename, architecture))
|
| -
|
| - comment, sep, rest = source_file.read().partition('*/')
|
| - if sep == '':
|
| - raise UserError('Generated file %s does not have '
|
| - 'header comment block' % source_filename)
|
| - target_file.write(rest)
|
| + comment, sep, rest = source_file.read().partition('*/')
|
| + if sep == '':
|
| + raise UserError('Generated file %s does not have '
|
| + 'header comment block' % source_filename)
|
| +
|
| + with open(target_filename, 'w') as target_file:
|
| + target_file.write(
|
| + ('/* native_client/%s\n'
|
| + ' * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\n'
|
| + ' * Compiled for %s mode.\n'
|
| + ' */') % (target_filename, architecture))
|
| +
|
| + target_file.write(rest)
|
|
|
| + # inject comments and place files to appropriate dir
|
| env.Command(
|
| target=c_full_filename,
|
| source=['%s/%s' % (rl_src_dir, c_file)],
|
| @@ -128,75 +178,112 @@ if generate:
|
| return rl_file, c_file, c_full_filename
|
|
|
| decoder32 = MakeAutomaton(
|
| - '32', 'decoder',
|
| - 'check_access,opcode,parse_operands_states,mark_data_fields',
|
| - '-T0')
|
| + '32', 'decoder',
|
| + 'check_access,opcode,parse_operands_states,mark_data_fields',
|
| + '-T0')
|
| validator32 = MakeAutomaton(
|
| - '32', 'validator',
|
| - ('check_access,opcode,parse_operands,parse_operands_states,'
|
| - 'instruction_name,mark_data_fields,nacl-forbidden,'
|
| - 'imm_operand_action,rel_operand_action'),
|
| - '-G2')
|
| + '32', 'validator',
|
| + ('check_access,opcode,parse_operands,parse_operands_states,'
|
| + 'instruction_name,mark_data_fields,nacl-forbidden,'
|
| + 'imm_operand_action,rel_operand_action'),
|
| + '-G2')
|
| decoder64 = MakeAutomaton(
|
| - '64', 'decoder',
|
| - 'check_access,opcode,parse_operands_states,mark_data_fields',
|
| - '-T0')
|
| + '64', 'decoder',
|
| + 'check_access,opcode,parse_operands_states,mark_data_fields',
|
| + '-T0')
|
| validator64 = MakeAutomaton(
|
| - '64', 'validator',
|
| - ('opcode,instruction_name,mark_data_fields,imm_operand_action,'
|
| - 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,'
|
| - 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,'
|
| - 'parse_ymm_operands,parse_relative_operands,'
|
| - 'parse_immediate_operands,parse_operands_states,'
|
| - 'parse_operand_positions'),
|
| - '-GT2')
|
| + '64', 'validator',
|
| + ('opcode,instruction_name,mark_data_fields,imm_operand_action,'
|
| + 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,'
|
| + 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,'
|
| + 'parse_ymm_operands,parse_relative_operands,'
|
| + 'parse_immediate_operands,parse_operands_states,'
|
| + 'parse_operand_positions'),
|
| + '-GT2')
|
|
|
| automata = list(decoder32 + validator32 + decoder64 + validator64)
|
|
|
| - env.AlwaysBuild(env.Alias('dfagen', automata))
|
| - env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata)))
|
| + # Generate checkdecoder test
|
|
|
| -# Generate 32 and 64 bit versions of decoders and validators. Both libraries
|
| -# are used for command-line decoder and validator those detect specific
|
| -# architecture of the ELF file provided.
|
| -env.ComponentLibrary('dfa_validate_x86_32',
|
| - ['gen/validator_x86_32.c'])
|
| -env.ComponentLibrary('dfa_validate_x86_64',
|
| - ['gen/validator_x86_64.c'])
|
| -env.ComponentLibrary('dfa_decode_x86_32',
|
| - ['gen/decoder_x86_32.c'])
|
| -env.ComponentLibrary('dfa_decode_x86_64',
|
| - ['gen/decoder_x86_64.c'])
|
| + test_env = env.Clone()
|
| + test_env.Append(
|
| + CCFLAGS=['-g', '-Wno-unused-function'],
|
| + LINKFLAGS='-g',
|
| + CPPPATH='unreviewed')
|
|
|
| -# Glue library called from service runtime. The source file depends on the
|
| -# target architecture.
|
| -caller_lib_bits = None
|
| -if env.Bit('target_x86_32'):
|
| - caller_lib_bits = '32'
|
| -if env.Bit('target_x86_64'):
|
| - caller_lib_bits = '64'
|
| -if caller_lib_bits:
|
| - caller_lib = 'dfa_validate_caller_x86_%s' % caller_lib_bits
|
| - env.ComponentLibrary(caller_lib,
|
| - ['unreviewed/dfa_validate_%s.c' % caller_lib_bits])
|
| + test_dfa_object = test_env.Object('unreviewed/test_dfa.c')
|
|
|
| -# Command-line decoder.
|
| -env.ComponentProgram(
|
| - 'decoder_test',
|
| - ['unreviewed/decoder_test.c'],
|
| - EXTRA_LIBS=['dfa_decode_x86_32', 'dfa_decode_x86_64'])
|
| + objdump, gas = env.Command(
|
| + target=['objdump', 'gas'],
|
| + source=['obtain_binutils.py'],
|
| + action='python ${SOURCES[0]} ${TARGETS[0]} ${TARGETS[1]}'
|
| + )
|
|
|
| -# Command-line validator.
|
| -validator_test_exe = env.ComponentProgram(
|
| - 'validator_test',
|
| - ['unreviewed/validator_test.c'],
|
| - EXTRA_LIBS=['dfa_validate_x86_32', 'dfa_validate_x86_64'])
|
| + check_decoders = []
|
|
|
| -# Python-based regression test. TODO(pasko): remove it when validator_tests are
|
| -# migrated to be able to run with the new validator.
|
| -if env.Bit('validator_ragel'):
|
| - test_node = env.CommandTest('validator_test_py.out',
|
| - command=['${PYTHON}',
|
| - env.File('unreviewed/validator_test.py'),
|
| - validator_test_exe])
|
| - env.AddNodeToTestSuite(test_node, ['small_tests'], 'run_validator_test_py')
|
| + for bits in ('32', '64'):
|
| + (one_valid_instr_rl,) = env.Command(
|
| + target='one_valid_instruction_x86_%s.rl' % bits,
|
| + source=[gen_dfa] + INST_DEFS,
|
| + action=('${SOURCES[0]} -o ${TARGET} %s '
|
| + '-d check_access,rex_prefix,vex_prefix,opcode '
|
| + '-d parse_operands_states,parse_operands,instruction_name '
|
| + '-m %s') % (
|
| + ' '.join('${SOURCES[%d]}' % (i + 1)
|
| + for i in range(len(INST_DEFS))),
|
| + {'32': 'ia32', '64': 'amd64'}[bits])
|
| + )
|
| +
|
| + include_dir = one_valid_instr_rl.dir.get_abspath()
|
| +
|
| + (one_instr_dot,) = env.Command(
|
| + target='one_instruction_x86_%s.dot' % bits,
|
| + source=[
|
| + 'unreviewed/one_instruction_x86_%s.rl' % bits,
|
| + one_valid_instr_rl],
|
| + action=[
|
| + '%s -V -I%s ${SOURCES[0]} -o ${TARGET}' %
|
| + (ragel_binary, include_dir)]
|
| + )
|
| +
|
| + test_dfa_transitions = test_env.Command(
|
| + target='test_dfa_transitions_x86_%s.c' % bits,
|
| + source=['unreviewed/parse_dfa.py', one_instr_dot],
|
| + action='python ${SOURCES[0]} <"${SOURCES[1]}" >"${TARGET}"'
|
| + )
|
| +
|
| + test_dfa_transitions_object = test_env.Object(test_dfa_transitions)
|
| +
|
| + test_dfa = test_env.ComponentProgram(
|
| + 'test_dfa_x86_%s' % bits,
|
| + [test_dfa_object, test_dfa_transitions_object])
|
| +
|
| + fast_temp_for_test = '/dev/shm'
|
| +
|
| + (check_decoder,) = env.Command(
|
| + target='objdump_test_fake_file_%s' % bits,
|
| + source=[
|
| + 'unreviewed/run_objdump_test.py',
|
| + gas,
|
| + objdump,
|
| + decoder_test,
|
| + 'unreviewed/decoder_test_one_file.sh',
|
| + test_dfa,
|
| + ],
|
| + action=[(
|
| + 'python ${SOURCES[0]} '
|
| + '--gas="${SOURCES[1]} --%s" '
|
| + '--objdump="${SOURCES[2]}" '
|
| + '--decoder="${SOURCES[3]}" '
|
| + '--tester="${SOURCES[4]}" '
|
| + '-- '
|
| + '"${SOURCES[5]}" "%s"'
|
| + ) % (bits, fast_temp_for_test),
|
| + ])
|
| + check_decoders.append(check_decoder)
|
| +
|
| + SideEffect(fast_temp_for_test, check_decoders)
|
| +
|
| + env.AlwaysBuild(env.Alias('dfagen', automata))
|
| + env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata)))
|
| + env.AlwaysBuild(env.Alias('dfacheckdecoder', check_decoders))
|
|
|