#!/usr/bin/env python2 import argparse import os import shutil import tempfile import targets from utils import FindBaseNaCl, GetObjcopyCmd, shellcmd def Translate(ll_files, extra_args, obj, verbose, target): """Translate a set of input bitcode files into a single object file. Use pnacl-llc to translate textual bitcode input ll_files into object file obj, using extra_args as the architectural flags. """ externalize = ['-externalize'] shellcmd(['cat'] + ll_files + ['|', 'pnacl-llc', '-function-sections', '-O2', '-filetype=obj', '-bitcode-format=llvm', '-o', obj ] + extra_args + externalize, echo=verbose) localize_syms = ['nacl_tp_tdb_offset', 'nacl_tp_tls_offset'] shellcmd([GetObjcopyCmd(target), obj] + [('--localize-symbol=' + sym) for sym in localize_syms]) def PartialLink(obj_files, extra_args, lib, verbose): """Partially links a set of obj files into a final obj library.""" shellcmd(['le32-nacl-ld', '-o', lib, '-r', ] + extra_args + obj_files, echo=verbose) def MakeRuntimesForTarget(target_info, ll_files, srcdir, tempdir, rtdir, verbose, excluded_targets): """Builds native, sandboxed, and nonsfi runtimes for the given target.""" if target_info.target in excluded_targets: return # File-mangling helper functions. def TmpFile(template): return template.format(dir=tempdir, target=target_info.target) def OutFile(template): return template.format(rtdir=rtdir, target=target_info.target) # Helper function for building the native unsandboxed runtime. def MakeNativeRuntime(): """Builds just the native runtime.""" # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to # szrt_native_{target}.tmp.o. Translate(ll_files, ['-mtriple=' + target_info.triple] + target_info.llc_flags, TmpFile('{dir}/szrt_native_{target}.tmp.o'), verbose, target_info.target) # Compile srcdir/szrt_profiler.c to # tempdir/szrt_profiler_native_{target}.o. shellcmd(['clang', '-O2', '-target=' + target_info.triple, '-c', '{srcdir}/szrt_profiler.c'.format(srcdir=srcdir), '-o', TmpFile('{dir}/szrt_native_profiler_{target}.o') ], echo=verbose) # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o. shellcmd(['llvm-mc', '-triple=' + target_info.triple, '--defsym NATIVE=1', '-filetype=obj', '-o', TmpFile('{dir}/szrt_native_asm_{target}.o'), '{srcdir}/szrt_asm_{target}.s'.format( srcdir=srcdir, target=target_info.target) ], echo=verbose) # Write full szrt_native_{target}.o. PartialLink([TmpFile('{dir}/szrt_native_{target}.tmp.o'), TmpFile('{dir}/szrt_native_asm_{target}.o'), TmpFile('{dir}/szrt_native_profiler_{target}.o')], ['-m {ld_emu}'.format(ld_emu=target_info.ld_emu)], OutFile('{rtdir}/szrt_native_{target}.o'), verbose) shellcmd([GetObjcopyCmd(target_info.target), '--strip-symbol=NATIVE', OutFile('{rtdir}/szrt_native_{target}.o')]) # Compile srcdir/szrt_asan.c to szrt_asan_{target}.o shellcmd(['clang', '-O2', '-target=' + target_info.triple, '-c', '{srcdir}/szrt_asan.c'.format(srcdir=srcdir), '-o', OutFile('{rtdir}/szrt_asan_{target}.o') ], echo=verbose) # Helper function for building the sandboxed runtime. def MakeSandboxedRuntime(): """Builds just the sandboxed runtime.""" # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to szrt_sb_{target}.o. # The sandboxed library does not get the profiler helper function as the # binaries are linked with -nostdlib. Translate(ll_files, ['-mtriple=' + targets.ConvertTripleToNaCl(target_info.triple)] + target_info.llc_flags, TmpFile('{dir}/szrt_sb_{target}.tmp.o'), verbose,target_info.target) # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o. shellcmd(['llvm-mc', '-triple=' + targets.ConvertTripleToNaCl(target_info.triple), '--defsym NACL=1', '-filetype=obj', '-o', TmpFile('{dir}/szrt_sb_asm_{target}.o'), '{srcdir}/szrt_asm_{target}.s'.format( srcdir=srcdir, target=target_info.target) ], echo=verbose) PartialLink([TmpFile('{dir}/szrt_sb_{target}.tmp.o'), TmpFile('{dir}/szrt_sb_asm_{target}.o')], ['-m {ld_emu}'.format(ld_emu=target_info.sb_emu)], OutFile('{rtdir}/szrt_sb_{target}.o'), verbose) shellcmd([GetObjcopyCmd(target_info.target), '--strip-symbol=NACL', OutFile('{rtdir}/szrt_sb_{target}.o')]) # Helper function for building the Non-SFI runtime. def MakeNonsfiRuntime(): """Builds just the nonsfi runtime.""" # Translate tempdir/szrt.ll and tempdir/szrt_ll.ll to # szrt_nonsfi_{target}.tmp.o. Translate(ll_files, ['-mtriple=' + target_info.triple] + target_info.llc_flags + ['-relocation-model=pic', '-force-tls-non-pic', '-malign-double'], TmpFile('{dir}/szrt_nonsfi_{target}.tmp.o'), verbose, target_info.target) # Assemble srcdir/szrt_asm_{target}.s to tempdir/szrt_asm_{target}.o. shellcmd(['llvm-mc', '-triple=' + target_info.triple, '--defsym NONSFI=1', '-filetype=obj', '-o', TmpFile('{dir}/szrt_nonsfi_asm_{target}.o'), '{srcdir}/szrt_asm_{target}.s'.format( srcdir=srcdir, target=target_info.target) ], echo=verbose) # Write full szrt_nonsfi_{target}.o. PartialLink([TmpFile('{dir}/szrt_nonsfi_{target}.tmp.o'), TmpFile('{dir}/szrt_nonsfi_asm_{target}.o')], ['-m {ld_emu}'.format(ld_emu=target_info.ld_emu)], OutFile('{rtdir}/szrt_nonsfi_{target}.o'), verbose) shellcmd([GetObjcopyCmd(target_info.target), '--strip-symbol=NONSFI', OutFile('{rtdir}/szrt_nonsfi_{target}.o')]) # Run the helper functions. MakeNativeRuntime() MakeSandboxedRuntime() MakeNonsfiRuntime() def main(): """Build the Subzero runtime support library for all architectures. """ nacl_root = FindBaseNaCl() argparser = argparse.ArgumentParser( description=' ' + main.__doc__, formatter_class=argparse.RawTextHelpFormatter) argparser.add_argument('--verbose', '-v', dest='verbose', action='store_true', help='Display some extra debugging output') argparser.add_argument('--pnacl-root', dest='pnacl_root', default=( '{root}/toolchain/linux_x86/pnacl_newlib_raw' ).format(root=nacl_root), help='Path to PNaCl toolchain binaries.') argparser.add_argument('--exclude-target', dest='excluded_targets', default=[], action='append', help='Target whose runtime should not be built') args = argparser.parse_args() os.environ['PATH'] = ('{root}/bin{sep}{path}' ).format(root=args.pnacl_root, sep=os.pathsep, path=os.environ['PATH']) srcdir = ( '{root}/toolchain_build/src/subzero/runtime' ).format(root=nacl_root) rtdir = ( '{root}/toolchain_build/src/subzero/build/runtime' ).format(root=nacl_root) try: tempdir = tempfile.mkdtemp() if os.path.exists(rtdir) and not os.path.isdir(rtdir): os.remove(rtdir) if not os.path.exists(rtdir): os.makedirs(rtdir) # Compile srcdir/szrt.c to tempdir/szrt.ll shellcmd(['pnacl-clang', '-O2', '-c', '{srcdir}/szrt.c'.format(srcdir=srcdir), '-o', '{dir}/szrt.tmp.bc'.format(dir=tempdir) ], echo=args.verbose) shellcmd(['pnacl-opt', '-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt', '-pnaclabi-allow-debug-metadata', '{dir}/szrt.tmp.bc'.format(dir=tempdir), '-S', '-o', '{dir}/szrt.ll'.format(dir=tempdir) ], echo=args.verbose) ll_files = ['{dir}/szrt.ll'.format(dir=tempdir), '{srcdir}/szrt_ll.ll'.format(srcdir=srcdir)] MakeRuntimesForTarget(targets.X8632Target, ll_files, srcdir, tempdir, rtdir, args.verbose, args.excluded_targets) MakeRuntimesForTarget(targets.X8664Target, ll_files, srcdir, tempdir, rtdir, args.verbose, args.excluded_targets) MakeRuntimesForTarget(targets.ARM32Target, ll_files, srcdir, tempdir, rtdir, args.verbose, args.excluded_targets) MakeRuntimesForTarget(targets.MIPS32Target, ll_files, srcdir, tempdir, rtdir, args.verbose, args.excluded_targets) finally: try: shutil.rmtree(tempdir) except OSError as exc: if exc.errno != errno.ENOENT: # ENOENT - no such file or directory raise # re-raise exception if __name__ == '__main__': main()