summaryrefslogtreecommitdiff
path: root/lib/Driver/SanitizerArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/SanitizerArgs.cpp')
-rw-r--r--lib/Driver/SanitizerArgs.cpp166
1 files changed, 128 insertions, 38 deletions
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 7a442c83e158..f617d8b4551e 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -29,10 +29,12 @@ enum : SanitizerMask {
NeedsUbsanRt = Undefined | Integer | Nullability | CFI,
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
- RequiresPIE = DataFlow,
- NeedsUnwindTables = Address | Thread | Memory | DataFlow,
- SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
- Integer | Nullability | DataFlow | Fuzzer,
+ NotAllowedWithMinimalRuntime = Vptr,
+ RequiresPIE = DataFlow | Scudo,
+ NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
+ SupportsCoverage = Address | HWAddress | KernelAddress | Memory | Leak |
+ Undefined | Integer | Nullability | DataFlow | Fuzzer |
+ FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | Nullability,
Unrecoverable = Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
@@ -41,6 +43,7 @@ enum : SanitizerMask {
Nullability | LocalBounds | CFI,
TrappingDefault = CFI,
CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
+ CompatibleWithMinimalRuntime = TrappingSupported,
};
enum CoverageFeature {
@@ -55,8 +58,10 @@ enum CoverageFeature {
Coverage8bitCounters = 1 << 8, // Deprecated.
CoverageTracePC = 1 << 9,
CoverageTracePCGuard = 1 << 10,
- CoverageInline8bitCounters = 1 << 12,
CoverageNoPrune = 1 << 11,
+ CoverageInline8bitCounters = 1 << 12,
+ CoveragePCTable = 1 << 13,
+ CoverageStackDepth = 1 << 14,
};
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -92,6 +97,8 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
const char *BlacklistFile = nullptr;
if (Kinds & Address)
BlacklistFile = "asan_blacklist.txt";
+ else if (Kinds & HWAddress)
+ BlacklistFile = "hwasan_blacklist.txt";
else if (Kinds & Memory)
BlacklistFile = "msan_blacklist.txt";
else if (Kinds & Thread)
@@ -100,6 +107,8 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
BlacklistFile = "dfsan_abilist.txt";
else if (Kinds & CFI)
BlacklistFile = "cfi_blacklist.txt";
+ else if (Kinds & (Undefined | Integer | Nullability))
+ BlacklistFile = "ubsan_blacklist.txt";
if (BlacklistFile) {
clang::SmallString<64> Path(D.ResourceDir);
@@ -165,19 +174,23 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
}
bool SanitizerArgs::needsUbsanRt() const {
- return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
- CoverageFeatures) &&
- !Sanitizers.has(Address) && !Sanitizers.has(Memory) &&
- !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) &&
- !Sanitizers.has(Leak) && !CfiCrossDso;
+ // All of these include ubsan.
+ if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
+ needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || needsScudoRt())
+ return false;
+
+ return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
+ CoverageFeatures;
}
bool SanitizerArgs::needsCfiRt() const {
- return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
+ return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
+ !ImplicitCfiRuntime;
}
bool SanitizerArgs::needsCfiDiagRt() const {
- return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
+ return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
+ !ImplicitCfiRuntime;
}
bool SanitizerArgs::requiresPIE() const {
@@ -208,6 +221,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
+ MinimalRuntime =
+ Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
+ options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
+
// The object size sanitizer should not be enabled at -O0.
Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
bool RemoveObjectSizeAtO0 =
@@ -245,6 +262,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
DiagnosedKinds |= KindsToDiagnose;
}
Add &= ~InvalidTrappingKinds;
+
+ if (MinimalRuntime) {
+ if (SanitizerMask KindsToDiagnose =
+ Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
+ std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << Desc << "-fsanitize-minimal-runtime";
+ DiagnosedKinds |= KindsToDiagnose;
+ }
+ Add &= ~NotAllowedWithMinimalRuntime;
+ }
+
if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
@@ -281,11 +310,22 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Silently discard any unsupported sanitizers implicitly enabled through
// group expansion.
Add &= ~InvalidTrappingKinds;
+ if (MinimalRuntime) {
+ Add &= ~NotAllowedWithMinimalRuntime;
+ }
Add &= Supported;
- // Enable coverage if the fuzzing flag is set.
if (Add & Fuzzer)
- CoverageFeatures |= CoverageTracePCGuard | CoverageIndirCall | CoverageTraceCmp;
+ Add |= FuzzerNoLink;
+
+ // Enable coverage if the fuzzing flag is set.
+ if (Add & FuzzerNoLink) {
+ CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
+ CoverageTraceCmp | CoveragePCTable;
+ // Due to TLS differences, stack depth tracking is only enabled on Linux
+ if (TC.getTriple().isOSLinux())
+ CoverageFeatures |= CoverageStackDepth;
+ }
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
@@ -333,17 +373,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Warn about incompatible groups of sanitizers.
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
- std::make_pair(Address, Thread), std::make_pair(Address, Memory),
- std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
- std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
- std::make_pair(KernelAddress, Leak),
- std::make_pair(KernelAddress, Thread),
- std::make_pair(KernelAddress, Memory),
- std::make_pair(Efficiency, Address),
- std::make_pair(Efficiency, Leak),
- std::make_pair(Efficiency, Thread),
- std::make_pair(Efficiency, Memory),
- std::make_pair(Efficiency, KernelAddress)};
+ std::make_pair(Address, Thread | Memory),
+ std::make_pair(Thread, Memory),
+ std::make_pair(Leak, Thread | Memory),
+ std::make_pair(KernelAddress, Address | Leak | Thread | Memory),
+ std::make_pair(HWAddress, Address | Thread | Memory | KernelAddress),
+ std::make_pair(Efficiency, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress),
+ std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress | Efficiency)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
@@ -456,9 +494,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
MsanUseAfterDtor =
- Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
+ Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
+ options::OPT_fno_sanitize_memory_use_after_dtor,
+ MsanUseAfterDtor);
NeedPIE |= !(TC.getTriple().isOSLinux() &&
TC.getTriple().getArch() == llvm::Triple::x86_64);
+ } else {
+ MsanUseAfterDtor = false;
}
if (AllAddedKinds & Thread) {
@@ -479,11 +521,33 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Without PIE, external function address may resolve to a PLT record, which
// can not be verified by the target module.
NeedPIE |= CfiCrossDso;
+ CfiICallGeneralizePointers =
+ Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
+
+ if (CfiCrossDso && CfiICallGeneralizePointers)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-cfi-cross-dso"
+ << "-fsanitize-cfi-icall-generalize-pointers";
}
Stats = Args.hasFlag(options::OPT_fsanitize_stats,
options::OPT_fno_sanitize_stats, false);
+ if (MinimalRuntime) {
+ SanitizerMask IncompatibleMask =
+ Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
+ if (IncompatibleMask)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-minimal-runtime"
+ << lastArgumentForMask(D, Args, IncompatibleMask);
+
+ SanitizerMask NonTrappingCfi = Kinds & CFI & ~TrappingKinds;
+ if (NonTrappingCfi)
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "fsanitize-minimal-runtime"
+ << "fsanitize-trap=cfi";
+ }
+
// Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
// enabled sanitizers.
for (const auto *Arg : Args) {
@@ -504,7 +568,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Disable coverage and not claim the flags if there is at least one
// non-supporting sanitizer.
- if (!(AllAddedKinds & ~setGroupBits(SupportsCoverage))) {
+ if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
Arg->claim();
} else {
CoverageFeatures = 0;
@@ -539,23 +603,34 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< "-fsanitize-coverage=trace-pc-guard";
int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
+ int InstrumentationTypes =
+ CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters;
if ((CoverageFeatures & InsertionPointTypes) &&
- !(CoverageFeatures &(CoverageTracePC | CoverageTracePCGuard))) {
+ !(CoverageFeatures & InstrumentationTypes)) {
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=[func|bb|edge]"
<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
}
// trace-pc w/o func/bb/edge implies edge.
- if ((CoverageFeatures &
- (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) &&
- !(CoverageFeatures & InsertionPointTypes))
- CoverageFeatures |= CoverageEdge;
+ if (!(CoverageFeatures & InsertionPointTypes)) {
+ if (CoverageFeatures &
+ (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters))
+ CoverageFeatures |= CoverageEdge;
+
+ if (CoverageFeatures & CoverageStackDepth)
+ CoverageFeatures |= CoverageFunc;
+ }
+
+ SharedRuntime =
+ Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
+ TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
+ TC.getTriple().isOSDarwin());
+
+ ImplicitCfiRuntime = TC.getTriple().isAndroid();
if (AllAddedKinds & Address) {
- AsanSharedRuntime =
- Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
- NeedPIE |= TC.getTriple().isAndroid();
+ NeedPIE |= TC.getTriple().isOSFuchsia();
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
StringRef S = A->getValue();
@@ -589,12 +664,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// globals in ASan is disabled by default on ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
AsanGlobalsDeadStripping =
- !TC.getTriple().isOSBinFormatELF() ||
+ !TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
} else {
AsanUseAfterScope = false;
}
+ if (AllAddedKinds & SafeStack) {
+ // SafeStack runtime is built into the system on Fuchsia.
+ SafeStackRuntime = !TC.getTriple().isOSFuchsia();
+ }
+
// Parse -link-cxx-sanitizer flag.
LinkCXXRuntimes =
Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
@@ -656,7 +736,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"),
std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"),
- std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")};
+ std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
+ std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
+ std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")};
for (auto F : CoverageFlags) {
if (CoverageFeatures & F.first)
CmdArgs.push_back(F.second);
@@ -733,9 +815,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (CfiCrossDso)
CmdArgs.push_back("-fsanitize-cfi-cross-dso");
+ if (CfiICallGeneralizePointers)
+ CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
+
if (Stats)
CmdArgs.push_back("-fsanitize-stats");
+ if (MinimalRuntime)
+ CmdArgs.push_back("-fsanitize-minimal-runtime");
+
if (AsanFieldPadding)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
llvm::utostr(AsanFieldPadding)));
@@ -748,7 +836,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// MSan: Workaround for PR16386.
// ASan: This is mainly to help LSan with cases such as
- // https://code.google.com/p/address-sanitizer/issues/detail?id=373
+ // https://github.com/google/sanitizers/issues/373
// We can't make this conditional on -fsanitize=leak, as that flag shouldn't
// affect compilation.
if (Sanitizers.has(Memory) || Sanitizers.has(Address))
@@ -818,6 +906,8 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
.Case("trace-pc-guard", CoverageTracePCGuard)
.Case("no-prune", CoverageNoPrune)
.Case("inline-8bit-counters", CoverageInline8bitCounters)
+ .Case("pc-table", CoveragePCTable)
+ .Case("stack-depth", CoverageStackDepth)
.Default(0);
if (F == 0)
D.Diag(clang::diag::err_drv_unsupported_option_argument)