18007ff1aSReid Kleckner# -*- Python -*- 28007ff1aSReid Kleckner 38007ff1aSReid Klecknerimport os 48007ff1aSReid Klecknerimport platform 58007ff1aSReid Klecknerimport re 6aa6cb0f2SFangrui Songimport shlex 78007ff1aSReid Kleckner 88007ff1aSReid Klecknerimport lit.formats 98007ff1aSReid Kleckner 10f98ee40fSTobias Hieta 118007ff1aSReid Klecknerdef get_required_attr(config, attr_name): 128007ff1aSReid Kleckner attr_value = getattr(config, attr_name, None) 13*0af6c304SEisuke Kawashima if attr_value is None: 148007ff1aSReid Kleckner lit_config.fatal( 158007ff1aSReid Kleckner "No attribute %r in test configuration! You may need to run " 168007ff1aSReid Kleckner "tests from your build directory or add this attribute " 17f98ee40fSTobias Hieta "to lit.site.cfg.py " % attr_name 18f98ee40fSTobias Hieta ) 198007ff1aSReid Kleckner return attr_value 208007ff1aSReid Kleckner 218007ff1aSReid Kleckner# Setup config name. 22f98ee40fSTobias Hietaconfig.name = "AddressSanitizer" + config.name_suffix 238007ff1aSReid Kleckner 248007ff1aSReid Kleckner# Platform-specific default ASAN_OPTIONS for lit tests. 258007ff1aSReid Klecknerdefault_asan_opts = list(config.default_sanitizer_opts) 268007ff1aSReid Kleckner 27dcf11af2SJulian Lettner# On Darwin, leak checking is not enabled by default. Enable on macOS 288007ff1aSReid Kleckner# tests to prevent regressions 29f98ee40fSTobias Hietaif config.host_os == "Darwin" and config.apple_platform == "osx": 30f98ee40fSTobias Hieta default_asan_opts += ["detect_leaks=1"] 318007ff1aSReid Kleckner 32f98ee40fSTobias Hietadefault_asan_opts_str = ":".join(default_asan_opts) 338007ff1aSReid Klecknerif default_asan_opts_str: 34f98ee40fSTobias Hieta config.environment["ASAN_OPTIONS"] = default_asan_opts_str 35f98ee40fSTobias Hieta default_asan_opts_str += ":" 36f98ee40fSTobias Hietaconfig.substitutions.append( 37f98ee40fSTobias Hieta ("%env_asan_opts=", "env ASAN_OPTIONS=" + default_asan_opts_str) 38f98ee40fSTobias Hieta) 398007ff1aSReid Kleckner 408007ff1aSReid Kleckner# Setup source root. 418007ff1aSReid Klecknerconfig.test_source_root = os.path.dirname(__file__) 428007ff1aSReid Kleckner 43f98ee40fSTobias Hietaif config.host_os not in ["FreeBSD", "NetBSD"]: 448007ff1aSReid Kleckner libdl_flag = "-ldl" 458007ff1aSReid Klecknerelse: 468007ff1aSReid Kleckner libdl_flag = "" 478007ff1aSReid Kleckner 488007ff1aSReid Kleckner# GCC-ASan doesn't link in all the necessary libraries automatically, so 498007ff1aSReid Kleckner# we have to do it ourselves. 50f98ee40fSTobias Hietaif config.compiler_id == "GNU": 518007ff1aSReid Kleckner extra_link_flags = ["-pthread", "-lstdc++", libdl_flag] 528007ff1aSReid Klecknerelse: 538007ff1aSReid Kleckner extra_link_flags = [] 548007ff1aSReid Kleckner 558007ff1aSReid Kleckner# Setup default compiler flags used with -fsanitize=address option. 568007ff1aSReid Kleckner# FIXME: Review the set of required flags and check if it can be reduced. 578007ff1aSReid Klecknertarget_cflags = [get_required_attr(config, "target_cflags")] + extra_link_flags 588007ff1aSReid Klecknertarget_cxxflags = config.cxx_mode_flags + target_cflags 59f98ee40fSTobias Hietaclang_asan_static_cflags = ( 60f98ee40fSTobias Hieta [ 61f98ee40fSTobias Hieta "-fsanitize=address", 628007ff1aSReid Kleckner "-mno-omit-leaf-frame-pointer", 638007ff1aSReid Kleckner "-fno-omit-frame-pointer", 64f98ee40fSTobias Hieta "-fno-optimize-sibling-calls", 65f98ee40fSTobias Hieta ] 66f98ee40fSTobias Hieta + config.debug_info_flags 67f98ee40fSTobias Hieta + target_cflags 68f98ee40fSTobias Hieta) 69f98ee40fSTobias Hietaif config.target_arch == "s390x": 708007ff1aSReid Kleckner clang_asan_static_cflags.append("-mbackchain") 718007ff1aSReid Klecknerclang_asan_static_cxxflags = config.cxx_mode_flags + clang_asan_static_cflags 728007ff1aSReid Kleckner 73f98ee40fSTobias Hietatarget_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple)) 74bae2fbaeSAlvin Wong 758007ff1aSReid Klecknerasan_dynamic_flags = [] 768007ff1aSReid Klecknerif config.asan_dynamic: 778007ff1aSReid Kleckner asan_dynamic_flags = ["-shared-libasan"] 78f98ee40fSTobias Hieta if platform.system() == "Windows" and target_is_msvc: 79bae2fbaeSAlvin Wong # On MSVC target, we need to simulate "clang-cl /MD" on the clang driver side. 80f98ee40fSTobias Hieta asan_dynamic_flags += [ 81f98ee40fSTobias Hieta "-D_MT", 82f98ee40fSTobias Hieta "-D_DLL", 83f98ee40fSTobias Hieta "-Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames", 84f98ee40fSTobias Hieta ] 85f98ee40fSTobias Hieta elif platform.system() == "FreeBSD": 863aecf4bdSDimitry Andric # On FreeBSD, we need to add -pthread to ensure pthread functions are available. 87f98ee40fSTobias Hieta asan_dynamic_flags += ["-pthread"] 888007ff1aSReid Kleckner config.available_features.add("asan-dynamic-runtime") 898007ff1aSReid Klecknerelse: 908007ff1aSReid Kleckner config.available_features.add("asan-static-runtime") 918007ff1aSReid Klecknerclang_asan_cflags = clang_asan_static_cflags + asan_dynamic_flags 928007ff1aSReid Klecknerclang_asan_cxxflags = clang_asan_static_cxxflags + asan_dynamic_flags 938007ff1aSReid Kleckner 948007ff1aSReid Kleckner# Add win32-(static|dynamic)-asan features to mark tests as passing or failing 958007ff1aSReid Kleckner# in those modes. lit doesn't support logical feature test combinations. 96f98ee40fSTobias Hietaif platform.system() == "Windows": 978007ff1aSReid Kleckner if config.asan_dynamic: 988007ff1aSReid Kleckner win_runtime_feature = "win32-dynamic-asan" 998007ff1aSReid Kleckner else: 1008007ff1aSReid Kleckner win_runtime_feature = "win32-static-asan" 1018007ff1aSReid Kleckner config.available_features.add(win_runtime_feature) 1028007ff1aSReid Kleckner 103f98ee40fSTobias Hieta 104911289a6SUsama Hameeddef build_invocation(compile_flags, with_lto=False): 105911289a6SUsama Hameed lto_flags = [] 106911289a6SUsama Hameed if with_lto and config.lto_supported: 107911289a6SUsama Hameed lto_flags += config.lto_flags 108911289a6SUsama Hameed 109911289a6SUsama Hameed return " " + " ".join([config.clang] + lto_flags + compile_flags) + " " 1108007ff1aSReid Kleckner 111f98ee40fSTobias Hieta 1128007ff1aSReid Klecknerconfig.substitutions.append(("%clang ", build_invocation(target_cflags))) 1138007ff1aSReid Klecknerconfig.substitutions.append(("%clangxx ", build_invocation(target_cxxflags))) 1148007ff1aSReid Klecknerconfig.substitutions.append(("%clang_asan ", build_invocation(clang_asan_cflags))) 1158007ff1aSReid Klecknerconfig.substitutions.append(("%clangxx_asan ", build_invocation(clang_asan_cxxflags))) 116911289a6SUsama Hameedconfig.substitutions.append( 117911289a6SUsama Hameed ("%clang_asan_lto ", build_invocation(clang_asan_cflags, True)) 118911289a6SUsama Hameed) 119911289a6SUsama Hameedconfig.substitutions.append( 120911289a6SUsama Hameed ("%clangxx_asan_lto ", build_invocation(clang_asan_cxxflags, True)) 121911289a6SUsama Hameed) 1228007ff1aSReid Klecknerif config.asan_dynamic: 123f98ee40fSTobias Hieta if config.host_os in ["Linux", "FreeBSD", "NetBSD", "SunOS"]: 124f98ee40fSTobias Hieta shared_libasan_path = os.path.join( 125f98ee40fSTobias Hieta config.compiler_rt_libdir, 126f98ee40fSTobias Hieta "libclang_rt.asan{}.so".format(config.target_suffix), 127f98ee40fSTobias Hieta ) 128f98ee40fSTobias Hieta elif config.host_os == "Darwin": 129f98ee40fSTobias Hieta shared_libasan_path = os.path.join( 130f98ee40fSTobias Hieta config.compiler_rt_libdir, 131f98ee40fSTobias Hieta "libclang_rt.asan_{}_dynamic.dylib".format(config.apple_platform), 132f98ee40fSTobias Hieta ) 13353a81d4dSCharlie Barto elif config.host_os == "Windows": 13453a81d4dSCharlie Barto shared_libasan_path = os.path.join( 13553a81d4dSCharlie Barto config.compiler_rt_libdir, 13653a81d4dSCharlie Barto "clang_rt.asan_dynamic-{}.lib".format(config.target_suffix), 13753a81d4dSCharlie Barto ) 1388007ff1aSReid Kleckner else: 139f98ee40fSTobias Hieta lit_config.warning( 140f98ee40fSTobias Hieta "%shared_libasan substitution not set but dynamic ASan is available." 141f98ee40fSTobias Hieta ) 1428007ff1aSReid Kleckner shared_libasan_path = None 1438007ff1aSReid Kleckner 1448007ff1aSReid Kleckner if shared_libasan_path is not None: 1458007ff1aSReid Kleckner config.substitutions.append(("%shared_libasan", shared_libasan_path)) 146f98ee40fSTobias Hieta config.substitutions.append( 147f98ee40fSTobias Hieta ("%clang_asan_static ", build_invocation(clang_asan_static_cflags)) 148f98ee40fSTobias Hieta ) 149f98ee40fSTobias Hieta config.substitutions.append( 150f98ee40fSTobias Hieta ("%clangxx_asan_static ", build_invocation(clang_asan_static_cxxflags)) 151f98ee40fSTobias Hieta ) 1528007ff1aSReid Kleckner 153f98ee40fSTobias Hietaif platform.system() == "Windows": 154bae2fbaeSAlvin Wong # MSVC-specific tests might also use the clang-cl.exe driver. 1553c1aa20cSAlvin Wong if target_is_msvc: 156a6bdf3faSCharlie Barto clang_cl_cxxflags = ( 157a6bdf3faSCharlie Barto [ 1588007ff1aSReid Kleckner "-WX", 1598007ff1aSReid Kleckner "-D_HAS_EXCEPTIONS=0", 160a6bdf3faSCharlie Barto ] 161a6bdf3faSCharlie Barto + config.debug_info_flags 162a6bdf3faSCharlie Barto + target_cflags 163a6bdf3faSCharlie Barto ) 164a6bdf3faSCharlie Barto if config.compiler_id != "MSVC": 165a6bdf3faSCharlie Barto clang_cl_cxxflags = ["-Wno-deprecated-declarations"] + clang_cl_cxxflags 1668007ff1aSReid Kleckner clang_cl_asan_cxxflags = ["-fsanitize=address"] + clang_cl_cxxflags 1678007ff1aSReid Kleckner if config.asan_dynamic: 1688007ff1aSReid Kleckner clang_cl_asan_cxxflags.append("-MD") 1698007ff1aSReid Kleckner 1708007ff1aSReid Kleckner clang_cl_invocation = build_invocation(clang_cl_cxxflags) 1718007ff1aSReid Kleckner clang_cl_invocation = clang_cl_invocation.replace("clang.exe", "clang-cl.exe") 1728007ff1aSReid Kleckner config.substitutions.append(("%clang_cl ", clang_cl_invocation)) 1738007ff1aSReid Kleckner 1748007ff1aSReid Kleckner clang_cl_asan_invocation = build_invocation(clang_cl_asan_cxxflags) 175f98ee40fSTobias Hieta clang_cl_asan_invocation = clang_cl_asan_invocation.replace( 176f98ee40fSTobias Hieta "clang.exe", "clang-cl.exe" 177f98ee40fSTobias Hieta ) 1788007ff1aSReid Kleckner config.substitutions.append(("%clang_cl_asan ", clang_cl_asan_invocation)) 179fe4a5a08SAlvin Wong config.substitutions.append(("%clang_cl_nocxx_asan ", clang_cl_asan_invocation)) 1803c1aa20cSAlvin Wong config.substitutions.append(("%Od", "-Od")) 1813c1aa20cSAlvin Wong config.substitutions.append(("%Fe", "-Fe")) 1825ad8bbeeSAlvin Wong config.substitutions.append(("%LD", "-LD")) 1835ad8bbeeSAlvin Wong config.substitutions.append(("%MD", "-MD")) 1845ad8bbeeSAlvin Wong config.substitutions.append(("%MT", "-MT")) 185fe4a5a08SAlvin Wong config.substitutions.append(("%Gw", "-Gw")) 1868007ff1aSReid Kleckner 187f98ee40fSTobias Hieta base_lib = os.path.join( 188f98ee40fSTobias Hieta config.compiler_rt_libdir, "clang_rt.asan%%s%s.lib" % config.target_suffix 189f98ee40fSTobias Hieta ) 19053a81d4dSCharlie Barto config.substitutions.append(("%asan_lib", base_lib % "_dynamic")) 19153a81d4dSCharlie Barto if config.asan_dynamic: 19253a81d4dSCharlie Barto config.substitutions.append( 19353a81d4dSCharlie Barto ("%asan_thunk", base_lib % "_dynamic_runtime_thunk") 19453a81d4dSCharlie Barto ) 19553a81d4dSCharlie Barto else: 19653a81d4dSCharlie Barto config.substitutions.append( 19753a81d4dSCharlie Barto ("%asan_thunk", base_lib % "_static_runtime_thunk") 19853a81d4dSCharlie Barto ) 1998007ff1aSReid Kleckner config.substitutions.append(("%asan_cxx_lib", base_lib % "_cxx")) 20053a81d4dSCharlie Barto config.substitutions.append( 20153a81d4dSCharlie Barto ("%asan_dynamic_runtime_thunk", base_lib % "_dynamic_runtime_thunk") 20253a81d4dSCharlie Barto ) 20353a81d4dSCharlie Barto config.substitutions.append( 20453a81d4dSCharlie Barto ("%asan_static_runtime_thunk", base_lib % "_static_runtime_thunk") 20553a81d4dSCharlie Barto ) 2068007ff1aSReid Kleckner config.substitutions.append(("%asan_dll_thunk", base_lib % "_dll_thunk")) 2073c1aa20cSAlvin Wong else: 2083c1aa20cSAlvin Wong # To make some of these tests work on MinGW target without changing their 2093c1aa20cSAlvin Wong # behaviour for MSVC target, substitute clang-cl flags with gcc-like ones. 2103c1aa20cSAlvin Wong config.substitutions.append(("%clang_cl ", build_invocation(target_cxxflags))) 211f98ee40fSTobias Hieta config.substitutions.append( 212f98ee40fSTobias Hieta ("%clang_cl_asan ", build_invocation(clang_asan_cxxflags)) 213f98ee40fSTobias Hieta ) 214f98ee40fSTobias Hieta config.substitutions.append( 215f98ee40fSTobias Hieta ("%clang_cl_nocxx_asan ", build_invocation(clang_asan_cflags)) 216f98ee40fSTobias Hieta ) 2173c1aa20cSAlvin Wong config.substitutions.append(("%Od", "-O0")) 2183c1aa20cSAlvin Wong config.substitutions.append(("%Fe", "-o")) 2195ad8bbeeSAlvin Wong config.substitutions.append(("%LD", "-shared")) 2205ad8bbeeSAlvin Wong config.substitutions.append(("%MD", "")) 2215ad8bbeeSAlvin Wong config.substitutions.append(("%MT", "")) 222fe4a5a08SAlvin Wong config.substitutions.append(("%Gw", "-fdata-sections")) 2238007ff1aSReid Kleckner 2248007ff1aSReid Kleckner# FIXME: De-hardcode this path. 2258007ff1aSReid Klecknerasan_source_dir = os.path.join( 226f98ee40fSTobias Hieta get_required_attr(config, "compiler_rt_src_root"), "lib", "asan" 227f98ee40fSTobias Hieta) 228aa6cb0f2SFangrui Songpython_exec = shlex.quote(get_required_attr(config, "python_executable")) 2298007ff1aSReid Kleckner# Setup path to asan_symbolize.py script. 2308007ff1aSReid Klecknerasan_symbolize = os.path.join(asan_source_dir, "scripts", "asan_symbolize.py") 2318007ff1aSReid Klecknerif not os.path.exists(asan_symbolize): 2328007ff1aSReid Kleckner lit_config.fatal("Can't find script on path %r" % asan_symbolize) 233f98ee40fSTobias Hietaconfig.substitutions.append( 234f98ee40fSTobias Hieta ("%asan_symbolize", python_exec + " " + asan_symbolize + " ") 235f98ee40fSTobias Hieta) 2368007ff1aSReid Kleckner# Setup path to sancov.py script. 2378007ff1aSReid Klecknersanitizer_common_source_dir = os.path.join( 238f98ee40fSTobias Hieta get_required_attr(config, "compiler_rt_src_root"), "lib", "sanitizer_common" 239f98ee40fSTobias Hieta) 2408007ff1aSReid Klecknersancov = os.path.join(sanitizer_common_source_dir, "scripts", "sancov.py") 2418007ff1aSReid Klecknerif not os.path.exists(sancov): 2428007ff1aSReid Kleckner lit_config.fatal("Can't find script on path %r" % sancov) 2438007ff1aSReid Klecknerconfig.substitutions.append(("%sancov ", python_exec + " " + sancov + " ")) 2448007ff1aSReid Kleckner 2458007ff1aSReid Kleckner# Determine kernel bitness 246f98ee40fSTobias Hietaif config.host_arch.find("64") != -1 and not config.android: 247f98ee40fSTobias Hieta kernel_bits = "64" 2488007ff1aSReid Klecknerelse: 249f98ee40fSTobias Hieta kernel_bits = "32" 2508007ff1aSReid Kleckner 251f98ee40fSTobias Hietaconfig.substitutions.append( 252f98ee40fSTobias Hieta ("CHECK-%kernel_bits", ("CHECK-kernel-" + kernel_bits + "-bits")) 253f98ee40fSTobias Hieta) 2548007ff1aSReid Kleckner 2558007ff1aSReid Klecknerconfig.substitutions.append(("%libdl", libdl_flag)) 2568007ff1aSReid Kleckner 2578007ff1aSReid Klecknerconfig.available_features.add("asan-" + config.bits + "-bits") 2588007ff1aSReid Kleckner 2598007ff1aSReid Kleckner# Fast unwinder doesn't work with Thumb 260039126c9SAdhemerval Zanellaif not config.arm_thumb: 261f98ee40fSTobias Hieta config.available_features.add("fast-unwinder-works") 2628007ff1aSReid Kleckner 2638007ff1aSReid Kleckner# Turn on leak detection on 64-bit Linux. 264f98ee40fSTobias Hietaleak_detection_android = ( 265f98ee40fSTobias Hieta config.android 266f98ee40fSTobias Hieta and "android-thread-properties-api" in config.available_features 267f98ee40fSTobias Hieta and (config.target_arch in ["x86_64", "i386", "i686", "aarch64"]) 268f98ee40fSTobias Hieta) 269f98ee40fSTobias Hietaleak_detection_linux = ( 270f98ee40fSTobias Hieta (config.host_os == "Linux") 271f98ee40fSTobias Hieta and (not config.android) 272f98ee40fSTobias Hieta and (config.target_arch in ["x86_64", "i386", "riscv64", "loongarch64"]) 273f98ee40fSTobias Hieta) 274f98ee40fSTobias Hietaleak_detection_mac = (config.host_os == "Darwin") and (config.apple_platform == "osx") 275f98ee40fSTobias Hietaleak_detection_netbsd = (config.host_os == "NetBSD") and ( 276f98ee40fSTobias Hieta config.target_arch in ["x86_64", "i386"] 277f98ee40fSTobias Hieta) 278f98ee40fSTobias Hietaif ( 279f98ee40fSTobias Hieta leak_detection_android 280f98ee40fSTobias Hieta or leak_detection_linux 281f98ee40fSTobias Hieta or leak_detection_mac 282f98ee40fSTobias Hieta or leak_detection_netbsd 283f98ee40fSTobias Hieta): 284f98ee40fSTobias Hieta config.available_features.add("leak-detection") 2858007ff1aSReid Kleckner 2868007ff1aSReid Kleckner# Add the RT libdir to PATH directly so that we can successfully run the gtest 2878007ff1aSReid Kleckner# binary to list its tests. 28853a81d4dSCharlie Bartoif config.host_os == "Windows": 289f98ee40fSTobias Hieta os.environ["PATH"] = os.path.pathsep.join( 290f98ee40fSTobias Hieta [config.compiler_rt_libdir, os.environ.get("PATH", "")] 291f98ee40fSTobias Hieta ) 2928007ff1aSReid Kleckner 293a6bdf3faSCharlie Barto# msvc needs to be instructed where the compiler-rt libraries are 294a6bdf3faSCharlie Bartoif config.compiler_id == "MSVC": 295a6bdf3faSCharlie Barto config.environment["LIB"] = os.path.pathsep.join( 296a6bdf3faSCharlie Barto [config.compiler_rt_libdir, config.environment.get("LIB", "")] 297a6bdf3faSCharlie Barto ) 298a6bdf3faSCharlie Barto 2998007ff1aSReid Kleckner# Default test suffixes. 300f98ee40fSTobias Hietaconfig.suffixes = [".c", ".cpp"] 3018007ff1aSReid Kleckner 302f98ee40fSTobias Hietaif config.host_os == "Darwin": 303f98ee40fSTobias Hieta config.suffixes.append(".mm") 3048007ff1aSReid Kleckner 305f98ee40fSTobias Hietaif config.host_os == "Windows": 306f98ee40fSTobias Hieta config.substitutions.append(("%fPIC", "")) 307f98ee40fSTobias Hieta config.substitutions.append(("%fPIE", "")) 308f98ee40fSTobias Hieta config.substitutions.append(("%pie", "")) 3098007ff1aSReid Klecknerelse: 310f98ee40fSTobias Hieta config.substitutions.append(("%fPIC", "-fPIC")) 311f98ee40fSTobias Hieta config.substitutions.append(("%fPIE", "-fPIE")) 312f98ee40fSTobias Hieta config.substitutions.append(("%pie", "-pie")) 3138007ff1aSReid Kleckner 3148007ff1aSReid Kleckner# Only run the tests on supported OSs. 315f98ee40fSTobias Hietaif config.host_os not in ["Linux", "Darwin", "FreeBSD", "SunOS", "Windows", "NetBSD"]: 3168007ff1aSReid Kleckner config.unsupported = True 3178007ff1aSReid Kleckner 3188007ff1aSReid Klecknerif not config.parallelism_group: 319f98ee40fSTobias Hieta config.parallelism_group = "shadow-memory" 3206c2b2b9eSMichał Górny 321f98ee40fSTobias Hietaif config.host_os == "NetBSD": 322f98ee40fSTobias Hieta config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) 323