| 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) |