diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -220,8 +220,8 @@ "malformed sanitizer coverage ignorelist: '%0'">; def err_drv_malformed_sanitizer_metadata_ignorelist : Error< "malformed sanitizer metadata ignorelist: '%0'">; -def err_drv_unsupported_static_ubsan_darwin : Error< - "static UndefinedBehaviorSanitizer runtime is not supported on darwin">; +def err_drv_unsupported_static_sanitizer_darwin : Error< + "static %0 runtime is not supported on darwin">; def err_drv_duplicate_config : Error< "no more than one option '--config' is allowed">; def err_drv_cannot_open_config_file : Error< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1215,7 +1215,7 @@ def shared_libsan : Flag<["-"], "shared-libsan">, HelpText<"Dynamically link the sanitizer runtime">; def static_libsan : Flag<["-"], "static-libsan">, - HelpText<"Statically link the sanitizer runtime">; + HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">; def : Flag<["-"], "shared-libasan">, Alias; def fasm : Flag<["-"], "fasm">, Group; diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1426,24 +1426,42 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(Args); - if (!Sanitize.needsSharedRt() && Sanitize.needsUbsanRt()) { - getDriver().Diag(diag::err_drv_unsupported_static_ubsan_darwin); - return; + if (!Sanitize.needsSharedRt()) { + const char *sanitizer = nullptr; + if (Sanitize.needsUbsanRt()) { + sanitizer = "UndefinedBehaviorSanitizer"; + } else if (Sanitize.needsAsanRt()) { + sanitizer = "AddressSanitizer"; + } else if (Sanitize.needsTsanRt()) { + sanitizer = "ThreadSanitizer"; + } + if (sanitizer) { + getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin) + << sanitizer; + return; + } } if (Sanitize.linkRuntimes()) { - if (Sanitize.needsAsanRt()) + if (Sanitize.needsAsanRt()) { + assert(Sanitize.needsSharedRt() && + "Static sanitizer runtimes not supported"); AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + } if (Sanitize.needsLsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) { - assert(Sanitize.needsSharedRt() && "Static sanitizer runtimes not supported"); - AddLinkSanitizerLibArgs(Args, CmdArgs, - Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" - : "ubsan"); + assert(Sanitize.needsSharedRt() && + "Static sanitizer runtimes not supported"); + AddLinkSanitizerLibArgs( + Args, CmdArgs, + Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan"); } - if (Sanitize.needsTsanRt()) + if (Sanitize.needsTsanRt()) { + assert(Sanitize.needsSharedRt() && + "Static sanitizer runtimes not supported"); AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); + } if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false); diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -457,6 +457,18 @@ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-STATIC-DARWIN %s // CHECK-UBSAN-STATIC-DARWIN: {{.*}}error: static UndefinedBehaviorSanitizer runtime is not supported on darwin +// RUN: %clang -fsanitize=address -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin -fuse-ld=ld -static-libsan \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-STATIC-DARWIN %s +// CHECK-ASAN-STATIC-DARWIN: {{.*}}error: static AddressSanitizer runtime is not supported on darwin + +// RUN: %clang -fsanitize=thread -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin -fuse-ld=ld -static-libsan \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-TSAN-STATIC-DARWIN %s +// CHECK-TSAN-STATIC-DARWIN: {{.*}}error: static ThreadSanitizer runtime is not supported on darwin + // RUN: %clang -fsanitize=address,undefined -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld \ // RUN: -resource-dir=%S/Inputs/resource_dir \ diff --git a/compiler-rt/test/asan/TestCases/replaceable_new_delete.cpp b/compiler-rt/test/asan/TestCases/replaceable_new_delete_shared.cpp rename from compiler-rt/test/asan/TestCases/replaceable_new_delete.cpp rename to compiler-rt/test/asan/TestCases/replaceable_new_delete_shared.cpp --- a/compiler-rt/test/asan/TestCases/replaceable_new_delete.cpp +++ b/compiler-rt/test/asan/TestCases/replaceable_new_delete_shared.cpp @@ -1,4 +1,4 @@ -// Ensure that operator new/delete are still replaceable. +// Ensure that operator new/delete are still replaceable using shared-libsan. // FIXME: Weak symbols aren't supported on Windows, although some code in // compiler-rt already exists to solve this problem. We should probably define @@ -6,7 +6,6 @@ // UNSUPPORTED: target={{.*windows.*}} // RUN: %clangxx %s -o %t -fsanitize=address -shared-libsan && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx %s -o %t -fsanitize=address -static-libsan && not %run %t 2>&1 | FileCheck %s #include #include diff --git a/compiler-rt/test/asan/TestCases/replaceable_new_delete_static.cpp b/compiler-rt/test/asan/TestCases/replaceable_new_delete_static.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/replaceable_new_delete_static.cpp @@ -0,0 +1,35 @@ +// Ensure that operator new/delete are still replaceable using static-libsan. + +// FIXME: Weak symbols aren't supported on Windows, although some code in +// compiler-rt already exists to solve this problem. We should probably define +// the new/delete interceptors as "weak" using those workarounds as well. +// UNSUPPORTED: target={{.*windows.*}} + +// darwin only supports `shared-libsan`. +// UNSUPPORTED: darwin + +// RUN: %clangxx %s -o %t -fsanitize=address -static-libsan && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +void *operator new[](size_t size) { + fprintf(stderr, "replaced new\n"); + return malloc(size); +} + +void operator delete[](void *ptr) noexcept { + fprintf(stderr, "replaced delete\n"); + return free(ptr); +} + +int main(int argc, char **argv) { + // CHECK: replaced new + char *x = new char[5]; + // CHECK: replaced delete + delete[] x; + // CHECK: ERROR: AddressSanitizer + *x = 13; + return 0; +}