3062df40f602ff9b16b8e22bc820f404ab926324
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / build.scons
1 # -*- python -*-
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
4 # found in the LICENSE file.
5
6 import platform
7 import os
8
9 Import('env')
10
11 env.Append(CPPPATH=['${TARGET_ROOT}/gen'])
12
13 # normally comment out -- uncomment out to test the pedantic removal
14 # check below.
15 #if env.Bit('linux') or env.Bit('mac'):
16 #  env.FilterOut(CCFLAGS=['-pedantic'])
17 #  env.FilterOut(CCFLAGS=['-Wall'])
18
19 if env.Bit('windows'):
20   syscall_impl = 'win/nacl_syscall_impl.c'
21 else:
22   syscall_impl = 'posix/nacl_syscall_impl.c'
23
24
25 # TODO GENERATED CODE
26 GENERATED='${TARGET_ROOT}/gen/native_client/src/trusted/service_runtime'
27 env.Command(target=env.File(GENERATED + '/nacl_syscall_handlers.c'),
28             source=[syscall_impl, 'nacl_syscall_handlers_gen.py'],
29             action=[Action('${PYTHON} ${SOURCES[1]} ${SYSCALL_GEN_FLAGS}'
30                            ' -i ${SOURCE} -o ${TARGET}'),
31                     ],
32             )
33
34
35 # ----------------------------------------------------------
36 # TODO(robertm): this library is too big and needs to be split up
37 #                for easier unit testing
38 ldr_inputs = [
39     'dyn_array.c',
40     'elf_util.c',
41     'load_file.c',
42     'nacl_all_modules.c',
43     'nacl_app_thread.c',
44     'nacl_bootstrap_channel_error_reporter.c',
45     'nacl_copy.c',
46     'nacl_desc_effector_ldr.c',
47     'nacl_desc_postmessage.c',
48     'nacl_error_gio.c',
49     'nacl_error_log_hook.c',
50     'nacl_globals.c',
51     'nacl_kernel_service.c',
52     'nacl_resource.c',
53     'nacl_reverse_host_interface.c',
54     'nacl_reverse_quota_interface.c',
55     'nacl_runtime_host_interface.c',
56     'nacl_secure_service.c',
57     'nacl_signal_common.c',
58     'nacl_stack_safety.c',
59     'nacl_syscall_common.c',
60     GENERATED + '/nacl_syscall_handlers.c',
61     'nacl_syscall_hook.c',
62     'nacl_text.c',
63     'nacl_valgrind_hooks.c',
64     'name_service/default_name_service.c',
65     'name_service/name_service.c',
66     'sel_addrspace.c',
67     'sel_ldr.c',
68     'sel_ldr_standard.c',
69     'sel_ldr_thread_interface.c',
70     'sel_mem.c',
71     'sel_qualify.c',
72     'sel_validate_image.c',
73     'sys_exception.c',
74     'sys_fdio.c',
75     'sys_filename.c',
76     'sys_futex.c',
77     'sys_imc.c',
78     'sys_list_mappings.c',
79     'sys_memory.c',
80     'sys_parallel_io.c',
81     'thread_suspension_common.c',
82     'thread_suspension_unwind.c',
83 ]
84
85 if env.Bit('build_x86_32'):
86   ldr_inputs += [
87       'arch/x86/nacl_ldt_x86.c',
88       'arch/x86_32/nacl_app_32.c',
89       'arch/x86_32/nacl_switch_32.S',
90       'arch/x86_32/nacl_switch_all_regs_32.c',
91       'arch/x86_32/nacl_switch_all_regs_asm_32.S',
92       'arch/x86_32/nacl_switch_to_app_32.c',
93       'arch/x86_32/nacl_syscall_32.S',
94       'arch/x86_32/nacl_tls_32.c',
95       'arch/x86_32/sel_addrspace_x86_32.c',
96       'arch/x86_32/sel_ldr_x86_32.c',
97       'arch/x86_32/sel_rt_32.c',
98       'arch/x86_32/springboard.S',
99       'arch/x86_32/tramp_32.S',
100       ]
101 elif env.Bit('build_x86_64'):
102   ldr_inputs += [
103       'arch/x86/nacl_ldt_x86.c',
104       'arch/x86_64/nacl_app_64.c',
105       'arch/x86_64/nacl_switch_64.S',
106       'arch/x86_64/nacl_switch_to_app_64.c',
107       'arch/x86_64/nacl_syscall_64.S',
108       'arch/x86_64/nacl_tls_64.c',
109       'arch/x86_64/sel_ldr_x86_64.c',
110       'arch/x86_64/sel_rt_64.c',
111       'arch/x86_64/tramp_64.S',
112       ]
113   if env.Bit('windows'):
114     # We assemble the .asm assembly file with the Microsoft assembler
115     # because we need to generate x86-64 Windows unwind info, which
116     # the GNU assembler we use elsewhere does not support.
117     win64_asm_env = env.Clone(ASCOM='ml64 $ASFLAGS /c /Fo$TARGET $SOURCES')
118     ldr_inputs += [
119         'arch/x86_64/sel_addrspace_win_x86_64.c',
120         'arch/x86_64/fnstcw.S',
121         'arch/x86_64/fxsaverstor.S',
122         win64_asm_env.ComponentObject('arch/x86_64/nacl_switch_unwind_win.asm')]
123   else:
124     ldr_inputs += ['arch/x86_64/sel_addrspace_posix_x86_64.c']
125   if env.Bit('x86_64_zero_based_sandbox'):
126     env.Append(CPPDEFINES=['-DNACL_X86_64_ZERO_BASED_SANDBOX=1'])
127   else:
128     env.Append(CPPDEFINES=['-DNACL_X86_64_ZERO_BASED_SANDBOX=0'])
129 elif env.Bit('build_arm'):
130   ldr_inputs += [
131     'arch/arm/nacl_app.c',
132     'arch/arm/nacl_switch_to_app_arm.c',
133     'arch/arm/sel_rt.c',
134     'arch/arm/nacl_tls.c',
135     'arch/arm/sel_ldr_arm.c',
136     'arch/arm/sel_addrspace_arm.c',
137     'arch/arm/nacl_switch.S',
138     'arch/arm/nacl_syscall.S',
139     'arch/arm/tramp_arm.S',
140   ]
141 elif env.Bit('build_mips32'):
142   ldr_inputs += [
143     'arch/mips/nacl_app.c',
144     'arch/mips/nacl_switch_to_app_mips.c',
145     'arch/mips/sel_rt.c',
146     'arch/mips/nacl_tls.c',
147     'arch/mips/sel_ldr_mips.c',
148     'arch/mips/sel_addrspace_mips.c',
149     'arch/mips/nacl_switch.S',
150     'arch/mips/nacl_syscall.S',
151     'arch/mips/tramp_mips.S',
152   ]
153
154 if env.Bit('windows'):
155   ldr_inputs += [
156     'win/addrspace_teardown.c',
157     'win/nacl_ldt.c',
158     'win/nacl_thread_nice.c',
159     'win/sel_memory.c',
160     'win/sel_segments.c',
161   ]
162 elif env.Bit('mac'):
163   # Rely on the c preprocessor to discover where the mach interface definitions
164   # are located.
165   env.Command(
166      [GENERATED + '/exc.defs'], [],
167      "echo '#include <mach/exc.defs>' | ${CC} ${CFLAGS} -E - > ${TARGET}")
168   env.Command(
169      [GENERATED + '/nacl_exc.h', GENERATED + '/nacl_exc_server.c'],
170      ['osx/run_mig.py', GENERATED + '/exc.defs'],
171      '${PYTHON} ${SOURCES} ${TARGETS}')
172   ldr_inputs += [
173     GENERATED + '/nacl_exc_server.c',
174     'osx/crash_filter.c',
175     'osx/mach_exception_handler.c',
176     'osx/mach_thread_map.c',
177     'osx/nacl_ldt.c',
178     'osx/nacl_thread_nice.c',
179     'osx/outer_sandbox.c',
180     'posix/addrspace_teardown.c',
181     'posix/sel_memory.c',
182     'posix/x86/sel_segments.c',
183   ]
184 elif env.Bit('linux'):
185   ldr_inputs += [
186     'linux/nacl_bootstrap_args.c',
187     'linux/nacl_thread_nice.c',
188     'linux/r_debug.c',
189     'linux/reserved_at_zero.c',
190     'posix/addrspace_teardown.c',
191     'posix/sel_memory.c',
192   ]
193   if env.Bit('build_x86'):
194     ldr_inputs += [
195       'linux/x86/nacl_ldt.c',
196       'posix/x86/sel_segments.c',
197     ]
198   elif env.Bit('build_arm'):
199     ldr_inputs += [
200       'linux/arm/sel_segments.c',
201     ]
202   elif env.Bit('build_mips32'):
203     ldr_inputs += [
204       'linux/mips/sel_segments.c',
205     ]
206
207
208 # -------------------------------------------------------------
209 # Add OS and architecture specific signal handling files.
210 #
211 if env.Bit('windows'):
212   ldr_inputs += [
213     'win/debug_exception_handler.c',
214     'win/debug_exception_handler_standalone.c',
215     'win/nacl_signal_stack.c',
216     'win/thread_handle_map.c',
217     'win/thread_suspension.c',
218     'win/sel_addrspace_win.c',
219   ]
220   if env.Bit('target_x86_32'):
221     ldr_inputs += [
222       'win/nacl_signal_32.c',
223     ]
224   elif env.Bit('target_x86_64'):
225     ldr_inputs += [
226       'win/exception_patch/exit_fast.S',
227       'win/exception_patch/intercept.S',
228       'win/exception_patch/ntdll_patch.c',
229       'win/nacl_signal_64.c',
230     ]
231   else:
232     raise Exception("Unsupported target")
233
234 if env.Bit('linux'):
235   ldr_inputs += [
236       'linux/thread_suspension.c',
237       'posix/nacl_signal_stack.c',
238       'posix/sel_addrspace_posix.c'
239       ]
240   if env.Bit('target_arm'):
241     ldr_inputs += ['linux/nacl_signal_arm.c']
242   elif env.Bit('target_mips32'):
243     ldr_inputs += ['linux/nacl_signal_mips.c']
244   elif env.Bit('target_x86_32'):
245     ldr_inputs += ['linux/nacl_signal_32.c']
246   elif env.Bit('target_x86_64'):
247     ldr_inputs += ['linux/nacl_signal_64.c']
248   else:
249     raise Exception("Unsupported target")
250
251   nacl_signal_env = env.Clone()
252   if env.Bit('target_x86_32'):
253     # nacl_signal.c needs to be compiled without the stack protector
254     # on i386.
255     # See https://code.google.com/p/nativeclient/issues/detail?id=3581.
256     nacl_signal_env.FilterOut(CCFLAGS=['-fstack-protector',
257                                        '-fstack-protector-all'])
258     nacl_signal_env.Append(CCFLAGS=['-fno-stack-protector'])
259   ldr_inputs += [nacl_signal_env.ComponentObject('linux/nacl_signal.c')]
260
261 if env.Bit('mac'):
262   ldr_inputs += [
263       'osx/thread_suspension.c',
264       'posix/nacl_signal_stack.c',
265       'posix/sel_addrspace_posix.c'
266       ]
267   if env.Bit('target_x86_32'):
268     ldr_inputs += ['osx/nacl_signal_32.c']
269   elif env.Bit('target_x86_64'):
270     ldr_inputs += ['osx/nacl_signal_64.c']
271   else:
272     raise Exception("Unsupported target")
273
274 if env.Bit('windows'):
275   ldr_inputs += ['win/vm_hole.c']
276 else:
277   ldr_inputs += ['generic/vm_hole.c']
278
279
280 syscall_gen_flags = '-a ${TARGET_ARCHITECTURE} -s ${TARGET_SUBARCH}'
281
282 env.Append(SYSCALL_GEN_FLAGS=syscall_gen_flags)
283
284 env.DualLibrary('sel', ldr_inputs)
285
286 env.DualLibrary('sel_main_chrome', ['sel_main_chrome.c'])
287
288 env.DualLibrary('sel_main', ['sel_main.c'])
289
290 env.DualLibrary('env_cleanser', ['env_cleanser.c'])
291
292 env.DualLibrary('nacl_error_code',
293                 ['nacl_error_code.c',
294                  ])
295
296 if env.Bit('windows'):
297   env.ComponentLibrary('sel_test', 'win/mmap_test_check.cc')
298 elif env.Bit('mac'):
299   env.ComponentLibrary('sel_test', 'osx/mmap_test_check.cc')
300 elif env.Bit('linux'):
301   env.ComponentLibrary('sel_test', 'linux/mmap_test_check.cc')
302 else:
303   raise AssertionError('Unsupported host OS')
304
305
306 # NOTE(robertm): these extra libs were orignially only added to the
307 #                sel_ldr binary
308 # TODO(robertm): see who really needs them and remove
309 if env.Bit('windows'):
310   env.Append(
311       LIBS = [
312           'ws2_32',
313           'kernel32',
314           'advapi32',
315           'winmm',
316 # TODO(gregoryd): ntdll.lib is required for sem_get_value implementation but
317 # it is available in Windows DDK only. The DDK is not
318 # in third_party, but we might need to add it if we want to use it.
319 #          'ntdll',
320       ],
321   )
322
323 sel_ldr_libs = ['sel',
324                 'sel_main',
325                 'desc_cacheability',
326                 'env_cleanser',
327                 'nacl_error_code',
328                 'manifest_proxy',
329                 'simple_service',
330                 'thread_interface',
331                 'gio_wrapped_desc',
332                 'nonnacl_srpc',
333                 'nrd_xfer',
334                 'nacl_perf_counter',
335                 'nacl_base',
336                 'imc',
337                 'nacl_fault_inject',
338                 'nacl_interval',
339                 'platform',
340                 'platform_qual_lib',
341                 'validators',
342                 ]
343
344 if not env.Bit('coverage_enabled') or not env.Bit('windows'):
345   sel_main_objs = [env.ComponentObject('nacl_test_injection_main.c')]
346   SEL_LDR_NODE = env.ComponentProgram('sel_ldr', sel_main_objs,
347                                       EXTRA_LIBS=['sel_main'])
348   if env.Bit('mac'):
349     # This target exists only to check that the service_runtime code
350     # can successfully be linked into a Mac OS X dynamic library.  Our
351     # assembly code needs to be PIC-friendly and linkable in this
352     # context, because it is linked into a dynamic library inside
353     # Chromium, and OS X is strict about TEXTRELs.  Without this, the
354     # standalone build won't catch some mistakes that can break the
355     # Chromium build.  Linking a dylib here works because -fPIC is the
356     # default for all C code on OS X.
357     dylib_env = env.Clone()
358     dylib_env.Append(LINKFLAGS=['-bundle'])
359     dylib_env.ComponentProgram('dummy_sel_ldr.dylib', sel_main_objs,
360                                EXTRA_LIBS=['sel_main'])
361
362   # NOTE: we do not have segments on ARM
363   if env.Bit('build_x86'):
364     env.ComponentProgram('nacl_ldt_unittest',
365                          'nacl_ldt_unittest.c',
366                          EXTRA_LIBS=['sel',
367                                      'env_cleanser',
368                                      'nacl_perf_counter',
369                                      'gio_wrapped_desc',
370                                      'nacl_fault_inject',
371                                      'platform',
372                                      ])
373
374   env.SDKInstallBin('sel_ldr', SEL_LDR_NODE)
375
376 if env.Bit('linux') and env.Bit('target_x86_64'):
377   sel_ldr_seccomp_node = env.ComponentProgram('sel_ldr_seccomp',
378                                               ['sel_ldr_seccomp_main.c'],
379                                               EXTRA_LIBS=['sel_main',
380                                                           'seccomp_bpf'])
381   env.SDKInstallBin('sel_ldr_seccomp', sel_ldr_seccomp_node)
382
383 env.EnsureRequiredBuildWarnings()
384
385 # Bootstrap loader used on Linux.
386 if (env.Bit('linux') and not env.Bit('built_elsewhere')):
387   bootstrap_env = env.Clone()
388   bootstrap_env.Replace(CLANG_OPTS='')
389   bootstrap_env.FilterOut(CCFLAGS=['-fstack-protector', '-fPIC', '-fPIE',
390                                    '-pedantic', '$COVERAGE_CCFLAGS'],
391                           CFLAGS=['-Wdeclaration-after-statement'])
392   bootstrap_env.Append(CCFLAGS=['-fno-pic', '-fno-PIC', '-fno-pie', '-fno-pie',
393                                 '-fno-stack-protector'])
394
395   # TODO(bbudge) Remove -Qunused-arguments when Clang supports -fno-pic.
396   if env.Bit('clang'):
397     bootstrap_env.Append(CCFLAGS=['-ffreestanding',
398                                   '-U__STDC_HOSTED__',
399                                   '-D__STDC_HOSTED__=1',
400                                   '-Qunused-arguments'])
401
402   if env.Bit('target_x86_64'):
403     ld_emul = 'elf_x86_64'
404     if env.Bit('x86_64_zero_based_sandbox'):
405       # For the zero-based 64-bit sandbox, we want to reserve 44GB of address
406       # space: 4GB for the program plus 40GB of guard pages.  Due to a binutils
407       # bug (see http://sourceware.org/bugzilla/show_bug.cgi?id=13400), the
408       # amount of address space that the linker can pre-reserve is capped
409       # at 4GB. For proper reservation, GNU ld version 2.22 or higher
410       # needs to be used.
411       #
412       # Without the bug fix, trying to reserve 44GB will result in
413       # pre-reserving the entire capped space of 4GB.  This tricks the run-time
414       # into thinking that we can mmap up to 44GB.  This is unsafe as it can
415       # overwrite the run-time program itself and/or other programs.  Because
416       # of this, we only reserve 4GB.
417       #
418       # TODO(arbenson): remove these comments and reserve 44GB once the
419       # necessary ld version becomes standard.
420       reserve_top = '0x100000000'
421       # The reserve_top value gets interpreted as a pointer in
422       # linux/nacl_bootstrap.c.  By default, mcmodel is set to small,
423       # which restricts code and data to the first 2GB.  With
424       # mcmodel set to small or medium, the reserve_top value is
425       # truncated, which produces an error.  With mcmodel set to large,
426       # there is no restriction on the code and data, so we can
427       # safely set reserve_top to 0x100000000.
428       bootstrap_env.Append(CCFLAGS=['-mcmodel=large'])
429     else:
430       reserve_top = '0x0'
431   elif env.Bit('target_x86_32'):
432     ld_emul = 'elf_i386'
433     reserve_top = '0x40000000'
434   elif env.Bit('target_arm'):
435     ld_emul = 'armelf_linux_eabi'
436     reserve_top = '0x40002000'
437   elif env.Bit('target_mips32'):
438     ld_emul = 'elf32ltsmip'
439     reserve_top = '0x40008000'
440
441   bootstrap_obj = bootstrap_env.ComponentObject('linux/nacl_bootstrap.c')
442   bootstrap_raw = bootstrap_env.Command(
443       'nacl_bootstrap_raw',
444       [bootstrap_obj],
445       ("env CXX='${CXX}' ${PYTHON} %s " +
446        '-m %s --build-id -static -z max-page-size=0x1000 ' +
447        '--defsym RESERVE_TOP=%s --script %s -o ${TARGET} ${SOURCES}') %
448       (bootstrap_env.File('linux/ld_bfd.py'), ld_emul, reserve_top,
449        bootstrap_env.File('linux/nacl_bootstrap.x')),
450       )
451
452   # The bootstrap program is used as an intermediate program so it
453   # must be built in the current build environment.
454   munge_env = env['BUILD_ENV']
455   bootstrap_munge = munge_env.Program(
456       'nacl_bootstrap_munge_phdr',
457       ['linux/nacl_bootstrap_munge_phdr.c'],
458       LIBS=['elf'])
459
460   bootstrap_prog = bootstrap_env.Command(
461       'nacl_helper_bootstrap',
462       [bootstrap_env.File('linux/nacl_bootstrap_munge_phdr.py'),
463        bootstrap_munge, bootstrap_raw],
464       '${PYTHON} ${SOURCES} ${TARGET}'
465       )
466   bootstrap_out = bootstrap_env.Install('${STAGING_DIR}', bootstrap_prog)
467
468   bootstrap_env.Alias('nacl_helper_bootstrap', bootstrap_out)
469   bootstrap_env.Requires(SEL_LDR_NODE, bootstrap_out)
470   env.SDKInstallBin('nacl_helper_bootstrap', bootstrap_prog)
471
472 # ----------------------------------------------------------
473 # Unit Tests
474 # ----------------------------------------------------------
475
476 # NOTE: uses validator
477 # TODO(robertm): break this test up in smaller pieces with more managable
478 #                dependencies
479 gtest_env = env.MakeGTestEnv()
480
481 unittest_inputs = [
482     'mmap_unittest.cc',
483     'unittest_main.cc',
484     'sel_memory_unittest.cc',
485     # nacl_sync_unittest.cc was testing the wrong (i.e., too low level) API
486     # re-enable it when it has been converted to the C API.
487     #'nacl_sync_unittest.cc',
488     'sel_mem_test.cc',
489     'sel_ldr_test.cc',
490     'thread_suspension_test.cc',
491 ]
492
493 if not env.Bit('coverage_enabled') or not env.Bit('windows'):
494   unit_tests_exe = gtest_env.ComponentProgram(
495       'service_runtime_tests',
496       unittest_inputs,
497       EXTRA_LIBS=['sel',
498                   'env_cleanser',
499                   'manifest_proxy',
500                   'simple_service',
501                   'thread_interface',
502                   'gio_wrapped_desc',
503                   'nonnacl_srpc',
504                   'nrd_xfer',
505                   'nacl_perf_counter',
506                   'nacl_base',
507                   'imc',
508                   'nacl_fault_inject',
509                   'nacl_interval',
510                   'platform',
511                   'sel_test',
512                   ])
513
514   node = gtest_env.CommandTest(
515       'gtest_output.xml.out',
516       size='large', # This test suite is fairly slow on Windows XP.
517       command=[unit_tests_exe, '--gtest_output=xml:${TARGET}'])
518   gtest_env.AddNodeToTestSuite(node, ['small_tests'],
519       'run_service_runtime_tests')
520
521
522 if not env.Bit('coverage_enabled') or not env.Bit('windows'):
523   format_string_test_exe = env.ComponentProgram(
524       'format_string_test',
525       ['format_string_test.c'],
526       EXTRA_LIBS=['sel',
527                   'env_cleanser',
528                   'nacl_perf_counter',
529                   ])
530
531   node = env.CommandTest(
532       'format_string_test.out',
533       command=[format_string_test_exe])
534   env.AddNodeToTestSuite(node, ['small_tests'], 'run_format_string_test')
535
536
537 if env.Bit('target_x86_32'):
538   arch_testdata_dir = 'testdata/x86_32'
539 elif env.Bit('target_x86_64'):
540   arch_testdata_dir = 'testdata/x86_64'
541 else:
542   arch_testdata_dir = 'testdata/' + env['TARGET_ARCHITECTURE']
543
544 untrusted_env = env.MakeUntrustedNativeEnv()
545 hello_world_nexe = untrusted_env.File('$STAGING_DIR/hello_world.nexe')
546
547 # Doesn't work on windows under coverage.
548 # TODO(bradnelson): fix this to work on windows under coverage.
549 if ((not env.Bit('windows') or not env.Bit('coverage_enabled')) and
550     env.Bit('nacl_static_link')):
551   # NOTE: uses validator
552   mmap_test_objs = [env.ComponentObject('mmap_test.c')]
553   mmap_test_exe = env.ComponentProgram(
554       'mmap_test',
555       mmap_test_objs,
556       EXTRA_LIBS=['sel',
557                   'env_cleanser',
558                   'manifest_proxy',
559                   'simple_service',
560                   'thread_interface',
561                   'gio_wrapped_desc',
562                   'nonnacl_srpc',
563                   'nrd_xfer',
564                   'nacl_perf_counter',
565                   'nacl_base',
566                   'imc',
567                   'nacl_fault_inject',
568                   'nacl_interval',
569                   'platform',
570                   'sel_test',
571                   ])
572
573   mmap_test_command = env.AddBootstrap(mmap_test_exe, [hello_world_nexe])
574
575   # TODO(robertm): This test emits lots of messages to stderr
576   node = env.CommandTest (
577       "mmap_test.out",
578       command=mmap_test_command,
579       # TODO(mseaborn): Extend this test to cover the case where the
580       # dynamic code segment is present.
581       osenv='NACL_DISABLE_DYNAMIC_LOADING=1')
582   env.AddNodeToTestSuite(node, ['medium_tests'], 'run_trusted_mmap_test')
583
584
585 if env.Bit('linux'):
586   nacl_bootstrap_prereservation_test_exe = env.ComponentProgram(
587       'nacl_bootstrap_prereservation_test',
588       ['linux/nacl_bootstrap_prereservation_test.c'],
589       EXTRA_LIBS=['sel'])
590
591   bootstrap, bootstrap_arg = env.GetBootstrap()
592   node = env.CommandTest(
593       'nacl_bootstrap_prereservation_test.out',
594       command=env.AddBootstrap(nacl_bootstrap_prereservation_test_exe, []))
595   env.AddNodeToTestSuite(node, ['small_tests'],
596                          'run_nacl_bootstrap_prereservation_test')
597
598
599 # also seems to have issues with windows coverage or VMs
600 # NOTE: uses validator
601 is_broken = env.Bit('coverage_enabled') or env.Bit('running_on_vm')
602 nacl_sync_cond_test_exe = env.ComponentProgram(
603     'nacl_sync_cond_test',
604     ['nacl_sync_cond_test.c'],
605     EXTRA_LIBS=['sel',
606                 'env_cleanser',
607                 'manifest_proxy',
608                 'simple_service',
609                 'thread_interface',
610                 'gio_wrapped_desc',
611                 'nonnacl_srpc',
612                 'nrd_xfer',
613                 'nacl_perf_counter',
614                 'nacl_base',
615                 'imc',
616                 'nacl_fault_inject',
617                 'nacl_interval',
618                 'platform',
619                 ])
620 node = env.CommandTest(
621     'nacl_sync_cond_test.out',
622     command=[nacl_sync_cond_test_exe])
623 env.AddNodeToTestSuite(node,
624                        ['medium_tests'],
625                        'run_nacl_sync_cond_test',
626                        is_broken=is_broken)
627
628
629 env_cleanser_test_exe = env.ComponentProgram('env_cleanser_test',
630                                              ['env_cleanser_test.c'],
631                                              EXTRA_LIBS=['env_cleanser',
632                                                          'gio_wrapped_desc',
633                                                          ])
634 node = env.CommandTest(
635     'env_cleanser_test.out',
636     command=[env_cleanser_test_exe])
637 env.AddNodeToTestSuite(node, ['small_tests'], 'run_env_cleanser_test')
638
639 # Test nacl_resource
640
641 nacl_resource_test_exe = env.ComponentProgram('nacl_resource_test',
642                                               ['nacl_resource_test.c'],
643                                               EXTRA_LIBS=['sel'])
644 node = env.CommandTest(
645     'nacl_resource_test.out',
646     command=[nacl_resource_test_exe])
647 env.AddNodeToTestSuite(node, ['small_tests'], 'run_nacl_resource_test')
648
649 # Test nacl_signal
650 if env.Bit('linux'):
651   if (not env.Bit('coverage_enabled') and
652       not env.Bit('target_arm') and
653       not env.Bit('target_mips32') and
654       not env.IsRunningUnderValgrind()):
655     nacl_signal_exe = env.ComponentProgram(
656         'nacl_signal_unittest', 'nacl_signal_unittest.c',
657         EXTRA_LIBS=['sel'])
658     node = env.CommandTest('nacl_signal_unittest.out',
659                            command=[nacl_signal_exe])
660
661     env.AddNodeToTestSuite(node, ['small_tests'], 'run_nacl_signal_test')
662
663   test_prog = env.ComponentProgram('nacl_signal_frame_test',
664                                    'nacl_signal_frame_test.c',
665                                    EXTRA_LIBS=['sel'])
666   node = env.CommandTest('nacl_signal_frame_test.out',
667                          command=[test_prog],
668                          declares_exit_status=True,
669                          using_nacl_signal_handler=True)
670   env.AddNodeToTestSuite(node, ['small_tests'], 'run_signal_frame_test')
671
672 if env.Bit('windows') and env.Bit('target_x86_64'):
673   test_prog = env.ComponentProgram('patch_ntdll_test',
674                                    'win/exception_patch/ntdll_test.c',
675                                    EXTRA_LIBS=['sel',
676                                                'nacl_fault_inject',
677                                                'nacl_interval',
678                                                'platform',
679                                                ])
680   node = env.CommandTest('patch_ntdll_test.out',
681                          command=[test_prog], declares_exit_status=True)
682   env.AddNodeToTestSuite(node, ['small_tests'], 'run_patch_ntdll_test')
683
684   intercept_test_prog = env.ComponentProgram(
685       'ntdll_intercept_test', 'win/exception_patch/intercept_test.c',
686       EXTRA_LIBS=sel_ldr_libs)
687   node = env.CommandTest(
688       'ntdll_intercept_test.out',
689       command=[intercept_test_prog, 'test_intercept'],
690       exit_status='untrusted_segfault',
691       stdout_golden=env.File('win/exception_patch/intercept_test.stdout'))
692   env.AddNodeToTestSuite(node, ['small_tests'], 'run_ntdll_intercept_test')
693   node = env.CommandTest(
694       'ntdll_fallback_test.out',
695       command=[intercept_test_prog, 'test_fallback'],
696       exit_status='untrusted_segfault',
697       stdout_golden=env.File('win/exception_patch/fallback_test.stdout'))
698   env.AddNodeToTestSuite(node, ['small_tests'], 'run_ntdll_fallback_test')
699
700
701 check_test_exe = env.ComponentProgram('nacl_check_test',
702                                       ['nacl_check_test.c'],
703                                       EXTRA_LIBS=['sel',
704                                                   'env_cleanser',
705                                                   'nacl_perf_counter',
706                                                   'gio_wrapped_desc',
707                                                   'nacl_fault_inject',
708                                                   'nacl_interval',
709                                                   'platform',
710                                                   ])
711 node = env.CommandTest(
712     'check_test.out',
713     command=[check_test_exe, '-C'])
714 env.AddNodeToTestSuite(node, ['small_tests'], 'run_check_test')
715
716
717 ABORT_EXIT = '17'  # magic, see nacl_check_test.c
718
719
720 node = env.CommandTest(
721     'check_test_death.out',
722     command=[check_test_exe, '-c'],
723     exit_status=ABORT_EXIT)  # abort()
724 env.AddNodeToTestSuite(node, ['small_tests'], 'run_check_test_death')
725
726
727 if env.Bit('debug'):
728   node = env.CommandTest(
729       'dcheck_test_death.out',
730       command=[check_test_exe, '-d'],
731       exit_status=ABORT_EXIT)  # abort()
732 else:
733   node = env.CommandTest(
734       'dcheck_test_death.out',
735       command=[check_test_exe, '-d'])  # no abort()
736 env.AddNodeToTestSuite(node, ['small_tests'], 'run_dcheck_test_death')
737
738
739 node = env.CommandTest(
740     'check_test_always_death.out',
741     command=[check_test_exe, '-s', '0', '-C'])  # no abort
742 env.AddNodeToTestSuite(node, ['small_tests'], 'run_check_test_always_death')
743
744
745 node = env.CommandTest(
746     'check_test_always_death_abort.out',
747     command=[check_test_exe, '-s', '0', '-c'],
748     exit_status=ABORT_EXIT)  # abort
749 env.AddNodeToTestSuite(
750     node,
751     ['small_tests'],
752     'run_check_test_always_death_abort')
753
754
755 node = env.CommandTest(
756     'dcheck_test_never_death.out',
757     command=[check_test_exe, '-s', '0', '-d'])  # no abort
758 env.AddNodeToTestSuite(node, ['small_tests'], 'run_dcheck_test_never_death')
759
760
761 node = env.CommandTest(
762     'dcheck_test_always_death.out',
763     command=[check_test_exe, '-s', '1', '-d'],
764     exit_status=ABORT_EXIT)  # abort()
765 env.AddNodeToTestSuite(
766     node,
767     ['small_tests'],
768     'run_dcheck_test_always_death')
769
770
771 # Mac does not support thread local storage via "__thread" so do not run this
772 # test on Mac.
773 # This test is thread-unsafe by design. Don't run it under Valgrind.
774 if not env.Bit('mac') and not env.IsRunningUnderValgrind():
775   nacl_tls_unittest = env.ComponentProgram('nacl_tls_unittest',
776                                            ['nacl_tls_unittest.c'],
777                                            EXTRA_LIBS=['platform'])
778   node = env.CommandTest('nacl_tls_unittest.out',
779                          command=[nacl_tls_unittest])
780
781   env.AddNodeToTestSuite(node, ['small_tests'], 'run_nacl_tls_unittest')
782
783 # Test that sel_ldr does not crash if the executable file cannot be opened.
784 node = env.CommandSelLdrTestNacl(
785     'sel_ldr_exe_not_found.out',
786     'name_of_file_that_does_not_exist.nexe',
787     exit_status='1')
788 env.AddNodeToTestSuite(node, ['small_tests'], 'run_sel_ldr_exe_not_found_test')
789
790 # Check that "-F" makes sel_ldr stop after loading the nexe but before running
791 # it.
792 nullptr_nexe = untrusted_env.GetTranslatedNexe(
793     untrusted_env.File('$STAGING_DIR/nullptr$PROGSUFFIX'))
794
795 node = env.CommandSelLdrTestNacl(
796     'fuzz_nullptr_test.out',
797     nullptr_nexe,
798     sel_ldr_flags=['-F'])
799 env.AddNodeToTestSuite(node, ['small_tests'], 'run_fuzz_nullptr_test')
800
801 # Test hello_world binary with obsolete, non-ragel based validator.
802 if (not env.Bit('validator_ragel') and env.Bit('target_x86')
803     and env.Bit('nacl_static_link')):
804   node = env.CommandSelLdrTestNacl(
805       'dfa_hwd.out',
806       hello_world_nexe,
807       stdout_golden = env.File('testdata/hello_world.stdout'),
808       stderr_golden = env.File('testdata/non_dfa_validator_hello.stderr'),
809       filter_regex = '"^(Hello, World!)$' + '|' +
810         '^[[][^]]*[]] (USING OBSOLETE NON-DFA-BASED VALIDATOR!)$"',
811       filter_group_only = 'true',
812       )
813   env.AddNodeToTestSuite(node, ['medium_tests', 'validator_tests'],
814                          'run_dfa_validator_hello_world_test')
815
816 if env.Bit('target_mips32'):
817   text_region_start = 0x00020000
818   # Use arbitrary non-page-aligned addresses for data and rodata.
819   rodata_region_start = 0x10020094
820   data_region_start = 0x10030098
821   untrusted_env.Append(CPPFLAGS=['--pnacl-allow-native', '-arch', 'mips32'])
822   unaligned_data_objs = untrusted_env.ComponentObject(
823       'arch/mips/unaligned_data_test.S')
824   unaligned_data_nexe = untrusted_env.ComponentProgram(
825       'unaligned_data.nexe',
826       unaligned_data_objs,
827       LINKFLAGS=['-nostdlib',
828                  '--pnacl-allow-native', '-arch', 'mips32',
829                  '-Wn,--section-start=.text=0x%x' % (text_region_start),
830                  '-Wn,--section-start=.rodata=0x%x' % (rodata_region_start),
831                  '-Wn,--section-start=.data=0x%x' % (data_region_start)],
832       ASFLAGS=['--pnacl-allow-native', '-arch', 'mips32'])
833
834   rodata_region_start_irt = 0x3eef0000
835   text_region_start_irt = 0x0fc00000
836   unaligned_data_irt_nexe = untrusted_env.ComponentProgram(
837       'unaligned_data_irt.nexe',
838       unaligned_data_objs,
839       LINKFLAGS=['-nostdlib',
840                  '--pnacl-allow-native', '-arch', 'mips32',
841                  '-Wl,-Ttext-segment=0x%x' % text_region_start_irt,
842                  '-Wl,-Trodata-segment=0x%x' % rodata_region_start_irt],
843       ASFLAGS=['--pnacl-allow-native', '-arch', 'mips32'])
844 else:
845   unaligned_data_nexe = env.File(os.path.join(arch_testdata_dir,
846                                               'unaligned_data.nexe'))
847   unaligned_data_irt_nexe = env.File(os.path.join(arch_testdata_dir,
848                                                   'unaligned_data_irt.nexe'))
849
850 node = env.CommandSelLdrTestNacl('unaligned_data.out', unaligned_data_nexe)
851 env.AddNodeToTestSuite(node, ['small_tests'], 'run_unaligned_data_test')
852
853 node = env.CommandSelLdrTestNacl(
854     'unaligned_data_irt.out',
855     unaligned_data_nexe,
856     sel_ldr_flags=['-B', unaligned_data_irt_nexe]
857     )
858 env.AddNodeToTestSuite(node, ['small_tests'], 'run_unaligned_data_irt_test')
859
860 # ----------------------------------------------------------
861 # Small tests with canned binaries
862 # ----------------------------------------------------------
863
864 if env.Bit('target_x86_64'):
865   node = env.CommandSelLdrTestNacl(
866       'hello_x32.out',
867       env.File(os.path.join(arch_testdata_dir, 'hello_x32.nexe')),
868       stdout_golden=env.File(os.path.join('${MAIN_DIR}',
869                                           'tests/hello_world',
870                                           'hello_world.stdout'))
871       )
872   env.AddNodeToTestSuite(node, ['small_tests'], 'run_hello_x32_test')
873
874 # ----------------------------------------------------------
875 # Integration Tests With Canned x86 Binaries
876 # ----------------------------------------------------------
877 # To update the canned tests run:
878 # ./scons platform=x86-64
879 # cp scons-out/nacl-x86-64/staging/{mandel.nexe,fib_*} \
880 #     src/trusted/service_runtime/testdata/x86_64/
881 # ./scons platform=x86-32
882 # cp scons-out/nacl-x86-32/staging/{mandel.nexe,fib_*} \
883 #     src/trusted/service_runtime/testdata/x86_32/
884
885 # TODO: Create integration test nexes for arm.
886 INTEGRATION_TESTS_X86 = [ 'mandel',
887                           'fib_scalar',
888                           'fib_array' ]
889 INTEGRATION_TESTS_X86_STDIN_OUT = ['$SCONSTRUCT_DIR/tests/mandel/test',
890                                    '$SCONSTRUCT_DIR/tests/fib/fib_scalar_test',
891                                    '$SCONSTRUCT_DIR/tests/fib/fib_array_test' ]
892
893 def AddIntegrationTest(test, location):
894   if not test or not location:
895     return
896
897   node = env.SelUniversalTest(
898       test + '_canned.out',
899       env.File(arch_testdata_dir + '/' + test + '.nexe'),
900       stdin = location + '.stdin',
901       stdout_golden = location + '.stdout',
902       )
903   env.AddNodeToTestSuite(node,
904                          ['medium_tests'],
905                          'run_%s_integration_test' % test)
906
907 if env.Bit('target_x86') and env.Bit('nacl_static_link'):
908   RE_HELLO = '^(Hello, World!)$'
909   RE_IDENT = '^\[[0-9,:.]*\] (e_ident\+1 = ELF)$'
910
911   node = env.CommandSelLdrTestNacl(
912       'nacl_log.out',
913       hello_world_nexe,
914       log_golden = env.File('testdata/hello_world.log'),
915       stdout_golden = env.File('testdata/hello_world.stdout'),
916       filter_regex = '"' + RE_HELLO + '|' + RE_IDENT + '"',
917       filter_group_only = 'true',
918       )
919   env.AddNodeToTestSuite(node, ['medium_tests'],
920                          'run_service_runtime_hello_world_test')
921
922   assert len(INTEGRATION_TESTS_X86) == len(INTEGRATION_TESTS_X86_STDIN_OUT)
923   map(AddIntegrationTest,
924       INTEGRATION_TESTS_X86,
925       INTEGRATION_TESTS_X86_STDIN_OUT)
926
927 # ----------------------------------------------------------
928 # Death Tests With Canned x86 Binaries
929 # ----------------------------------------------------------
930 ERROR_WHILE_LOADING = '"^(Error while loading).*' + '(:[^:]*)"'
931
932 # TODO: Create death test nexes for arm.
933 DEATH_TESTS_X86 = [ 'old_abi',  # hello_world.nexe with an old ABI version
934                     'integer_overflow_while_madvising',
935                     'negative_hole',
936                     'rodata_data_overlap',
937                     'data_not_last',
938                     'text_overlaps_rodata',
939                     'text_overlaps_data',
940                     'text_too_big' ]
941
942 NOT_AVAIL_X86_32 = [ ]
943
944 NOT_AVAIL_X86_64 = [ 'text_overlaps_rodata',
945                      'text_overlaps_data' ]
946
947 def AddDeathTest(test, skip):
948   if not test:
949     return
950
951   if test in skip:
952     print 'SKIPPING test ', test
953     return
954
955   # Use an arch-specific golden file if there is one.
956   # We can't use the SCons File .exists() method because that will
957   # look for the file in a scons-out directory.
958   stderr_file = env.File(os.path.join(arch_testdata_dir, test + '.stderr'))
959   if not os.path.exists(str(stderr_file)):
960     stderr_file = env.File(os.path.join('testdata', test + '.stderr'))
961
962   node = env.CommandSelLdrTestNacl(
963       test  + '.out',
964       env.File(arch_testdata_dir + '/' + test + '.nexe'),
965       stderr_golden = stderr_file,
966       filter_regex = ERROR_WHILE_LOADING,
967       filter_group_only = 'true',
968       exit_status = '1')
969   env.AddNodeToTestSuite(node, ['medium_tests'],
970                          'run_' + test + '_death_test')
971
972
973 if env.Bit('target_x86'):
974   if env.Bit('build_x86_32'):
975     skip = NOT_AVAIL_X86_32
976   else:
977     skip = NOT_AVAIL_X86_64
978
979   for death_test in DEATH_TESTS_X86:
980     AddDeathTest(death_test, skip)
981
982 # ----------------------------------------------------------
983 # More Death Tests
984 # ----------------------------------------------------------
985 if not env.Bit('coverage_enabled') or not env.Bit('windows'):
986   # NOTE: uses validator
987   sel_ldr_thread_death_test_exe = env.ComponentProgram(
988       'sel_ldr_thread_death_test',
989       ['sel_ldr_thread_death_test.c'],
990       EXTRA_LIBS=['sel',
991                   'env_cleanser',
992                   'manifest_proxy',
993                   'simple_service',
994                   'thread_interface',
995                   'gio_wrapped_desc',
996                   'nonnacl_srpc',
997                   'nrd_xfer',
998                   'nacl_perf_counter',
999                   'nacl_base',
1000                   'imc',
1001                   'nacl_fault_inject',
1002                   'nacl_interval',
1003                   'platform',
1004                   ])
1005
1006   # NaClAbort() behaves differently when code coverage is enabled: it
1007   # calls exit() rather than abort().
1008   if env.Bit('coverage_enabled'):
1009     expected_exit_status = 'naclabort_coverage'
1010   else:
1011     expected_exit_status = 'trusted_sigabrt'
1012   node = env.CommandTest(
1013       'sel_ldr_thread_death_test.out',
1014       command=[sel_ldr_thread_death_test_exe],
1015       exit_status=expected_exit_status)
1016
1017   # TODO(tuduce): Make it work on windows.
1018   env.AddNodeToTestSuite(node, ['medium_tests'],
1019                          'run_sel_ldr_thread_death_test',
1020                          is_broken=env.Bit('windows'))
1021
1022
1023 exe = env.ComponentProgram('nacl_error_gio_test',
1024                            ['nacl_error_gio_test.c'],
1025                            EXTRA_LIBS=sel_ldr_libs)
1026
1027 node = env.CommandTest('nacl_error_gio_test.out',
1028                        command=[exe, '-n', '1000'])
1029
1030 env.AddNodeToTestSuite(node, ['small_tests'],
1031                        'run_nacl_error_gio_test')
1032
1033 exe = env.ComponentProgram('nacl_error_log_test',
1034                             ['nacl_error_log_test.c'],
1035                             EXTRA_LIBS=sel_ldr_libs)
1036
1037 if env.Bit('coverage_enabled'):
1038   expected_exit = 'naclabort_coverage'
1039 else:
1040   expected_exit = 'trusted_sigabrt'
1041
1042 node = env.CommandTest(
1043   'nacl_error_log_test.out',
1044   command=[exe],
1045   exit_status=expected_exit,
1046   filter_regex='"(NaClCrashLogWriter.*)|(This is a test of the emergency.*)"',
1047   filter_group_only='true',
1048   stdout_golden=env.File('nacl_error_log_test.stdout'))
1049
1050 is_broken = env.Bit('host_windows') and env.Bit('coverage_enabled')
1051 env.AddNodeToTestSuite(node, ['small_tests'],
1052                        'run_nacl_error_log_test',
1053                        is_broken=is_broken)
1054
1055 dyn_array_test_exe = env.ComponentProgram('dyn_array_test',
1056                                           ['dyn_array_test.c'],
1057                                           EXTRA_LIBS=sel_ldr_libs)
1058
1059 node = env.CommandTest('dyn_array_test.out',
1060                        command=[dyn_array_test_exe])
1061
1062 env.AddNodeToTestSuite(node, ['small_tests'], 'run_dyn_array_test')