You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
3.9 KiB
176 lines
3.9 KiB
4 months ago
|
#!/usr/bin/env python
|
||
|
# Copyright 2017 Google Inc.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
#
|
||
|
################################################################################
|
||
|
|
||
|
from __future__ import print_function
|
||
|
import os
|
||
|
import subprocess
|
||
|
import sys
|
||
|
|
||
|
import msan_build
|
||
|
|
||
|
GCC_ONLY_ARGS = [
|
||
|
'-aux-info',
|
||
|
]
|
||
|
|
||
|
|
||
|
def InvokedAsGcc():
|
||
|
"""Return whether or not we're pretending to be GCC."""
|
||
|
return sys.argv[0].endswith('gcc') or sys.argv[0].endswith('g++')
|
||
|
|
||
|
|
||
|
def Is32Bit(args):
|
||
|
"""Return whether or not we're 32-bit."""
|
||
|
M32_BIT_ARGS = [
|
||
|
'-m32',
|
||
|
'-mx32',
|
||
|
]
|
||
|
|
||
|
return any(arg in M32_BIT_ARGS for arg in args)
|
||
|
|
||
|
|
||
|
def FilterWlArg(arg):
|
||
|
"""Remove -z,defs and equivalents from a single -Wl option."""
|
||
|
parts = arg.split(',')[1:]
|
||
|
|
||
|
filtered = []
|
||
|
for part in parts:
|
||
|
if part == 'defs':
|
||
|
removed = filtered.pop()
|
||
|
assert removed == '-z'
|
||
|
continue
|
||
|
|
||
|
if part == '--no-undefined':
|
||
|
continue
|
||
|
|
||
|
filtered.append(part)
|
||
|
|
||
|
if filtered:
|
||
|
return '-Wl,' + ','.join(filtered)
|
||
|
|
||
|
# Filtered entire argument.
|
||
|
return None
|
||
|
|
||
|
|
||
|
def _RemoveLastMatching(l, find):
|
||
|
for i in xrange(len(l) - 1, -1, -1):
|
||
|
if l[i] == find:
|
||
|
del l[i]
|
||
|
return
|
||
|
|
||
|
raise IndexError('Not found')
|
||
|
|
||
|
|
||
|
def RemoveZDefs(args):
|
||
|
"""Remove unsupported -Wl,-z,defs linker option."""
|
||
|
filtered = []
|
||
|
|
||
|
for arg in args:
|
||
|
if arg == '-Wl,defs':
|
||
|
_RemoveLastMatching(filtered, '-Wl,-z')
|
||
|
continue
|
||
|
|
||
|
if arg == '-Wl,--no-undefined':
|
||
|
continue
|
||
|
|
||
|
if arg.startswith('-Wl,'):
|
||
|
arg = FilterWlArg(arg)
|
||
|
if not arg:
|
||
|
continue
|
||
|
|
||
|
filtered.append(arg)
|
||
|
|
||
|
return filtered
|
||
|
|
||
|
|
||
|
def GetCompilerArgs(args, is_cxx):
|
||
|
"""Generate compiler args."""
|
||
|
compiler_args = args[1:]
|
||
|
|
||
|
if Is32Bit(args):
|
||
|
# 32 bit builds not supported.
|
||
|
compiler_args.extend([
|
||
|
'-fno-sanitize=memory',
|
||
|
'-fno-sanitize-memory-track-origins',
|
||
|
])
|
||
|
|
||
|
return compiler_args
|
||
|
|
||
|
compiler_args = RemoveZDefs(compiler_args)
|
||
|
compiler_args.extend([
|
||
|
# FORTIFY_SOURCE is not supported by sanitizers.
|
||
|
'-U_FORTIFY_SOURCE',
|
||
|
'-Wp,-U_FORTIFY_SOURCE',
|
||
|
# Reduce binary size.
|
||
|
'-gline-tables-only',
|
||
|
# Disable all warnings.
|
||
|
'-w',
|
||
|
# LTO isn't supported.
|
||
|
'-fno-lto',
|
||
|
])
|
||
|
|
||
|
if InvokedAsGcc():
|
||
|
compiler_args.extend([
|
||
|
# For better compatibility with flags passed via -Wa,...
|
||
|
'-fno-integrated-as',
|
||
|
])
|
||
|
|
||
|
if '-fsanitize=memory' not in args:
|
||
|
# If MSan flags weren't added for some reason, add them here.
|
||
|
compiler_args.extend(msan_build.GetInjectedFlags())
|
||
|
|
||
|
if is_cxx:
|
||
|
compiler_args.append('-stdlib=libc++')
|
||
|
|
||
|
return compiler_args
|
||
|
|
||
|
|
||
|
def FindRealClang():
|
||
|
"""Return path to real clang."""
|
||
|
return os.environ['REAL_CLANG_PATH']
|
||
|
|
||
|
|
||
|
def FallbackToGcc(args):
|
||
|
"""Check whether if we should fall back to GCC."""
|
||
|
if not InvokedAsGcc():
|
||
|
return False
|
||
|
|
||
|
return any(arg in GCC_ONLY_ARGS for arg in args[1:])
|
||
|
|
||
|
|
||
|
def main(args):
|
||
|
if FallbackToGcc(args):
|
||
|
sys.exit(subprocess.call(['/usr/bin/' + os.path.basename(args[0])] +
|
||
|
args[1:]))
|
||
|
|
||
|
is_cxx = args[0].endswith('++')
|
||
|
real_clang = FindRealClang()
|
||
|
|
||
|
if is_cxx:
|
||
|
real_clang += '++'
|
||
|
|
||
|
args = [real_clang] + GetCompilerArgs(args, is_cxx)
|
||
|
debug_log_path = os.getenv('WRAPPER_DEBUG_LOG_PATH')
|
||
|
if debug_log_path:
|
||
|
with open(debug_log_path, 'a') as f:
|
||
|
f.write(str(args) + '\n')
|
||
|
|
||
|
sys.exit(subprocess.call(args))
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main(sys.argv)
|