mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Determine whether a given sanitizer is available based on the presenc… (#14919)
Determine whether a given sanitizer is available based on the presence of the library. rdar://37192887
This commit is contained in:
@@ -199,8 +199,10 @@ public:
|
||||
///
|
||||
/// \param args Invocation arguments.
|
||||
/// \param sanitizer Sanitizer name.
|
||||
/// \param shared Whether the library is shared
|
||||
virtual bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
|
||||
StringRef sanitizer) const;
|
||||
StringRef sanitizer,
|
||||
bool shared=true) const;
|
||||
|
||||
};
|
||||
} // end namespace driver
|
||||
|
||||
@@ -32,11 +32,9 @@ class DiagnosticEngine;
|
||||
// sanitizer dylib with a given name.
|
||||
/// \return Returns a SanitizerKind.
|
||||
OptionSet<SanitizerKind> parseSanitizerArgValues(
|
||||
const llvm::opt::ArgList &Args,
|
||||
const llvm::opt::Arg *A,
|
||||
const llvm::Triple &Triple,
|
||||
DiagnosticEngine &Diag,
|
||||
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists);
|
||||
const llvm::opt::ArgList &Args, const llvm::opt::Arg *A,
|
||||
const llvm::Triple &Triple, DiagnosticEngine &Diag,
|
||||
llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists);
|
||||
|
||||
/// \brief Parses a -sanitize-coverage= argument's value.
|
||||
llvm::SanitizerCoverageOptions parseSanitizerCoverageArgValue(
|
||||
|
||||
@@ -1356,8 +1356,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ))
|
||||
OI.SelectedSanitizers = parseSanitizerArgValues(
|
||||
Args, A, TC.getTriple(), Diags,
|
||||
[&](StringRef sanitizerName) {
|
||||
return TC.sanitizerRuntimeLibExists(Args, sanitizerName);
|
||||
[&](StringRef sanitizerName, bool shared) {
|
||||
return TC.sanitizerRuntimeLibExists(Args, sanitizerName, shared);
|
||||
});
|
||||
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ)) {
|
||||
|
||||
@@ -317,7 +317,8 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> jobs,
|
||||
|
||||
bool
|
||||
ToolChain::sanitizerRuntimeLibExists(const ArgList &args,
|
||||
StringRef sanitizerName) const {
|
||||
StringRef sanitizerName,
|
||||
bool shared) const {
|
||||
// Assume no sanitizers are supported by default.
|
||||
// This method should be overriden by a platform-specific subclass.
|
||||
return false;
|
||||
|
||||
@@ -1132,18 +1132,21 @@ getSanitizerRuntimeLibNameForLinux(StringRef Sanitizer, const llvm::Triple &Trip
|
||||
}
|
||||
|
||||
bool toolchains::Darwin::sanitizerRuntimeLibExists(
|
||||
const ArgList &args, StringRef sanitizer) const {
|
||||
const ArgList &args, StringRef sanitizer, bool shared) const {
|
||||
SmallString<128> sanitizerLibPath;
|
||||
getClangLibraryPath(*this, args, sanitizerLibPath);
|
||||
llvm::sys::path::append(sanitizerLibPath,
|
||||
getSanitizerRuntimeLibNameForDarwin(sanitizer, this->getTriple()));
|
||||
getSanitizerRuntimeLibNameForDarwin(
|
||||
sanitizer, this->getTriple(), shared));
|
||||
return llvm::sys::fs::exists(sanitizerLibPath.str());
|
||||
}
|
||||
|
||||
bool toolchains::GenericUnix::sanitizerRuntimeLibExists(
|
||||
const ArgList &args, StringRef sanitizer) const {
|
||||
const ArgList &args, StringRef sanitizer, bool shared) const {
|
||||
SmallString<128> sanitizerLibPath;
|
||||
getClangLibraryPath(*this, args, sanitizerLibPath);
|
||||
|
||||
// All libraries are static for linux.
|
||||
llvm::sys::path::append(sanitizerLibPath,
|
||||
getSanitizerRuntimeLibNameForLinux(sanitizer, this->getTriple()));
|
||||
return llvm::sys::fs::exists(sanitizerLibPath.str());
|
||||
@@ -1784,4 +1787,3 @@ std::string toolchains::Cygwin::getDefaultLinker() const {
|
||||
std::string toolchains::Cygwin::getTargetForLinker() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ public:
|
||||
Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
|
||||
~Darwin() = default;
|
||||
bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
|
||||
StringRef sanitizerLibName)
|
||||
StringRef sanitizerLibName,
|
||||
bool shared)
|
||||
const override;
|
||||
};
|
||||
|
||||
@@ -73,7 +74,8 @@ public:
|
||||
GenericUnix(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
|
||||
~GenericUnix() = default;
|
||||
bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
|
||||
StringRef sanitizerLibName)
|
||||
StringRef sanitizerLibName,
|
||||
bool shared)
|
||||
const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -686,7 +686,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ)) {
|
||||
Opts.Sanitizers = parseSanitizerArgValues(
|
||||
Args, A, Triple, Diags,
|
||||
/* sanitizerRuntimeLibExists= */[](StringRef libName) {
|
||||
/* sanitizerRuntimeLibExists= */[](StringRef libName, bool shared) {
|
||||
|
||||
// The driver has checked the existence of the library
|
||||
// already.
|
||||
|
||||
@@ -41,6 +41,18 @@ static StringRef toStringRef(const SanitizerKind kind) {
|
||||
llvm_unreachable("Unsupported sanitizer");
|
||||
}
|
||||
|
||||
static const char* toFileName(const SanitizerKind kind) {
|
||||
switch (kind) {
|
||||
case SanitizerKind::Address:
|
||||
return "asan";
|
||||
case SanitizerKind::Thread:
|
||||
return "tsan";
|
||||
case SanitizerKind::Fuzzer:
|
||||
return "fuzzer";
|
||||
}
|
||||
llvm_unreachable("Unsupported sanitizer");
|
||||
}
|
||||
|
||||
llvm::SanitizerCoverageOptions swift::parseSanitizerCoverageArgValue(
|
||||
const llvm::opt::Arg *A, const llvm::Triple &Triple,
|
||||
DiagnosticEngine &Diags, OptionSet<SanitizerKind> sanitizers) {
|
||||
@@ -108,33 +120,43 @@ llvm::SanitizerCoverageOptions swift::parseSanitizerCoverageArgValue(
|
||||
return opts;
|
||||
}
|
||||
|
||||
static bool isTSanSupported(
|
||||
const llvm::Triple &Triple,
|
||||
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
|
||||
|
||||
return Triple.isArch64Bit() && sanitizerRuntimeLibExists("tsan");
|
||||
}
|
||||
|
||||
OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
|
||||
const llvm::opt::ArgList &Args,
|
||||
const llvm::opt::Arg *A,
|
||||
const llvm::Triple &Triple,
|
||||
DiagnosticEngine &Diags,
|
||||
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
|
||||
llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists) {
|
||||
OptionSet<SanitizerKind> sanitizerSet;
|
||||
|
||||
// Find the sanitizer kind.
|
||||
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
|
||||
StringRef opt = A->getValue(i);
|
||||
if (opt == "address") {
|
||||
sanitizerSet |= SanitizerKind::Address;
|
||||
} else if (opt == "thread") {
|
||||
sanitizerSet |= SanitizerKind::Thread;
|
||||
} else if (opt == "fuzzer") {
|
||||
sanitizerSet |= SanitizerKind::Fuzzer;
|
||||
} else {
|
||||
auto kind = llvm::StringSwitch<Optional<SanitizerKind>>(A->getValue(i))
|
||||
.Case("address", SanitizerKind::Address)
|
||||
.Case("thread", SanitizerKind::Thread)
|
||||
.Case("fuzzer", SanitizerKind::Fuzzer)
|
||||
.Default(None);
|
||||
bool isShared = kind && *kind != SanitizerKind::Fuzzer;
|
||||
if (!kind) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
|
||||
A->getOption().getPrefixedName(), A->getValue(i));
|
||||
} else {
|
||||
// Support is determined by existance of the sanitizer library.
|
||||
bool sanitizerSupported =
|
||||
sanitizerRuntimeLibExists(toFileName(*kind), isShared);
|
||||
|
||||
// TSan is explicitly not supported for 32 bits.
|
||||
if (*kind == SanitizerKind::Thread && !Triple.isArch64Bit())
|
||||
sanitizerSupported = false;
|
||||
|
||||
if (!sanitizerSupported) {
|
||||
SmallString<128> b;
|
||||
Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
|
||||
(A->getOption().getPrefixedName() + toStringRef(*kind))
|
||||
.toStringRef(b),
|
||||
Triple.getTriple());
|
||||
} else {
|
||||
sanitizerSet |= *kind;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,16 +181,5 @@ OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
|
||||
+ toStringRef(SanitizerKind::Thread)).toStringRef(b2));
|
||||
}
|
||||
|
||||
// Thread Sanitizer only works on OS X and the simulators. It's only supported
|
||||
// on 64 bit architectures.
|
||||
if ((sanitizerSet & SanitizerKind::Thread) &&
|
||||
!isTSanSupported(Triple, sanitizerRuntimeLibExists)) {
|
||||
SmallString<128> b;
|
||||
Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
|
||||
(A->getOption().getPrefixedName()
|
||||
+ toStringRef(SanitizerKind::Thread)).toStringRef(b),
|
||||
Triple.getTriple());
|
||||
}
|
||||
|
||||
return sanitizerSet;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address %s | %FileCheck -check-prefix=LIBFUZZER %s
|
||||
// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER %s
|
||||
|
||||
// LIBFUZZER: libclang_rt.fuzzer
|
||||
@_cdecl("LLVMFuzzerTestOneInput") public func fuzzOneInput(Data: UnsafePointer<CChar>, Size: CLong) -> CInt {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_OSX %s
|
||||
// RUN: not %swiftc_driver -driver-print-jobs -sanitize=fuzzer -target x86_64-apple-macosx10.9 -resource-dir %S/Inputs/nonexistent-resource-dir %s 2>&1 | %FileCheck -check-prefix=FUZZER_NONEXISTENT %s
|
||||
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOSSIM %s
|
||||
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target arm64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOS %s
|
||||
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-tvos9.0 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_tvOS_SIM %s
|
||||
@@ -54,6 +55,7 @@
|
||||
// TSAN_tvOS: unsupported option '-sanitize=thread' for target 'arm64-apple-tvos9.0'
|
||||
// TSAN_watchOS_SIM: unsupported option '-sanitize=thread' for target 'i386-apple-watchos2.0'
|
||||
// TSAN_watchOS: unsupported option '-sanitize=thread' for target 'armv7k-apple-watchos2.0'
|
||||
// FUZZER_NONEXISTENT: unsupported option '-sanitize=fuzzer' for target 'x86_64-apple-macosx10.9'
|
||||
// TSAN_LINUX: lib/swift/clang/lib/linux/libclang_rt.tsan-x86_64.a
|
||||
|
||||
// TSAN: -rpath @executable_path
|
||||
|
||||
Reference in New Issue
Block a user