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

Side by Side Diff: src/trusted/validator_ragel/build.scons

Issue 10826182: Validator_ragel: move checkdecoder test from Makefile to scons (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: next round of minor changes Created 8 years, 4 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
« no previous file with comments | « no previous file | src/trusted/validator_ragel/obtain_binutils.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- python -*- 1 # -*- python -*-
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 from SCons.Errors import UserError 6 from SCons.Errors import UserError
7 7
8 Import('env') 8 Import('env')
9 9
10 # 10 #
(...skipping 12 matching lines...) Expand all
23 23
24 INST_DEFS = [ 24 INST_DEFS = [
25 'unreviewed/general_purpose_instructions.def', 25 'unreviewed/general_purpose_instructions.def',
26 'unreviewed/system_instructions.def', 26 'unreviewed/system_instructions.def',
27 'unreviewed/x87_instructions.def', 27 'unreviewed/x87_instructions.def',
28 'unreviewed/mmx_instructions.def', 28 'unreviewed/mmx_instructions.def',
29 'unreviewed/xmm_instructions.def', 29 'unreviewed/xmm_instructions.def',
30 'unreviewed/nops.def' 30 'unreviewed/nops.def'
31 ] 31 ]
32 32
33 # Generate 32 and 64 bit versions of decoders and validators. Both libraries
34 # are used for command-line decoder and validator those detect specific
35 # architecture of the ELF file provided.
36 env.ComponentLibrary('dfa_validate_x86_32',
37 ['gen/validator_x86_32.c'])
38 env.ComponentLibrary('dfa_validate_x86_64',
39 ['gen/validator_x86_64.c'])
40 env.ComponentLibrary('dfa_decode_x86_32',
41 ['gen/decoder_x86_32.c'])
42 env.ComponentLibrary('dfa_decode_x86_64',
43 ['gen/decoder_x86_64.c'])
44
45 # Glue library called from service runtime. The source file depends on the
46 # target architecture.
47 caller_lib = 'dfa_validate_caller_x86_%s' % env.get('TARGET_SUBARCH')
48 env.ComponentLibrary(
49 caller_lib,
50 'unreviewed/dfa_validate_%s.c' % env.get('TARGET_SUBARCH')
51 )
52
53 # Command-line decoder.
54 decoder_test = env.ComponentProgram(
55 'decoder_test',
56 ['unreviewed/decoder_test.c'],
57 EXTRA_LIBS=['dfa_decode_x86_32', 'dfa_decode_x86_64'])
58
59 # Command-line validator.
60 validator_test_exe = env.ComponentProgram(
61 'validator_test',
62 ['unreviewed/validator_test.c'],
63 EXTRA_LIBS=['dfa_validate_x86_32', 'dfa_validate_x86_64'])
64
65 # Python-based regression test. TODO(pasko): remove it when validator_tests are
66 # migrated to be able to run with the new validator.
67 if env.Bit('validator_ragel'):
68 test_node = env.CommandTest('validator_test_py.out',
69 command=['${PYTHON}',
70 env.File('unreviewed/validator_test.py'),
71 validator_test_exe])
72 env.AddNodeToTestSuite(test_node, ['small_tests'], 'run_validator_test_py')
73
33 # Source generation: 74 # Source generation:
34 # 75 #
35 # dfagen : Regenerate any autogenerated source files. 76 # dfagen : Regenerate any autogenerated source files.
36 77
37 generate = False 78 dfa_aliases = 'dfagen', 'dfaclean', 'dfacheckdecoder'
38 if 'dfagen' in COMMAND_LINE_TARGETS or 'dfaclean' in COMMAND_LINE_TARGETS: 79
39 generate = True 80 generate = any(a in COMMAND_LINE_TARGETS for a in dfa_aliases)
40 81
41 if generate: 82 if generate:
42 if not env.Bit('host_linux'): 83 if not env.Bit('host_linux'):
43 raise UserError('Right now DFA generation is only supported on Linux') 84 raise UserError('Right now DFA generation is only supported on Linux')
44 85
45 # Source generation step 1: Build generator of ragel files. 86 # Source generation step 1: Build generator of ragel files.
46 # 87 #
47 # We have generator which reads .def files and produced automaton definition. 88 # We have generator which reads .def files and produced automaton definition.
48 # 89 #
49 # Ragel is included in most Linux distributions, but it's not standard tool 90 # Ragel is included in most Linux distributions, but it's not standard tool
50 # on MacOS/Windows thus we only support gneration of automata under Linux. 91 # on MacOS/Windows thus we only support gneration of automata under Linux.
51 # This also means that we don't need to make sure gen_dfa.cc is portable to 92 # This also means that we don't need to make sure gen_dfa.cc is portable to
52 # non-POSIX platforms (in particular it's not Windows compatible). 93 # non-POSIX platforms (in particular it's not Windows compatible).
53 94
54 env_gen_dfa = env.Clone() 95 env_gen_dfa = env.Clone()
55 env_gen_dfa.Append(CCFLAGS=['-std=c++0x', '-DNACL_TRUSTED_BUT_NOT_TCB']) 96 env_gen_dfa.Append(CCFLAGS=['-std=c++0x', '-DNACL_TRUSTED_BUT_NOT_TCB'])
56 97
57 gen_dfa = env_gen_dfa.ComponentProgram( 98 gen_dfa = env_gen_dfa.ComponentProgram(
58 'gen_dfa', 99 'gen_dfa',
59 ['unreviewed/gen_dfa.cc']) 100 ['unreviewed/gen_dfa.cc'])
60 101
61 # Source generation step 2: Generate decoder automatas. 102 # Source generation step 2: Generate decoder automata.
62 # 103 #
63 # Now we are back to conditionally defining the large automata generated 104 # Now we are back to conditionally defining the large automata generated
64 # by gen_dfa. 105 # by gen_dfa.
65 106
66 def MakeAutomaton(bits, automaton, dfa_gen_actions, ragel_flags): 107 def MakeAutomaton(bits, automaton, dfa_gen_actions, ragel_flags):
67 rl_file = '%s_x86_%s_instruction.rl' % (automaton, bits) 108 rl_file = '%s_x86_%s_instruction.rl' % (automaton, bits)
68 109
69 # We are cheating here: there are two autogenerated files: 110 # We are cheating here: there are two autogenerated files:
70 # .rl and _consts.c, but we only track .rl one. This is safe because 111 # .rl and _consts.c, but we only track .rl one. This is safe because
71 # _consts.c file includes constants referenced by .rl file and if .rl 112 # _consts.c file includes constants referenced by .rl file and if .rl
72 # file is not changed _consts.c is guaranteed to be the same (reverse 113 # file is not changed _consts.c is guaranteed to be the same (reverse
73 # is not true). 114 # is not true).
115
74 const_file = '%s/%s_x86_%s_instruction_consts.c' % ( 116 const_file = '%s/%s_x86_%s_instruction_consts.c' % (
75 val_src_dir, automaton, bits) 117 val_src_dir, automaton, bits)
76 118
77 exe_path = '${STAGING_DIR}/${PROGPREFIX}gen_dfa${PROGSUFFIX}'
78 env.Command( 119 env.Command(
79 target=rl_file, 120 target=rl_file,
80 source=[exe_path] + INST_DEFS, 121 source=[gen_dfa] + INST_DEFS,
81 action=( 122 action=(
82 '${SOURCES[0]} -o ${TARGET} -c %s -m %s -d %s %s') % ( 123 '${SOURCES[0]} -o ${TARGET} -c %s -m %s -d %s %s') % (
83 # Const file (-c): not tracked by SCONS (see above) 124 # Const file (-c): not tracked by SCONS (see above)
84 const_file, 125 const_file,
85 # Argument for CPU type (-m): either "ia32" or "amd64". 126 # Argument for CPU type (-m): either "ia32" or "amd64".
86 {'32': 'ia32', '64': 'amd64'}[bits], 127 {'32': 'ia32', '64': 'amd64'}[bits],
87 # (-d): 128 # (-d):
88 dfa_gen_actions, 129 dfa_gen_actions,
89 # pass inst defs as remaining parameters 130 # pass inst defs as remaining parameters
90 ' '.join('${SOURCES[%d]}' % (i+1) 131 ' '.join('${SOURCES[%d]}' % (i + 1)
91 for i in range(len(INST_DEFS))) 132 for i in range(len(INST_DEFS)))
92 ) 133 )
93 ) 134 )
94 c_file = '%s_x86_%s.c' % (automaton, bits) 135 c_file = '%s_x86_%s.c' % (automaton, bits)
95 c_full_filename = '%s/%s' % (val_src_dir, c_file) 136 c_full_filename = '%s/%s' % (val_src_dir, c_file)
96 env.Command( 137 env.Command(
97 target=c_file, 138 target=c_file,
98 source=['unreviewed/%s_x86_%s.rl' % (automaton, bits), rl_file], 139 source=['unreviewed/%s_x86_%s.rl' % (automaton, bits), rl_file],
99 action=['%s %s -LL -I%s ${SOURCES[0]} -o ${TARGET}' % ( 140 action=['%s %s -LL -I%s ${SOURCES[0]} -o ${TARGET}' % (
100 ragel_binary, ragel_flags, rl_src_dir)] 141 ragel_binary, ragel_flags, rl_src_dir)]
101 ) 142 )
102 143
103 def InjectGeneratedFileHeader(target, source, env): 144 def InjectGeneratedFileHeader(target, source, env):
104 source_filename = source[0].get_abspath() 145 source_filename = source[0].get_abspath()
105 target_filename = target[0].get_abspath() 146 target_filename = target[0].get_abspath()
106 architecture = {'x86_32': 'ia32', 147 architecture = {'x86_32': 'ia32',
107 'x86_64': 'x86-64'}[target_filename[-8:-2]] 148 'x86_64': 'x86-64'}[target_filename[-8:-2]]
149
108 with open(source_filename, 'r') as source_file: 150 with open(source_filename, 'r') as source_file:
109 with open(target_filename, 'w') as target_file: 151 comment, sep, rest = source_file.read().partition('*/')
110 target_file.write( 152 if sep == '':
111 """/* native_client/%s 153 raise UserError('Generated file %s does not have '
112 * THIS FILE IS AUTO-GENERATED. DO NOT EDIT. 154 'header comment block' % source_filename)
113 * Compiled for %s mode.
114 */""" % (target_filename, architecture))
115 155
116 comment, sep, rest = source_file.read().partition('*/') 156 with open(target_filename, 'w') as target_file:
117 if sep == '': 157 target_file.write(
118 raise UserError('Generated file %s does not have ' 158 ('/* native_client/%s\n'
119 'header comment block' % source_filename) 159 ' * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\n'
120 target_file.write(rest) 160 ' * Compiled for %s mode.\n'
161 ' */') % (target_filename, architecture))
121 162
163 target_file.write(rest)
164
165 # inject comments and place files to appropriate dir
122 env.Command( 166 env.Command(
123 target=c_full_filename, 167 target=c_full_filename,
124 source=['%s/%s' % (rl_src_dir, c_file)], 168 source=['%s/%s' % (rl_src_dir, c_file)],
125 action=InjectGeneratedFileHeader 169 action=InjectGeneratedFileHeader
126 ) 170 )
127 171
128 return rl_file, c_file, c_full_filename 172 return rl_file, c_file, c_full_filename
129 173
130 decoder32 = MakeAutomaton( 174 decoder32 = MakeAutomaton(
131 '32', 'decoder', 175 '32', 'decoder',
132 'check_access,opcode,parse_operands_states,mark_data_fields', 176 'check_access,opcode,parse_operands_states,mark_data_fields',
133 '-T0') 177 '-T0')
134 validator32 = MakeAutomaton( 178 validator32 = MakeAutomaton(
135 '32', 'validator', 179 '32', 'validator',
136 ('check_access,opcode,parse_operands,parse_operands_states,' 180 ('check_access,opcode,parse_operands,parse_operands_states,'
137 'instruction_name,mark_data_fields,nacl-forbidden,' 181 'instruction_name,mark_data_fields,nacl-forbidden,'
138 'imm_operand_action,rel_operand_action'), 182 'imm_operand_action,rel_operand_action'),
139 '-G2') 183 '-G2')
140 decoder64 = MakeAutomaton( 184 decoder64 = MakeAutomaton(
141 '64', 'decoder', 185 '64', 'decoder',
142 'check_access,opcode,parse_operands_states,mark_data_fields', 186 'check_access,opcode,parse_operands_states,mark_data_fields',
143 '-T0') 187 '-T0')
144 validator64 = MakeAutomaton( 188 validator64 = MakeAutomaton(
145 '64', 'validator', 189 '64', 'validator',
146 ('opcode,instruction_name,mark_data_fields,imm_operand_action,' 190 ('opcode,instruction_name,mark_data_fields,imm_operand_action,'
147 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,' 191 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,'
148 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,' 192 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,'
149 'parse_ymm_operands,parse_relative_operands,' 193 'parse_ymm_operands,parse_relative_operands,'
150 'parse_immediate_operands,parse_operands_states,' 194 'parse_immediate_operands,parse_operands_states,'
151 'parse_operand_positions'), 195 'parse_operand_positions'),
152 '-GT2') 196 '-GT2')
153 197
154 automata = list(decoder32 + validator32 + decoder64 + validator64) 198 automata = list(decoder32 + validator32 + decoder64 + validator64)
155 199
200 # Prepair 'dfacheckdecoder' test.
201 #
202 # In this test, all acceptable instructions are enumerated
203 # by DFA traversal, and for each one objdump output and
204 # DFA-based decoder output are compared.
205 # It takes few hours to run the test, so it's not included
206 # into any suits and is supposed to be run manually when
207 # changes are made to DFA definitions.
208 # Also, since DFA generation is currently linux-only,
209 # this test is somewhat platform-dependent as well.
210
211 test_env = env.Clone()
212 test_env.Append(
213 CCFLAGS=['-g', '-Wno-unused-function'],
214 LINKFLAGS='-g',
215 CPPPATH='unreviewed')
216
217 test_dfa_object = test_env.Object('unreviewed/test_dfa.c')
218
219 objdump, gas = env.Command(
220 target=['objdump', 'gas'],
221 source=['obtain_binutils.py'],
222 action='python ${SOURCES[0]} ${TARGETS[0]} ${TARGETS[1]}'
223 )
224
225 check_decoders = []
226
227 for bits in ('32', '64'):
228 (one_valid_instr_rl,) = env.Command(
229 target='one_valid_instruction_x86_%s.rl' % bits,
230 source=[gen_dfa] + INST_DEFS,
231 action=('${SOURCES[0]} -o ${TARGET} %s '
232 '-d check_access,rex_prefix,vex_prefix,opcode '
233 '-d parse_operands_states,parse_operands,instruction_name '
234 '-m %s') % (
235 ' '.join('${SOURCES[%d]}' % (i + 1)
Nick Bray 2012/08/09 20:16:20 Line breaking a generator expression makes it hard
Vlad Shcherbina 2012/08/10 15:17:39 Since this construction relies on the fact that SO
236 for i in range(len(INST_DEFS))),
237 {'32': 'ia32', '64': 'amd64'}[bits])
238 )
239
240 include_dir = one_valid_instr_rl.dir.get_abspath()
241
242 (one_instr_dot,) = env.Command(
243 target='one_instruction_x86_%s.dot' % bits,
244 source=[
245 'unreviewed/one_instruction_x86_%s.rl' % bits,
246 one_valid_instr_rl],
247 action=[
248 '%s -V -I%s ${SOURCES[0]} -o ${TARGET}' %
249 (ragel_binary, include_dir)]
250 )
251
252 test_dfa_transitions = test_env.Command(
253 target='test_dfa_transitions_x86_%s.c' % bits,
254 source=['unreviewed/parse_dfa.py', one_instr_dot],
255 action='python ${SOURCES[0]} <"${SOURCES[1]}" >"${TARGET}"'
Nick Bray 2012/08/09 20:16:20 Not critical for this CL, but I'd delegate the log
Vlad Shcherbina 2012/08/10 15:17:39 I'll make it in a separate small CL.
256 )
257
258 test_dfa_transitions_object = test_env.Object(test_dfa_transitions)
259
260 test_dfa = test_env.ComponentProgram(
261 'test_dfa_x86_%s' % bits,
262 [test_dfa_object, test_dfa_transitions_object])
263
264 fast_temp_for_test = '/dev/shm'
265
266 (check_decoder,) = env.Command(
267 target='objdump_test_fake_file_%s' % bits,
268 source=[
269 'unreviewed/run_objdump_test.py',
270 gas,
271 objdump,
272 decoder_test,
273 'unreviewed/decoder_test_one_file.sh',
274 test_dfa,
275 ],
276 action=[(
277 'python ${SOURCES[0]} '
278 '--gas="${SOURCES[1]} --%s" '
279 '--objdump="${SOURCES[2]}" '
280 '--decoder="${SOURCES[3]}" '
281 '--tester="${SOURCES[4]}" '
282 '-- '
283 '"${SOURCES[5]}" "%s"'
284 ) % (bits, fast_temp_for_test),
285 ])
286 check_decoders.append(check_decoder)
287
288 SideEffect(fast_temp_for_test, check_decoders)
289
156 env.AlwaysBuild(env.Alias('dfagen', automata)) 290 env.AlwaysBuild(env.Alias('dfagen', automata))
157 env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata))) 291 env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata)))
158 292 env.AlwaysBuild(env.Alias('dfacheckdecoder', check_decoders))
159 # Generate 32 and 64 bit versions of decoders and validators. Both libraries
160 # are used for command-line decoder and validator those detect specific
161 # architecture of the ELF file provided.
162 env.ComponentLibrary('dfa_validate_x86_32',
163 ['gen/validator_x86_32.c'])
164 env.ComponentLibrary('dfa_validate_x86_64',
165 ['gen/validator_x86_64.c'])
166 env.ComponentLibrary('dfa_decode_x86_32',
167 ['gen/decoder_x86_32.c'])
168 env.ComponentLibrary('dfa_decode_x86_64',
169 ['gen/decoder_x86_64.c'])
170
171 # Glue library called from service runtime. The source file depends on the
172 # target architecture.
173 caller_lib_bits = None
174 if env.Bit('target_x86_32'):
175 caller_lib_bits = '32'
176 if env.Bit('target_x86_64'):
177 caller_lib_bits = '64'
178 if caller_lib_bits:
179 caller_lib = 'dfa_validate_caller_x86_%s' % caller_lib_bits
180 env.ComponentLibrary(caller_lib,
181 ['unreviewed/dfa_validate_%s.c' % caller_lib_bits])
182
183 # Command-line decoder.
184 env.ComponentProgram(
185 'decoder_test',
186 ['unreviewed/decoder_test.c'],
187 EXTRA_LIBS=['dfa_decode_x86_32', 'dfa_decode_x86_64'])
188
189 # Command-line validator.
190 validator_test_exe = env.ComponentProgram(
191 'validator_test',
192 ['unreviewed/validator_test.c'],
193 EXTRA_LIBS=['dfa_validate_x86_32', 'dfa_validate_x86_64'])
194
195 # Python-based regression test. TODO(pasko): remove it when validator_tests are
196 # migrated to be able to run with the new validator.
197 if env.Bit('validator_ragel'):
198 test_node = env.CommandTest('validator_test_py.out',
199 command=['${PYTHON}',
200 env.File('unreviewed/validator_test.py'),
201 validator_test_exe])
202 env.AddNodeToTestSuite(test_node, ['small_tests'], 'run_validator_test_py')
OLDNEW
« no previous file with comments | « no previous file | src/trusted/validator_ragel/obtain_binutils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698