Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 # Copyright 2013 The Chromium 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 """Wrapper script for launching application within the sel_ldr.
      7 """
      8 
      9 import optparse
     10 import os
     11 import subprocess
     12 import sys
     13 
     14 import create_nmf
     15 import getos
     16 
     17 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
     18 NACL_SDK_ROOT = os.path.dirname(SCRIPT_DIR)
     19 
     20 if sys.version_info < (2, 6, 0):
     21   sys.stderr.write("python 2.6 or later is required run this script\n")
     22   sys.exit(1)
     23 
     24 
     25 class Error(Exception):
     26   pass
     27 
     28 
     29 def Log(msg):
     30   if Log.verbose:
     31     sys.stderr.write(str(msg) + '\n')
     32 Log.verbose = False
     33 
     34 
     35 def FindQemu():
     36   qemu_locations = [os.path.join(SCRIPT_DIR, 'qemu_arm'),
     37                     os.path.join(SCRIPT_DIR, 'qemu-arm')]
     38   qemu_locations += [os.path.join(path, 'qemu_arm')
     39                      for path in os.environ["PATH"].split(os.pathsep)]
     40   qemu_locations += [os.path.join(path, 'qemu-arm')
     41                      for path in os.environ["PATH"].split(os.pathsep)]
     42   # See if qemu is in any of these locations.
     43   qemu_bin = None
     44   for loc in qemu_locations:
     45     if os.path.isfile(loc) and os.access(loc, os.X_OK):
     46       qemu_bin = loc
     47       break
     48   return qemu_bin
     49 
     50 
     51 def main(argv):
     52   usage = 'Usage: %prog [options] <.nexe>'
     53   epilog = 'Example: sel_ldr.py my_nexe.nexe'
     54   parser = optparse.OptionParser(usage, description=__doc__, epilog=epilog)
     55   parser.add_option('-v', '--verbose', action='store_true',
     56                     help='Verbose output')
     57   parser.add_option('-d', '--debug', action='store_true',
     58                     help='Enable debug stub')
     59   parser.add_option('--debug-libs', action='store_true',
     60                     help='For dynamic executables, reference debug '
     61                          'libraries rather then release')
     62 
     63   # To enable bash completion for this command first install optcomplete
     64   # and then add this line to your .bashrc:
     65   #  complete -F _optcomplete sel_ldr.py
     66   try:
     67     import optcomplete
     68     optcomplete.autocomplete(parser)
     69   except ImportError:
     70     pass
     71 
     72   options, args = parser.parse_args(argv)
     73   if not args:
     74     parser.error('No executable file specified')
     75 
     76   nexe = args[0]
     77   if options.verbose:
     78     Log.verbose = True
     79 
     80   osname = getos.GetPlatform()
     81   if not os.path.exists(nexe):
     82     raise Error('executable not found: %s' % nexe)
     83   if not os.path.isfile(nexe):
     84     raise Error('not a file: %s' % nexe)
     85 
     86   arch, dynamic = create_nmf.ParseElfHeader(nexe)
     87 
     88   if arch == 'arm' and osname != 'linux':
     89     raise Error('Cannot run ARM executables under sel_ldr on ' + osname)
     90 
     91   arch_suffix = arch.replace('-', '_')
     92 
     93   sel_ldr = os.path.join(SCRIPT_DIR, 'sel_ldr_%s' % arch_suffix)
     94   irt = os.path.join(SCRIPT_DIR, 'irt_core_%s.nexe' % arch_suffix)
     95   if osname == 'win':
     96     sel_ldr += '.exe'
     97   Log('ROOT    = %s' % NACL_SDK_ROOT)
     98   Log('SEL_LDR = %s' % sel_ldr)
     99   Log('IRT     = %s' % irt)
    100   cmd = [sel_ldr]
    101 
    102   if osname == 'linux':
    103     # Run sel_ldr under nacl_helper_bootstrap
    104     helper = os.path.join(SCRIPT_DIR, 'nacl_helper_bootstrap_%s' % arch_suffix)
    105     Log('HELPER  = %s' % helper)
    106     cmd.insert(0, helper)
    107     cmd.append('--r_debug=0xXXXXXXXXXXXXXXXX')
    108     cmd.append('--reserved_at_zero=0xXXXXXXXXXXXXXXXX')
    109 
    110   cmd += ['-a', '-B', irt]
    111 
    112   if options.debug:
    113     cmd.append('-g')
    114 
    115   if not options.verbose:
    116     cmd += ['-l', os.devnull]
    117 
    118   if arch == 'arm':
    119     # Use the QEMU arm emulator if available.
    120     qemu_bin = FindQemu()
    121     if qemu_bin:
    122       qemu = [qemu_bin, '-cpu', 'cortex-a8', '-L',
    123               os.path.abspath(os.path.join(NACL_SDK_ROOT, 'toolchain',
    124                                            'linux_arm_trusted'))]
    125       # '-Q' disables platform qualification, allowing arm binaries to run.
    126       cmd = qemu + cmd + ['-Q']
    127     else:
    128       raise Error('Cannot run ARM executables under sel_ldr without an emulator'
    129                   '. Try installing QEMU (http://wiki.qemu.org/).')
    130 
    131   if dynamic:
    132     if options.debug_libs:
    133       libpath = os.path.join(NACL_SDK_ROOT, 'lib',
    134                             'glibc_%s' % arch_suffix, 'Debug')
    135     else:
    136       libpath = os.path.join(NACL_SDK_ROOT, 'lib',
    137                             'glibc_%s' % arch_suffix, 'Release')
    138     toolchain = '%s_x86_glibc' % osname
    139     sdk_lib_dir = os.path.join(NACL_SDK_ROOT, 'toolchain',
    140                                toolchain, 'x86_64-nacl')
    141     if arch == 'x86-64':
    142       sdk_lib_dir = os.path.join(sdk_lib_dir, 'lib')
    143     else:
    144       sdk_lib_dir = os.path.join(sdk_lib_dir, 'lib32')
    145     ldso = os.path.join(sdk_lib_dir, 'runnable-ld.so')
    146     cmd.append(ldso)
    147     Log('LD.SO = %s' % ldso)
    148     libpath += ':' + sdk_lib_dir
    149     cmd.append('--library-path')
    150     cmd.append(libpath)
    151 
    152 
    153   if args:
    154     # Append arguments for the executable itself.
    155     cmd += args
    156 
    157   Log(cmd)
    158   rtn = subprocess.call(cmd)
    159   return rtn
    160 
    161 
    162 if __name__ == '__main__':
    163   try:
    164     sys.exit(main(sys.argv[1:]))
    165   except Error as e:
    166     sys.stderr.write(str(e) + '\n')
    167     sys.exit(1)
    168