| #!/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() |