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