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