Home | History | Annotate | Download | only in pydir
      1 #!/usr/bin/env python2
      2 
      3 import argparse
      4 import os
      5 import shutil
      6 import tempfile
      7 
      8 import targets
      9 from utils import FindBaseNaCl, GetObjcopyCmd, shellcmd
     10 
     11 
     12 def Translate(ll_files, extra_args, obj, verbose, target):
     13   """Translate a set of input bitcode files into a single object file.
     14 
     15   Use pnacl-llc to translate textual bitcode input ll_files into object file
     16   obj, using extra_args as the architectural flags.
     17   """
     18   externalize = ['-externalize']
     19   shellcmd(['cat'] + ll_files + ['|',
     20             'pnacl-llc',
     21             '-function-sections',
     22             '-O2',
     23             '-filetype=obj',
     24             '-bitcode-format=llvm',
     25             '-o', obj
     26     ] + extra_args + externalize, echo=verbose)
     27   localize_syms = ['nacl_tp_tdb_offset', 'nacl_tp_tls_offset']
     28 
     29   shellcmd([GetObjcopyCmd(target), obj] +
     30     [('--localize-symbol=' + sym) for sym in localize_syms])
     31 
     32 
     33 def PartialLink(obj_files, extra_args, lib, verbose):
     34   """Partially links a set of obj files into a final obj library."""
     35   shellcmd(['le32-nacl-ld',
     36             '-o', lib,
     37             '-r',
     38     ] + extra_args + obj_files, echo=verbose)
     39 
     40 
     41 def MakeRuntimesForTarget(target_info, ll_files,
     42                           srcdir, tempdir, rtdir, verbose, excluded_targets):
     43   """Builds native, sandboxed, and nonsfi runtimes for the given target."""
     44   if target_info.target in excluded_targets:
     45     return
     46   # File-mangling helper functions.
     47   def TmpFile(template):
     48     return template.format(dir=tempdir, target=target_info.target)
     49   def OutFile(template):
     50     return template.format(rtdir=rtdir, target=target_info.target)
     51   # Helper function for building the native unsandboxed runtime.
     52   def MakeNativeRuntime():
     53     """Builds just the native runtime."""
     54     # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to
     55     # szrt_native_{target}.tmp.o.
     56     Translate(ll_files,
     57               ['-mtriple=' + target_info.triple] + target_info.llc_flags,
     58               TmpFile('{dir}/szrt_native_{target}.tmp.o'),
     59               verbose, target_info.target)
     60     # Compile srcdir/szrt_profiler.c to
     61     # tempdir/szrt_profiler_native_{target}.o.
     62     shellcmd(['clang',
     63               '-O2',
     64               '-target=' + target_info.triple,
     65               '-c',
     66               '{srcdir}/szrt_profiler.c'.format(srcdir=srcdir),
     67               '-o', TmpFile('{dir}/szrt_native_profiler_{target}.o')
     68       ], echo=verbose)
     69     # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o.
     70     shellcmd(['llvm-mc',
     71               '-triple=' + target_info.triple, '--defsym NATIVE=1',
     72               '-filetype=obj',
     73               '-o', TmpFile('{dir}/szrt_native_asm_{target}.o'),
     74               '{srcdir}/szrt_asm_{target}.s'.format(
     75                 srcdir=srcdir, target=target_info.target)
     76       ], echo=verbose)
     77     # Write full szrt_native_{target}.o.
     78     PartialLink([TmpFile('{dir}/szrt_native_{target}.tmp.o'),
     79                  TmpFile('{dir}/szrt_native_asm_{target}.o'),
     80                  TmpFile('{dir}/szrt_native_profiler_{target}.o')],
     81                 ['-m {ld_emu}'.format(ld_emu=target_info.ld_emu)],
     82                 OutFile('{rtdir}/szrt_native_{target}.o'),
     83                 verbose)
     84     shellcmd([GetObjcopyCmd(target_info.target),
     85               '--strip-symbol=NATIVE',
     86               OutFile('{rtdir}/szrt_native_{target}.o')])
     87     # Compile srcdir/szrt_asan.c to szrt_asan_{target}.o
     88     shellcmd(['clang',
     89               '-O2',
     90               '-target=' + target_info.triple,
     91               '-c',
     92               '{srcdir}/szrt_asan.c'.format(srcdir=srcdir),
     93               '-o', OutFile('{rtdir}/szrt_asan_{target}.o')
     94       ], echo=verbose)
     95 
     96   # Helper function for building the sandboxed runtime.
     97   def MakeSandboxedRuntime():
     98     """Builds just the sandboxed runtime."""
     99     # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to szrt_sb_{target}.o.
    100     # The sandboxed library does not get the profiler helper function as the
    101     # binaries are linked with -nostdlib.
    102     Translate(ll_files,
    103               ['-mtriple=' + targets.ConvertTripleToNaCl(target_info.triple)] +
    104               target_info.llc_flags,
    105               TmpFile('{dir}/szrt_sb_{target}.tmp.o'),
    106               verbose,target_info.target)
    107     # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o.
    108     shellcmd(['llvm-mc',
    109               '-triple=' + targets.ConvertTripleToNaCl(target_info.triple),
    110               '--defsym NACL=1',
    111               '-filetype=obj',
    112               '-o', TmpFile('{dir}/szrt_sb_asm_{target}.o'),
    113               '{srcdir}/szrt_asm_{target}.s'.format(
    114                 srcdir=srcdir, target=target_info.target)
    115       ], echo=verbose)
    116     PartialLink([TmpFile('{dir}/szrt_sb_{target}.tmp.o'),
    117                  TmpFile('{dir}/szrt_sb_asm_{target}.o')],
    118                 ['-m {ld_emu}'.format(ld_emu=target_info.sb_emu)],
    119                 OutFile('{rtdir}/szrt_sb_{target}.o'),
    120                 verbose)
    121     shellcmd([GetObjcopyCmd(target_info.target),
    122               '--strip-symbol=NACL',
    123               OutFile('{rtdir}/szrt_sb_{target}.o')])
    124 
    125   # Helper function for building the Non-SFI runtime.
    126   def MakeNonsfiRuntime():
    127     """Builds just the nonsfi runtime."""
    128     # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to
    129     # szrt_nonsfi_{target}.tmp.o.
    130     Translate(ll_files,
    131               ['-mtriple=' + target_info.triple] + target_info.llc_flags +
    132               ['-relocation-model=pic', '-force-tls-non-pic', '-malign-double'],
    133               TmpFile('{dir}/szrt_nonsfi_{target}.tmp.o'),
    134               verbose, target_info.target)
    135     # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o.
    136     shellcmd(['llvm-mc',
    137               '-triple=' + target_info.triple, '--defsym NONSFI=1',
    138               '-filetype=obj',
    139               '-o', TmpFile('{dir}/szrt_nonsfi_asm_{target}.o'),
    140               '{srcdir}/szrt_asm_{target}.s'.format(
    141                 srcdir=srcdir, target=target_info.target)
    142       ], echo=verbose)
    143     # Write full szrt_nonsfi_{target}.o.
    144     PartialLink([TmpFile('{dir}/szrt_nonsfi_{target}.tmp.o'),
    145                  TmpFile('{dir}/szrt_nonsfi_asm_{target}.o')],
    146                 ['-m {ld_emu}'.format(ld_emu=target_info.ld_emu)],
    147                 OutFile('{rtdir}/szrt_nonsfi_{target}.o'),
    148                 verbose)
    149     shellcmd([GetObjcopyCmd(target_info.target),
    150               '--strip-symbol=NONSFI',
    151               OutFile('{rtdir}/szrt_nonsfi_{target}.o')])
    152 
    153 
    154   # Run the helper functions.
    155   MakeNativeRuntime()
    156   MakeSandboxedRuntime()
    157   MakeNonsfiRuntime()
    158 
    159 
    160 def main():
    161     """Build the Subzero runtime support library for all architectures.
    162     """
    163     nacl_root = FindBaseNaCl()
    164     argparser = argparse.ArgumentParser(
    165         description='    ' + main.__doc__,
    166         formatter_class=argparse.RawTextHelpFormatter)
    167     argparser.add_argument('--verbose', '-v', dest='verbose',
    168                            action='store_true',
    169                            help='Display some extra debugging output')
    170     argparser.add_argument('--pnacl-root', dest='pnacl_root',
    171                            default=(
    172                              '{root}/toolchain/linux_x86/pnacl_newlib_raw'
    173                            ).format(root=nacl_root),
    174                            help='Path to PNaCl toolchain binaries.')
    175     argparser.add_argument('--exclude-target', dest='excluded_targets',
    176                            default=[], action='append',
    177                            help='Target whose runtime should not be built')
    178     args = argparser.parse_args()
    179     os.environ['PATH'] = ('{root}/bin{sep}{path}'
    180         ).format(root=args.pnacl_root, sep=os.pathsep, path=os.environ['PATH'])
    181     srcdir = (
    182         '{root}/toolchain_build/src/subzero/runtime'
    183         ).format(root=nacl_root)
    184     rtdir = (
    185         '{root}/toolchain_build/src/subzero/build/runtime'
    186         ).format(root=nacl_root)
    187     try:
    188         tempdir = tempfile.mkdtemp()
    189         if os.path.exists(rtdir) and not os.path.isdir(rtdir):
    190             os.remove(rtdir)
    191         if not os.path.exists(rtdir):
    192             os.makedirs(rtdir)
    193         # Compile srcdir/szrt.c to tempdir/szrt.ll
    194         shellcmd(['pnacl-clang',
    195                   '-O2',
    196                   '-c',
    197                   '{srcdir}/szrt.c'.format(srcdir=srcdir),
    198                   '-o', '{dir}/szrt.tmp.bc'.format(dir=tempdir)
    199             ], echo=args.verbose)
    200         shellcmd(['pnacl-opt',
    201                   '-pnacl-abi-simplify-preopt',
    202                   '-pnacl-abi-simplify-postopt',
    203                   '-pnaclabi-allow-debug-metadata',
    204                   '{dir}/szrt.tmp.bc'.format(dir=tempdir),
    205                   '-S',
    206                   '-o', '{dir}/szrt.ll'.format(dir=tempdir)
    207             ], echo=args.verbose)
    208         ll_files = ['{dir}/szrt.ll'.format(dir=tempdir),
    209                     '{srcdir}/szrt_ll.ll'.format(srcdir=srcdir)]
    210 
    211         MakeRuntimesForTarget(targets.X8632Target, ll_files,
    212                               srcdir, tempdir, rtdir, args.verbose,
    213                               args.excluded_targets)
    214         MakeRuntimesForTarget(targets.X8664Target, ll_files,
    215                               srcdir, tempdir, rtdir, args.verbose,
    216                               args.excluded_targets)
    217         MakeRuntimesForTarget(targets.ARM32Target, ll_files,
    218                               srcdir, tempdir, rtdir, args.verbose,
    219                               args.excluded_targets)
    220         MakeRuntimesForTarget(targets.MIPS32Target, ll_files,
    221                               srcdir, tempdir, rtdir, args.verbose,
    222                               args.excluded_targets)
    223 
    224     finally:
    225         try:
    226             shutil.rmtree(tempdir)
    227         except OSError as exc:
    228             if exc.errno != errno.ENOENT: # ENOENT - no such file or directory
    229                 raise # re-raise exception
    230 
    231 if __name__ == '__main__':
    232     main()
    233