import os
import shutil
import subprocess
import sys
import tempfile
from utils import FindBaseNaCl, shellcmd
def subsToMacros(subs, src):
macros = ['#include <stddef.h>',
'#ifdef __cplusplus',
'extern "C" {',
'#endif']
for func in subs:
args = [('{atype} a{num}').format(atype=atype, num=i) for
i, atype in enumerate(subs[func]['sig'][1:])]
macros.append((
'{ftype} {name}({args});'
).format(ftype=subs[func]['sig'][0],
name=subs[func]['sub'],
args=', '.join(args)))
macros.append((
'#define {func}(args...) ({sub}(args))'
).format(func=func, sub=subs[func]['sub']))
macros += ['#ifdef __cplusplus',
'} // extern "C"',
'#endif',
'#line 1 "{src}"'.format(src=src)]
return '\n'.join(macros) + '\n'
def run(is_cpp):
"""Passes its arguments directly to pnacl-clang.
If -fsanitize-address is specified, extra information is passed to
pnacl-clang to ensure that later instrumentation in pnacl-sz can be
performed. For example, clang automatically inlines many memory allocation
functions, so this script will redefine them at compile time to make sure
they can be correctly instrumented by pnacl-sz.
"""
pnacl_root = FindBaseNaCl()
dummy_subs = {'calloc': {'sig': ['void *', 'size_t', 'size_t'],
'sub': '__asan_dummy_calloc'},
'_calloc': {'sig': ['void *', 'size_t', 'size_t'],
'sub': '__asan_dummy_calloc'}}
subs_src = (
'{root}/toolchain_build/src/subzero/pydir/sz_clang_dummies.c'
).format(root=pnacl_root)
clang = (
'{root}/toolchain/linux_x86/pnacl_newlib_raw/bin/pnacl-clang{pp}'
).format(root=pnacl_root, pp='++' if is_cpp else '')
args = sys.argv
args[0] = clang
tmp_dir = ''
if '-fsanitize-address' in args:
args.remove('-fsanitize-address')
include_dirs = set()
tmp_dir = tempfile.mkdtemp()
for i, arg in enumerate(args[1:], 1):
if not os.path.isfile(arg):
continue
src = os.path.basename(arg)
ext = os.path.splitext(arg)[1]
if ext in ['.c', '.cc', '.cpp']:
include_dirs |= {os.path.dirname(arg)}
dest_name = os.path.join(tmp_dir, src)
with open(dest_name, 'w') as dest:
dest.write(subsToMacros(dummy_subs, arg))
with open(arg) as src:
for line in src:
dest.write(line)
args[i] = dest_name
# If linking (not single file compilation) then add dummy definitions
if not ('-o' in args and
('-c' in args or '-S' in args or '-E' in args)):
args.append(subs_src)
for d in include_dirs:
args.append('-iquote {d}'.format(d=d))
if '-fno-inline' not in args:
args.append('-fno-inline')
err_code = 0
try:
shellcmd(args, echo=True)
except subprocess.CalledProcessError as e:
print e.output
err_code = e.returncode
if tmp_dir != '':
shutil.rmtree(tmp_dir)
exit(err_code)