Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1043,6 +1043,10 @@ Group; def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">, Group; +def fsanitize_runtime : Flag<["-"], "fsanitize-runtime">, + Group; +def fno_sanitize_runtime : Flag<["-"], "fno-sanitize-runtime">, + Group; def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">, Group; def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">, Index: clang/include/clang/Driver/SanitizerArgs.h =================================================================== --- clang/include/clang/Driver/SanitizerArgs.h +++ clang/include/clang/Driver/SanitizerArgs.h @@ -49,6 +49,7 @@ bool TsanFuncEntryExit = true; bool TsanAtomics = true; bool MinimalRuntime = false; + bool SanitizerRuntime = true; // True if cross-dso CFI support if provided by the system (i.e. Android). bool ImplicitCfiRuntime = false; @@ -58,24 +59,40 @@ bool needsSharedRt() const { return SharedRuntime; } - bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); } - bool needsHwasanRt() const { return Sanitizers.has(SanitizerKind::HWAddress); } - bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } - bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } - bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } + bool needsAsanRt() const { + return Sanitizers.has(SanitizerKind::Address) && SanitizerRuntime; + } + bool needsHwasanRt() const { + return Sanitizers.has(SanitizerKind::HWAddress) && SanitizerRuntime; + } + bool needsTsanRt() const { + return Sanitizers.has(SanitizerKind::Thread) && SanitizerRuntime; + } + bool needsMsanRt() const { + return Sanitizers.has(SanitizerKind::Memory) && SanitizerRuntime; + } + bool needsFuzzer() const { + return Sanitizers.has(SanitizerKind::Fuzzer) && SanitizerRuntime; + } bool needsLsanRt() const { return Sanitizers.has(SanitizerKind::Leak) && !Sanitizers.has(SanitizerKind::Address) && - !Sanitizers.has(SanitizerKind::HWAddress); + !Sanitizers.has(SanitizerKind::HWAddress) && SanitizerRuntime; } bool needsUbsanRt() const; - bool requiresMinimalRuntime() const { return MinimalRuntime; } - bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); } - bool needsSafeStackRt() const { return SafeStackRuntime; } + bool requiresMinimalRuntime() const { + return MinimalRuntime && SanitizerRuntime; + } + bool needsDfsanRt() const { + return Sanitizers.has(SanitizerKind::DataFlow) && SanitizerRuntime; + } + bool needsSafeStackRt() const { return SafeStackRuntime && SanitizerRuntime; } bool needsCfiRt() const; bool needsCfiDiagRt() const; - bool needsStatsRt() const { return Stats; } - bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); } + bool needsStatsRt() const { return Stats && SanitizerRuntime; } + bool needsScudoRt() const { + return Sanitizers.has(SanitizerKind::Scudo) && SanitizerRuntime; + } bool requiresPIE() const; bool needsUnwindTables() const; Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -208,7 +208,7 @@ // All of these include ubsan. if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || - (needsScudoRt() && !requiresMinimalRuntime())) + (needsScudoRt() && !requiresMinimalRuntime()) || !SanitizerRuntime) return false; return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || @@ -217,12 +217,12 @@ bool SanitizerArgs::needsCfiRt() const { return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && - CfiCrossDso && !ImplicitCfiRuntime; + CfiCrossDso && !ImplicitCfiRuntime && SanitizerRuntime; } bool SanitizerArgs::needsCfiDiagRt() const { return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && - CfiCrossDso && !ImplicitCfiRuntime; + CfiCrossDso && !ImplicitCfiRuntime && SanitizerRuntime; } bool SanitizerArgs::requiresPIE() const { @@ -265,6 +265,10 @@ Args.hasFlag(options::OPT_fsanitize_minimal_runtime, options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime); + SanitizerRuntime = + Args.hasFlag(options::OPT_fsanitize_runtime, + options::OPT_fno_sanitize_runtime, SanitizerRuntime); + // The object size sanitizer should not be enabled at -O0. Arg *OptLevel = Args.getLastArg(options::OPT_O_Group); bool RemoveObjectSizeAtO0 = Index: clang/test/Driver/sanitizer-ld.c =================================================================== --- clang/test/Driver/sanitizer-ld.c +++ clang/test/Driver/sanitizer-ld.c @@ -28,6 +28,14 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-SHARED-ASAN-LINUX %s +// RUN: %clang -fsanitize=address -fno-sanitize-runtime %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-unknown-linux -fuse-ld=ld \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-NO-RUNTIME-LINUX %s +// +// CHECK-ASAN-NO-RUNTIME-LINUX-NOT: libclang_rt.asan-x86_64.a" + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=address \ // RUN: -shared-libsan -static-libsan -shared-libasan \