blob: ef51266eb2c7a926c88ac50decb8415f64c9ee7d [file] [log] [blame]
Stephen Hines2d1fdb22014-05-28 23:58:16 -07001# -*- Python -*-
2
3import os
4
5def get_required_attr(config, attr_name):
6 attr_value = getattr(config, attr_name, None)
7 if attr_value == None:
8 lit_config.fatal(
9 "No attribute %r in test configuration! You may need to run "
10 "tests from your build directory or add this attribute "
11 "to lit.site.cfg " % attr_name)
12 return attr_value
13
14def push_ld_library_path(config, new_path):
15 new_ld_library_path = os.path.pathsep.join(
16 (new_path, config.environment['LD_LIBRARY_PATH']))
17 config.environment['LD_LIBRARY_PATH'] = new_ld_library_path
18
19# Setup config name.
20config.name = 'AddressSanitizer' + config.name_suffix
21
22# Setup source root.
23config.test_source_root = os.path.dirname(__file__)
24
25# GCC-ASan doesn't link in all the necessary libraries automatically, so
26# we have to do it ourselves.
27if config.compiler_id == 'GNU':
28 extra_linkflags = ["-lpthread", "-lstdc++", "-ldl"]
29else:
30 extra_linkflags = []
31# Setup default compiler flags used with -fsanitize=address option.
32# FIXME: Review the set of required flags and check if it can be reduced.
33target_cflags = [get_required_attr(config, "target_cflags")] + extra_linkflags
34target_cxxflags = config.cxx_mode_flags + target_cflags
35clang_asan_static_cflags = ["-fsanitize=address"] + target_cflags
36
37clang_path = getattr(config, 'clang', None)
38if clang_path.find("clang-cl") == -1:
39 clang_asan_static_cflags += ["-g",
40 "-mno-omit-leaf-frame-pointer",
41 "-fno-omit-frame-pointer",
42 "-fno-optimize-sibling-calls"]
43else:
44 clang_asan_static_cflags += ["-Zi",
45 "-Wno-deprecated-declarations",
46 "-D_HAS_EXCEPTIONS=0"]
47
48clang_asan_static_cxxflags = config.cxx_mode_flags + clang_asan_static_cflags
49
50if config.asan_dynamic:
51 clang_asan_cflags = clang_asan_static_cflags + ['-shared-libasan']
52 clang_asan_cxxflags = clang_asan_static_cxxflags + ['-shared-libasan']
53 config.available_features.add("asan-dynamic-runtime")
54else:
55 clang_asan_cflags = clang_asan_static_cflags
56 clang_asan_cxxflags = clang_asan_static_cxxflags
57 config.available_features.add("asan-static-runtime")
58
59asan_lit_source_dir = get_required_attr(config, "asan_lit_source_dir")
60if config.android == "TRUE":
61 config.available_features.add('android')
62 clang_wrapper = os.path.join(asan_lit_source_dir,
63 "android_commands", "android_compile.py") + " "
64else:
65 clang_wrapper = ""
66
67def build_invocation(compile_flags):
68 return " " + " ".join([clang_wrapper, config.clang] + compile_flags) + " "
69
70config.substitutions.append( ("%clang ", build_invocation(target_cflags)) )
71config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) )
72config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) )
73config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) )
74config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % config.target_arch))
75if config.asan_dynamic:
76 config.substitutions.append( ("%clang_asan_static ", build_invocation(clang_asan_static_cflags)) )
77 config.substitutions.append( ("%clangxx_asan_static ", build_invocation(clang_asan_static_cxxflags)) )
78
79# FIXME: De-hardcode this path.
80asan_source_dir = os.path.join(
81 get_required_attr(config, "compiler_rt_src_root"), "lib", "asan")
82# Setup path to asan_symbolize.py script.
83asan_symbolize = os.path.join(asan_source_dir, "scripts", "asan_symbolize.py")
84if not os.path.exists(asan_symbolize):
85 lit_config.fatal("Can't find script on path %r" % asan_symbolize)
86python_exec = get_required_attr(config, "python_executable")
87config.substitutions.append( ("%asan_symbolize", python_exec + " " + asan_symbolize + " ") )
88# Setup path to sancov.py script.
89sanitizer_common_source_dir = os.path.join(
90 get_required_attr(config, "compiler_rt_src_root"), "lib", "sanitizer_common")
91sancov = os.path.join(sanitizer_common_source_dir, "scripts", "sancov.py")
92if not os.path.exists(sancov):
93 lit_config.fatal("Can't find script on path %r" % sancov)
94python_exec = get_required_attr(config, "python_executable")
95config.substitutions.append( ("%sancov", python_exec + " " + sancov + " ") )
96
97# Determine kernel bitness
98if config.host_arch.find('64') != -1 and config.android != "TRUE":
99 kernel_bits = '64'
100else:
101 kernel_bits = '32'
102
103# Define CHECK-%os to check for OS-dependent output.
104config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
105config.substitutions.append( ('CHECK-%kernel_bits', ("CHECK-kernel-" + kernel_bits + "-bits")))
106
107config.available_features.add("asan-" + config.bits + "-bits")
108
109# Turn on leak detection on 64-bit Linux.
110if config.host_os == 'Linux' and config.bits == '64':
111 config.environment['ASAN_OPTIONS'] = 'detect_leaks=1'
112
113# Set LD_LIBRARY_PATH to pick dynamic runtime up properly.
114push_ld_library_path(config, config.compiler_rt_libdir)
115
116# GCC-ASan uses dynamic runtime by default.
117if config.compiler_id == 'GNU':
118 gcc_dir = os.path.dirname(config.clang)
119 libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
120 push_ld_library_path(config, libasan_dir)
121
122# Default test suffixes.
123config.suffixes = ['.c', '.cc', '.cpp']
124
125if config.host_os == 'Darwin':
126 config.suffixes.append('.mm')
127
128# AddressSanitizer tests are currently supported on Linux and Darwin only.
129if config.host_os not in ['Linux', 'Darwin']:
130 config.unsupported = True