• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import os
2import shutil
3import subprocess
4import sys
5import tempfile
6
7from utils import FindBaseNaCl, shellcmd
8
9def subsToMacros(subs, src):
10    macros = ['#include <stddef.h>',
11              '#ifdef __cplusplus',
12              'extern "C" {',
13              '#endif']
14    for func in subs:
15        args = [('{atype} a{num}').format(atype=atype, num=i) for
16                i, atype in enumerate(subs[func]['sig'][1:])]
17        macros.append((
18            '{ftype} {name}({args});'
19            ).format(ftype=subs[func]['sig'][0],
20                     name=subs[func]['sub'],
21                     args=', '.join(args)))
22        macros.append((
23            '#define {func}(args...) ({sub}(args))'
24            ).format(func=func, sub=subs[func]['sub']))
25    macros += ['#ifdef __cplusplus',
26               '} // extern "C"',
27               '#endif',
28               '#line 1 "{src}"'.format(src=src)]
29    return '\n'.join(macros) + '\n'
30
31def run(is_cpp):
32    """Passes its arguments directly to pnacl-clang.
33
34    If -fsanitize-address is specified, extra information is passed to
35    pnacl-clang to ensure that later instrumentation in pnacl-sz can be
36    performed. For example, clang automatically inlines many memory allocation
37    functions, so this script will redefine them at compile time to make sure
38    they can be correctly instrumented by pnacl-sz.
39    """
40    pnacl_root = FindBaseNaCl()
41    dummy_subs = {'calloc': {'sig': ['void *', 'size_t', 'size_t'],
42                             'sub': '__asan_dummy_calloc'},
43                  '_calloc': {'sig': ['void *', 'size_t', 'size_t'],
44                              'sub': '__asan_dummy_calloc'}}
45    subs_src = (
46        '{root}/toolchain_build/src/subzero/pydir/sz_clang_dummies.c'
47        ).format(root=pnacl_root)
48    clang = (
49        '{root}/toolchain/linux_x86/pnacl_newlib_raw/bin/pnacl-clang{pp}'
50        ).format(root=pnacl_root, pp='++' if is_cpp else '')
51    args = sys.argv
52    args[0] = clang
53    tmp_dir = ''
54    if '-fsanitize-address' in args:
55        args.remove('-fsanitize-address')
56        include_dirs = set()
57        tmp_dir = tempfile.mkdtemp()
58        for i, arg in enumerate(args[1:], 1):
59            if not os.path.isfile(arg):
60                continue
61            src = os.path.basename(arg)
62            ext = os.path.splitext(arg)[1]
63            if ext in ['.c', '.cc', '.cpp']:
64                include_dirs |= {os.path.dirname(arg)}
65                dest_name = os.path.join(tmp_dir, src)
66                with open(dest_name, 'w') as dest:
67                    dest.write(subsToMacros(dummy_subs, arg))
68                    with open(arg) as src:
69                        for line in src:
70                            dest.write(line)
71                args[i] = dest_name
72        # If linking (not single file compilation) then add dummy definitions
73        if not ('-o' in args and
74                ('-c' in args or '-S' in args or '-E' in args)):
75            args.append(subs_src)
76        for d in include_dirs:
77            args.append('-iquote {d}'.format(d=d))
78        if '-fno-inline' not in args:
79            args.append('-fno-inline')
80    err_code = 0
81    try:
82        shellcmd(args, echo=True)
83    except subprocess.CalledProcessError as e:
84        print e.output
85        err_code = e.returncode
86    if tmp_dir != '':
87        shutil.rmtree(tmp_dir)
88    exit(err_code)
89