• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python2
2
3import argparse
4import os
5import shutil
6import tempfile
7
8import targets
9from utils import FindBaseNaCl, GetObjcopyCmd, shellcmd
10
11
12def 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
33def 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
41def 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
160def 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
231if __name__ == '__main__':
232    main()
233