# -*- Python -*- import os def get_required_attr(config, attr_name): attr_value = getattr(config, attr_name, None) if not attr_value: lit_config.fatal( "No attribute %r in test configuration! You may need to run " "tests from your build directory or add this attribute " "to lit.site.cfg " % attr_name) return attr_value # Setup config name. config.name = 'AddressSanitizer' + config.name_suffix # Setup source root. config.test_source_root = os.path.dirname(__file__) # GCC-ASan doesn't link in all the necessary libraries automatically, so # we have to do it ourselves. if config.compiler_id == 'GNU': extra_linkflags = ["-lpthread", "-lstdc++", "-ldl"] else: extra_linkflags = [] # Setup default compiler flags used with -fsanitize=address option. # FIXME: Review the set of required flags and check if it can be reduced. target_cflags = [get_required_attr(config, "target_cflags")] + extra_linkflags target_cxxflags = config.cxx_mode_flags + target_cflags clang_asan_cflags = ["-fsanitize=address", "-mno-omit-leaf-frame-pointer", "-fno-omit-frame-pointer", "-fno-optimize-sibling-calls", "-g"] + target_cflags clang_asan_cxxflags = config.cxx_mode_flags + clang_asan_cflags asan_lit_source_dir = get_required_attr(config, "asan_lit_source_dir") if config.android == "TRUE": config.available_features.add('android') clang_wrapper = os.path.join(asan_lit_source_dir, "android_commands", "android_compile.py") + " " else: clang_wrapper = "" def build_invocation(compile_flags): return " " + " ".join([clang_wrapper, config.clang] + compile_flags) + " " config.substitutions.append( ("%clang ", build_invocation(target_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) ) config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) ) config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) ) # FIXME: De-hardcode this path. asan_source_dir = os.path.join( get_required_attr(config, "compiler_rt_src_root"), "lib", "asan") # Setup path to asan_symbolize.py script. asan_symbolize = os.path.join(asan_source_dir, "scripts", "asan_symbolize.py") if not os.path.exists(asan_symbolize): lit_config.fatal("Can't find script on path %r" % asan_symbolize) python_exec = get_required_attr(config, "python_executable") config.substitutions.append( ("%asan_symbolize", python_exec + " " + asan_symbolize + " ") ) # Determine kernel bitness if config.host_arch.find('64') != -1 and config.android != "TRUE": kernel_bits = '64' else: kernel_bits = '32' # Define CHECK-%os to check for OS-dependent output. config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os))) config.substitutions.append( ('CHECK-%kernel_bits', ("CHECK-kernel-" + kernel_bits + "-bits"))) config.available_features.add("asan-" + config.bits + "-bits") # Turn on leak detection on 64-bit Linux. if config.host_os == 'Linux' and config.bits == '64': config.environment['ASAN_OPTIONS'] = 'detect_leaks=1' # GCC-ASan uses dynamic runtime by default, so we have to set LD_LIBRARY_PATH # to pick it up properly. if config.compiler_id == 'GNU': gcc_dir = os.path.dirname(config.clang) libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits) new_ld_library_path = os.path.pathsep.join( (libasan_dir, config.environment['LD_LIBRARY_PATH'])) config.environment['LD_LIBRARY_PATH'] = new_ld_library_path # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] if config.host_os == 'Darwin': config.suffixes.append('.mm') # AddressSanitizer tests are currently supported on Linux and Darwin only. if config.host_os not in ['Linux', 'Darwin']: config.unsupported = True