1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#!/usr/bin/env python
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Copyright 2013 the V8 project authors. All rights reserved.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Redistribution and use in source and binary forms, with or without
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# modification, are permitted provided that the following conditions are
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# met:
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Redistributions of source code must retain the above copyright
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       notice, this list of conditions and the following disclaimer.
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Redistributions in binary form must reproduce the above
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       copyright notice, this list of conditions and the following
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       disclaimer in the documentation and/or other materials provided
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       with the distribution.
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Neither the name of Google Inc. nor the names of its
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       contributors may be used to endorse or promote products derived
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       from this software without specific prior written permission.
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# This script executes the passed command line using the Native Client
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 'sel_ldr' container. It is derived from android-run.py.
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport os
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom os.path import join, dirname, abspath
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport subprocess
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport sys
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport tempfile
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Check(output, errors):
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  failed = any([s.startswith('/system/bin/sh:') or s.startswith('ANDROID')
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                for s in output.split('\n')])
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 if failed else 0
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Execute(cmdline):
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (fd_out, outname) = tempfile.mkstemp()
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (fd_err, errname) = tempfile.mkstemp()
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  process = subprocess.Popen(
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    args=cmdline,
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shell=True,
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stdout=fd_out,
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stderr=fd_err,
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  )
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  exit_code = process.wait()
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  os.close(fd_out)
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  os.close(fd_err)
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  output = file(outname).read()
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  errors = file(errname).read()
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  os.unlink(outname)
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  os.unlink(errname)
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sys.stdout.write(output)
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sys.stderr.write(errors)
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return exit_code or Check(output, errors)
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Escape(arg):
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def ShouldEscape():
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for x in arg:
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if not x.isalnum() and x != '-' and x != '_':
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return True
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return False
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return arg if not ShouldEscape() else '"%s"' % (arg.replace('"', '\\"'))
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef WriteToTemporaryFile(data):
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (fd, fname) = tempfile.mkstemp()
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  os.close(fd)
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  tmp_file = open(fname, "w")
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  tmp_file.write(data)
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  tmp_file.close()
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return fname
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef GetNaClArchFromNexe(nexe):
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try:
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p = subprocess.Popen(['file', nexe], stdout=subprocess.PIPE)
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    out, err = p.communicate()
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lines = out.split('\n')
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if lines[0].find(": ELF 32-bit LSB executable, Intel 80386") > 0:
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return "x86_32"
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if lines[0].find(": ELF 64-bit LSB executable, x86-64") > 0:
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return "x86_64"
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  except:
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print 'file ' + sys.argv[1] + ' failed'
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return None
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef GetNaClResources(nexe):
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_sdk_dir = os.environ["NACL_SDK_ROOT"]
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_arch = GetNaClArchFromNexe(nexe)
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if sys.platform.startswith("linux"):
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    platform = "linux"
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elif sys.platform == "darwin":
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    platform = "mac"
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  else:
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print("NaCl V8 testing is supported on Linux and MacOS only.")
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sys.exit(1)
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if nacl_arch is "x86_64":
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    toolchain = platform + "_x86_glibc"
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sel_ldr = "sel_ldr_x86_64"
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    irt = "irt_core_x86_64.nexe"
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    libdir = "lib64"
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elif nacl_arch is "x86_32":
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    toolchain = platform + "_x86_glibc"
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sel_ldr = "sel_ldr_x86_32"
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    irt = "irt_core_x86_32.nexe"
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    libdir = "lib32"
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elif nacl_arch is "arm":
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print("NaCl V8 ARM support is not ready yet.")
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sys.exit(1)
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  else:
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print("Invalid nexe %s" % nexe)
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sys.exit(1)
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_sel_ldr = os.path.join(nacl_sdk_dir, "tools", sel_ldr)
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_irt = os.path.join(nacl_sdk_dir, "tools", irt)
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_ld_so = os.path.join(nacl_sdk_dir, "toolchain", toolchain,
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            "x86_64-nacl", libdir, "runnable-ld.so")
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nacl_lib_path = os.path.join(nacl_sdk_dir, "toolchain", toolchain,
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               "x86_64-nacl", libdir)
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (nacl_sdk_dir, nacl_sel_ldr, nacl_irt, nacl_ld_so, nacl_lib_path)
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Main():
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (len(sys.argv) == 1):
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print("Usage: %s <command-to-run-on-device>" % sys.argv[0])
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return 1
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  args = [Escape(arg) for arg in sys.argv[1:]]
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  (nacl_sdk_dir, nacl_sel_ldr, nacl_irt, nacl_ld_so,
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   nacl_lib_path) = GetNaClResources(sys.argv[1])
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  # sel_ldr Options:
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  # -c -c: disable validation (for performance)
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  # -a: allow file access
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  # -B <irt>: load the IRT
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  command = ' '.join([nacl_sel_ldr, '-c', '-c', '-a', '-B', nacl_irt, '--',
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     nacl_ld_so, '--library-path', nacl_lib_path] + args)
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  error_code = Execute(command)
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return error_code
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochif __name__ == '__main__':
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sys.exit(Main())
152