17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#!/usr/bin/env python
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# found in the LICENSE file.
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"""Wrapper script for launching application within the sel_ldr.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"""
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport optparse
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport os
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport subprocess
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport sys
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport create_nmf
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport getos
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochNACL_SDK_ROOT = os.path.dirname(SCRIPT_DIR)
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochif sys.version_info < (2, 6, 0):
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sys.stderr.write("python 2.6 or later is required run this script\n")
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sys.exit(1)
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass Error(Exception):
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  pass
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef Log(msg):
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if Log.verbose:
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sys.stderr.write(str(msg) + '\n')
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochLog.verbose = False
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def FindQemu():
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  qemu_locations = [os.path.join(SCRIPT_DIR, 'qemu_arm'),
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    os.path.join(SCRIPT_DIR, 'qemu-arm')]
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  qemu_locations += [os.path.join(path, 'qemu_arm')
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     for path in os.environ["PATH"].split(os.pathsep)]
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  qemu_locations += [os.path.join(path, 'qemu-arm')
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     for path in os.environ["PATH"].split(os.pathsep)]
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  # See if qemu is in any of these locations.
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  qemu_bin = None
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for loc in qemu_locations:
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if os.path.isfile(loc) and os.access(loc, os.X_OK):
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      qemu_bin = loc
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return qemu_bin
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef main(argv):
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  usage = 'Usage: %prog [options] <.nexe>'
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  epilog = 'Example: sel_ldr.py my_nexe.nexe'
540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  parser = optparse.OptionParser(usage, description=__doc__, epilog=epilog)
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  parser.add_option('-v', '--verbose', action='store_true',
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    help='Verbose output')
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  parser.add_option('-d', '--debug', action='store_true',
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    help='Enable debug stub')
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  parser.add_option('--debug-libs', action='store_true',
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    help='For dynamic executables, reference debug '
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                         'libraries rather then release')
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  # To enable bash completion for this command first install optcomplete
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  # and then add this line to your .bashrc:
650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  #  complete -F _optcomplete sel_ldr.py
660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  try:
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    import optcomplete
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    optcomplete.autocomplete(parser)
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  except ImportError:
700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    pass
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  options, args = parser.parse_args(argv)
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not args:
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    parser.error('No executable file specified')
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  nexe = args[0]
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if options.verbose:
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Log.verbose = True
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  osname = getos.GetPlatform()
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not os.path.exists(nexe):
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    raise Error('executable not found: %s' % nexe)
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not os.path.isfile(nexe):
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    raise Error('not a file: %s' % nexe)
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  arch, dynamic = create_nmf.ParseElfHeader(nexe)
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if arch == 'arm' and osname != 'linux':
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    raise Error('Cannot run ARM executables under sel_ldr on ' + osname)
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  arch_suffix = arch.replace('-', '_')
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sel_ldr = os.path.join(SCRIPT_DIR, 'sel_ldr_%s' % arch_suffix)
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  irt = os.path.join(SCRIPT_DIR, 'irt_core_%s.nexe' % arch_suffix)
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if osname == 'win':
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sel_ldr += '.exe'
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Log('ROOT    = %s' % NACL_SDK_ROOT)
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Log('SEL_LDR = %s' % sel_ldr)
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Log('IRT     = %s' % irt)
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cmd = [sel_ldr]
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if osname == 'linux':
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    # Run sel_ldr under nacl_helper_bootstrap
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    helper = os.path.join(SCRIPT_DIR, 'nacl_helper_bootstrap_%s' % arch_suffix)
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Log('HELPER  = %s' % helper)
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cmd.insert(0, helper)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cmd.append('--r_debug=0xXXXXXXXXXXXXXXXX')
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cmd.append('--reserved_at_zero=0xXXXXXXXXXXXXXXXX')
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  cmd += ['-a', '-B', irt]
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if options.debug:
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cmd.append('-g')
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if not options.verbose:
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cmd += ['-l', os.devnull]
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if arch == 'arm':
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Use the QEMU arm emulator if available.
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    qemu_bin = FindQemu()
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if qemu_bin:
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      qemu = [qemu_bin, '-cpu', 'cortex-a8', '-L',
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              os.path.abspath(os.path.join(NACL_SDK_ROOT, 'toolchain',
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           'linux_arm_trusted'))]
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # '-Q' disables platform qualification, allowing arm binaries to run.
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      cmd = qemu + cmd + ['-Q']
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else:
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      raise Error('Cannot run ARM executables under sel_ldr without an emulator'
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  '. Try installing QEMU (http://wiki.qemu.org/).')
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if dynamic:
1323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if options.debug_libs:
1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      libpath = os.path.join(NACL_SDK_ROOT, 'lib',
1343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                            'glibc_%s' % arch_suffix, 'Debug')
1353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    else:
1363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      libpath = os.path.join(NACL_SDK_ROOT, 'lib',
1373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                            'glibc_%s' % arch_suffix, 'Release')
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    toolchain = '%s_x86_glibc' % osname
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sdk_lib_dir = os.path.join(NACL_SDK_ROOT, 'toolchain',
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                               toolchain, 'x86_64-nacl')
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if arch == 'x86-64':
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sdk_lib_dir = os.path.join(sdk_lib_dir, 'lib')
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    else:
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      sdk_lib_dir = os.path.join(sdk_lib_dir, 'lib32')
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ldso = os.path.join(sdk_lib_dir, 'runnable-ld.so')
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cmd.append(ldso)
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Log('LD.SO = %s' % ldso)
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    libpath += ':' + sdk_lib_dir
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cmd.append('--library-path')
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cmd.append(libpath)
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if args:
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    # Append arguments for the executable itself.
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cmd += args
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Log(cmd)
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  rtn = subprocess.call(cmd)
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return rtn
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochif __name__ == '__main__':
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  try:
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sys.exit(main(sys.argv[1:]))
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  except Error as e:
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sys.stderr.write(str(e) + '\n')
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sys.exit(1)
168