1#!/usr/bin/env python3
2
3import glob, os, pipes, sys, subprocess
4
5
6device_id = os.environ.get('SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER')
7iossim_run_verbose = os.environ.get('SANITIZER_IOSSIM_RUN_VERBOSE')
8wait_for_debug = os.environ.get('SANITIZER_IOSSIM_RUN_WAIT_FOR_DEBUGGER')
9
10if not device_id:
11  raise EnvironmentError("Specify SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER to select which simulator to use.")
12
13for e in [
14  "ASAN_OPTIONS",
15  "TSAN_OPTIONS",
16  "UBSAN_OPTIONS",
17  "LSAN_OPTIONS",
18  "APPLE_ASAN_INIT_FOR_DLOPEN",
19  "ASAN_ACTIVATION_OPTIONS",
20  "MallocNanoZone",
21]:
22  if e in os.environ:
23    os.environ["SIMCTL_CHILD_" + e] = os.environ[e]
24
25find_atos_cmd = 'xcrun -sdk iphonesimulator -f atos'
26atos_path = subprocess.run(find_atos_cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True).stdout.decode().strip()
27for san in ['ASAN', 'TSAN', 'UBSAN', 'LSAN']:
28  os.environ[f'SIMCTL_CHILD_{san}_SYMBOLIZER_PATH'] = atos_path
29
30prog = sys.argv[1]
31exit_code = None
32if prog == 'rm':
33  # The simulator and host actually share the same file system so we can just
34  # execute directly on the host.
35  rm_args = []
36  for arg in sys.argv[2:]:
37    if '*' in arg or '?' in arg:
38      # Don't quote glob pattern
39      rm_args.append(arg)
40    else:
41      # FIXME(dliew): pipes.quote() is deprecated
42      rm_args.append(pipes.quote(arg))
43  rm_cmd_line = ["/bin/rm"] + rm_args
44  rm_cmd_line_str = ' '.join(rm_cmd_line)
45  # We use `shell=True` so that any wildcard globs get expanded by the shell.
46
47  if iossim_run_verbose:
48    print("RUNNING: \t{}".format(rm_cmd_line_str), flush=True)
49
50  exitcode = subprocess.call(rm_cmd_line_str, shell=True)
51
52else:
53  cmd = ["xcrun", "simctl", "spawn", "--standalone"]
54
55  if wait_for_debug:
56    cmd.append("--wait-for-debugger")
57
58  cmd.append(device_id)
59  cmd += sys.argv[1:]
60
61  if iossim_run_verbose:
62    print("RUNNING: \t{}".format(" ".join(cmd)), flush=True)
63
64  exitcode = subprocess.call(cmd)
65if exitcode > 125:
66  exitcode = 126
67sys.exit(exitcode)
68