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