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

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: rebase 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 benchmark = env.Command(
66 target='validator_ragel_benchmark_py.out',
67 source=['validator_benchmark.py', validator_test_exe, env.GetIrtNexe()],
68 action='${SOURCES[0]} ${SOURCES[1]} ${SOURCES[2]}'
69 )
70
71 env.AlwaysBuild(env.Alias('dfavalidatorbenchmark', benchmark))
72
73 # Python-based regression test. TODO(pasko): remove it when validator_tests are
74 # migrated to be able to run with the new validator.
75 if env.Bit('validator_ragel'):
76 test_node = env.CommandTest('validator_test_py.out',
77 command=['${PYTHON}',
78 env.File('unreviewed/validator_test.py'),
79 validator_test_exe])
80 env.AddNodeToTestSuite(test_node, ['small_tests'], 'run_validator_test_py')
81
33 # Source generation: 82 # Source generation:
34 # 83 #
35 # dfagen : Regenerate any autogenerated source files. 84 # dfagen : Regenerate any autogenerated source files.
36 85
37 generate = False 86 dfa_aliases = 'dfagen', 'dfaclean', 'dfacheckdecoder'
38 if 'dfagen' in COMMAND_LINE_TARGETS or 'dfaclean' in COMMAND_LINE_TARGETS: 87
39 generate = True 88 generate = any(a in COMMAND_LINE_TARGETS for a in dfa_aliases)
40 89
41 if generate: 90 if generate:
42 if not env.Bit('host_linux'): 91 if not env.Bit('host_linux'):
43 raise UserError('Right now DFA generation is only supported on Linux') 92 raise UserError('Right now DFA generation is only supported on Linux')
44 93
45 # Source generation step 1: Build generator of ragel files. 94 # Source generation step 1: Build generator of ragel files.
46 # 95 #
47 # We have generator which reads .def files and produced automaton definition. 96 # We have generator which reads .def files and produced automaton definition.
48 # 97 #
49 # Ragel is included in most Linux distributions, but it's not standard tool 98 # 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. 99 # 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 100 # 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). 101 # non-POSIX platforms (in particular it's not Windows compatible).
53 102
54 env_gen_dfa = env.Clone() 103 env_gen_dfa = env.Clone()
55 env_gen_dfa.Append(CCFLAGS=['-std=c++0x', '-DNACL_TRUSTED_BUT_NOT_TCB']) 104 env_gen_dfa.Append(CCFLAGS=['-std=c++0x', '-DNACL_TRUSTED_BUT_NOT_TCB'])
56 105
57 gen_dfa = env_gen_dfa.ComponentProgram( 106 gen_dfa = env_gen_dfa.ComponentProgram(
58 'gen_dfa', 107 'gen_dfa',
59 ['unreviewed/gen_dfa.cc']) 108 ['unreviewed/gen_dfa.cc'])
60 109
61 # Source generation step 2: Generate decoder automatas. 110 # Source generation step 2: Generate decoder automata.
62 # 111 #
63 # Now we are back to conditionally defining the large automata generated 112 # Now we are back to conditionally defining the large automata generated
64 # by gen_dfa. 113 # by gen_dfa.
65 114
66 def MakeAutomaton(bits, automaton, dfa_gen_actions, ragel_flags): 115 def MakeAutomaton(bits, automaton, dfa_gen_actions, ragel_flags):
67 rl_file = '%s_x86_%s_instruction.rl' % (automaton, bits) 116 rl_file = '%s_x86_%s_instruction.rl' % (automaton, bits)
68 117
69 # We are cheating here: there are two autogenerated files: 118 # We are cheating here: there are two autogenerated files:
70 # .rl and _consts.c, but we only track .rl one. This is safe because 119 # .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 120 # _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 121 # file is not changed _consts.c is guaranteed to be the same (reverse
73 # is not true). 122 # is not true).
123
74 const_file = '%s/%s_x86_%s_instruction_consts.c' % ( 124 const_file = '%s/%s_x86_%s_instruction_consts.c' % (
75 val_src_dir, automaton, bits) 125 val_src_dir, automaton, bits)
76 126
77 exe_path = '${STAGING_DIR}/${PROGPREFIX}gen_dfa${PROGSUFFIX}'
78 env.Command( 127 env.Command(
79 target=rl_file, 128 target=rl_file,
80 source=[exe_path] + INST_DEFS, 129 source=[gen_dfa] + INST_DEFS,
81 action=( 130 action=(
82 '${SOURCES[0]} -o ${TARGET} -c %s -m %s -d %s %s') % ( 131 '${SOURCES[0]} -o ${TARGET} -c %s -m %s -d %s %s') % (
83 # Const file (-c): not tracked by SCONS (see above) 132 # Const file (-c): not tracked by SCONS (see above)
84 const_file, 133 const_file,
85 # Argument for CPU type (-m): either "ia32" or "amd64". 134 # Argument for CPU type (-m): either "ia32" or "amd64".
86 {'32': 'ia32', '64': 'amd64'}[bits], 135 {'32': 'ia32', '64': 'amd64'}[bits],
87 # (-d): 136 # (-d):
88 dfa_gen_actions, 137 dfa_gen_actions,
89 # pass inst defs as remaining parameters 138 # pass inst defs as remaining parameters
90 ' '.join('${SOURCES[%d]}' % (i+1) 139 ' '.join('${SOURCES[%d]}' % (i + 1)
91 for i in range(len(INST_DEFS))) 140 for i in range(len(INST_DEFS)))
92 ) 141 )
93 ) 142 )
94 c_file = '%s_x86_%s.c' % (automaton, bits) 143 c_file = '%s_x86_%s.c' % (automaton, bits)
95 c_full_filename = '%s/%s' % (val_src_dir, c_file) 144 c_full_filename = '%s/%s' % (val_src_dir, c_file)
96 env.Command( 145 env.Command(
97 target=c_file, 146 target=c_file,
98 source=['unreviewed/%s_x86_%s.rl' % (automaton, bits), rl_file], 147 source=['unreviewed/%s_x86_%s.rl' % (automaton, bits), rl_file],
99 action=['%s %s -LL -I%s ${SOURCES[0]} -o ${TARGET}' % ( 148 action=['%s %s -LL -I%s ${SOURCES[0]} -o ${TARGET}' % (
100 ragel_binary, ragel_flags, rl_src_dir)] 149 ragel_binary, ragel_flags, rl_src_dir)]
101 ) 150 )
102 151
103 def InjectGeneratedFileHeader(target, source, env): 152 def InjectGeneratedFileHeader(target, source, env):
104 source_filename = source[0].get_abspath() 153 source_filename = source[0].get_abspath()
105 target_filename = target[0].get_abspath() 154 target_filename = target[0].get_abspath()
106 architecture = {'x86_32': 'ia32', 155 architecture = {'x86_32': 'ia32',
107 'x86_64': 'x86-64'}[target_filename[-8:-2]] 156 'x86_64': 'x86-64'}[target_filename[-8:-2]]
157
108 with open(source_filename, 'r') as source_file: 158 with open(source_filename, 'r') as source_file:
109 with open(target_filename, 'w') as target_file: 159 comment, sep, rest = source_file.read().partition('*/')
110 target_file.write( 160 if sep == '':
111 """/* native_client/%s 161 raise UserError('Generated file %s does not have '
112 * THIS FILE IS AUTO-GENERATED. DO NOT EDIT. 162 'header comment block' % source_filename)
113 * Compiled for %s mode.
114 */""" % (target_filename, architecture))
115 163
116 comment, sep, rest = source_file.read().partition('*/') 164 with open(target_filename, 'w') as target_file:
117 if sep == '': 165 target_file.write(
118 raise UserError('Generated file %s does not have ' 166 ('/* native_client/%s\n'
119 'header comment block' % source_filename) 167 ' * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\n'
120 target_file.write(rest) 168 ' * Compiled for %s mode.\n'
169 ' */') % (target_filename, architecture))
121 170
171 target_file.write(rest)
172
173 # inject comments and place files to appropriate dir
122 env.Command( 174 env.Command(
123 target=c_full_filename, 175 target=c_full_filename,
124 source=['%s/%s' % (rl_src_dir, c_file)], 176 source=['%s/%s' % (rl_src_dir, c_file)],
125 action=InjectGeneratedFileHeader 177 action=InjectGeneratedFileHeader
126 ) 178 )
127 179
128 return rl_file, c_file, c_full_filename 180 return rl_file, c_file, c_full_filename
129 181
130 decoder32 = MakeAutomaton( 182 decoder32 = MakeAutomaton(
131 '32', 'decoder', 183 '32', 'decoder',
132 'check_access,opcode,parse_operands_states,mark_data_fields', 184 'check_access,opcode,parse_operands_states,mark_data_fields',
133 '-T0') 185 '-T0')
134 validator32 = MakeAutomaton( 186 validator32 = MakeAutomaton(
135 '32', 'validator', 187 '32', 'validator',
136 ('check_access,opcode,parse_operands,parse_operands_states,' 188 ('check_access,opcode,parse_operands,parse_operands_states,'
137 'instruction_name,mark_data_fields,nacl-forbidden,' 189 'instruction_name,mark_data_fields,nacl-forbidden,'
138 'imm_operand_action,rel_operand_action'), 190 'imm_operand_action,rel_operand_action'),
139 '-G2') 191 '-G2')
140 decoder64 = MakeAutomaton( 192 decoder64 = MakeAutomaton(
141 '64', 'decoder', 193 '64', 'decoder',
142 'check_access,opcode,parse_operands_states,mark_data_fields', 194 'check_access,opcode,parse_operands_states,mark_data_fields',
143 '-T0') 195 '-T0')
144 validator64 = MakeAutomaton( 196 validator64 = MakeAutomaton(
145 '64', 'validator', 197 '64', 'validator',
146 ('opcode,instruction_name,mark_data_fields,imm_operand_action,' 198 ('opcode,instruction_name,mark_data_fields,imm_operand_action,'
147 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,' 199 'rel_operand_action,nacl-forbidden,parse_nonwrite_registers,'
148 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,' 200 'parse_x87_operands,parse_mmx_operands,parse_xmm_operands,'
149 'parse_ymm_operands,parse_relative_operands,' 201 'parse_ymm_operands,parse_relative_operands,'
150 'parse_immediate_operands,parse_operands_states,' 202 'parse_immediate_operands,parse_operands_states,'
151 'parse_operand_positions'), 203 'parse_operand_positions'),
152 '-GT2') 204 '-GT2')
153 205
154 automata = list(decoder32 + validator32 + decoder64 + validator64) 206 automata = list(decoder32 + validator32 + decoder64 + validator64)
155 207
208 # Prepair 'dfacheckdecoder' test.
209 #
210 # In this test, all acceptable instructions are enumerated
211 # by DFA traversal, and for each one objdump output and
212 # DFA-based decoder output are compared.
213 # It takes few hours to run the test, so it's not included
214 # into any suits and is supposed to be run manually when
215 # changes are made to DFA definitions.
216 # Also, since DFA generation is currently linux-only,
217 # this test is somewhat platform-dependent as well.
218
219 test_env = env.Clone()
220 test_env.Append(
221 CCFLAGS=['-g', '-Wno-unused-function'],
222 LINKFLAGS='-g',
223 CPPPATH='unreviewed')
224
225 test_dfa_object = test_env.Object('unreviewed/test_dfa.c')
226
227 objdump, gas = env.Command(
228 target=['objdump', 'gas'],
229 source=['obtain_binutils.py'],
230 action='python ${SOURCES[0]} ${TARGETS[0]} ${TARGETS[1]}'
231 )
232
233 check_decoders = []
234
235 for bits in ('32', '64'):
236 (one_valid_instr_rl,) = env.Command(
237 target='one_valid_instruction_x86_%s.rl' % bits,
238 source=[gen_dfa] + INST_DEFS,
239 action=('${SOURCES[0]} -o ${TARGET} %s '
240 '-d check_access,rex_prefix,vex_prefix,opcode '
241 '-d parse_operands_states,parse_operands,instruction_name '
242 '-m %s') % (
243 ' '.join('${SOURCES[%d]}' % (i + 1)
244 for i in range(len(INST_DEFS))),
245 {'32': 'ia32', '64': 'amd64'}[bits])
246 )
247
248 include_dir = one_valid_instr_rl.dir.get_abspath()
249
250 (one_instr_dot,) = env.Command(
251 target='one_instruction_x86_%s.dot' % bits,
252 source=[
253 'unreviewed/one_instruction_x86_%s.rl' % bits,
254 one_valid_instr_rl],
255 action=[
256 '%s -V -I%s ${SOURCES[0]} -o ${TARGET}' %
257 (ragel_binary, include_dir)]
258 )
259
260 test_dfa_transitions = test_env.Command(
261 target='test_dfa_transitions_x86_%s.c' % bits,
262 source=['unreviewed/parse_dfa.py', one_instr_dot],
263 action='python ${SOURCES[0]} <"${SOURCES[1]}" >"${TARGET}"'
264 )
265
266 test_dfa_transitions_object = test_env.Object(test_dfa_transitions)
267
268 test_dfa = test_env.ComponentProgram(
269 'test_dfa_x86_%s' % bits,
270 [test_dfa_object, test_dfa_transitions_object])
271
272 fast_temp_for_test = '/dev/shm'
273
274 (check_decoder,) = env.Command(
275 target='objdump_test_fake_file_%s' % bits,
276 source=[
277 'unreviewed/run_objdump_test.py',
278 gas,
279 objdump,
280 decoder_test,
281 'unreviewed/decoder_test_one_file.sh',
282 test_dfa,
283 ],
284 action=[(
285 'python ${SOURCES[0]} '
286 '--gas="${SOURCES[1]} --%s" '
287 '--objdump="${SOURCES[2]}" '
288 '--decoder="${SOURCES[3]}" '
289 '--tester="${SOURCES[4]}" '
290 '-- '
291 '"${SOURCES[5]}" "%s"'
292 ) % (bits, fast_temp_for_test),
293 ])
294 check_decoders.append(check_decoder)
295
296 SideEffect(fast_temp_for_test, check_decoders)
297
156 env.AlwaysBuild(env.Alias('dfagen', automata)) 298 env.AlwaysBuild(env.Alias('dfagen', automata))
157 env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata))) 299 env.AlwaysBuild(env.Alias('dfaclean', action=map(Delete, automata)))
158 300 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')
203
204 benchmark = env.Command(
205 target='validator_ragel_benchmark_py.out',
206 source=['validator_benchmark.py', validator_test_exe, env.GetIrtNexe()],
207 action='${SOURCES[0]} ${SOURCES[1]} ${SOURCES[2]}'
208 )
209
210 env.AlwaysBuild(env.Alias('dfavalidatorbenchmark', benchmark))
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