aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/SanitizerArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/SanitizerArgs.cpp')
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp116
1 files changed, 75 insertions, 41 deletions
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 403fac76f060..68fe90c7a69d 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -14,9 +14,9 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/AArch64TargetParser.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SpecialCaseList.h"
-#include "llvm/Support/AArch64TargetParser.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
@@ -44,7 +44,8 @@ static const SanitizerMask NeedsUnwindTables =
static const SanitizerMask SupportsCoverage =
SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
- SanitizerKind::MemTag | SanitizerKind::Memory |
+ SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
+ SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
SanitizerKind::KernelMemory | SanitizerKind::Leak |
SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
@@ -73,7 +74,8 @@ static const SanitizerMask CFIClasses =
SanitizerKind::CFIUnrelatedCast;
static const SanitizerMask CompatibleWithMinimalRuntime =
TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
- SanitizerKind::MemTag;
+ SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
+ SanitizerKind::MemtagGlobals;
enum CoverageFeature {
CoverageFunc = 1 << 0,
@@ -168,14 +170,14 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
// If cfi_ignorelist.txt cannot be found in the resource dir, driver
// should fail.
- D.Diag(clang::diag::err_drv_no_such_file) << Path;
+ D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
}
validateSpecialCaseListFormat(
D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
DiagnoseErrors);
}
-/// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values,
+/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
/// diagnosing any invalid file paths and validating special case list format.
static void parseSpecialCaseListArg(const Driver &D,
const llvm::opt::ArgList &Args,
@@ -185,7 +187,7 @@ static void parseSpecialCaseListArg(const Driver &D,
unsigned MalformedSCLErrorDiagID,
bool DiagnoseErrors) {
for (const auto *Arg : Args) {
- // Match -fsanitize-(coverage-)?(white|ignore)list.
+ // Match -fsanitize-(coverage-)?(allow|ignore)list.
if (Arg->getOption().matches(SCLOptionID)) {
Arg->claim();
std::string SCLPath = Arg->getValue();
@@ -218,9 +220,9 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
const llvm::opt::ArgList &Args,
bool DiagnoseErrors) {
- SanitizerMask TrapRemove; // During the loop below, the accumulated set of
- // sanitizers disabled by the current sanitizer
- // argument or any argument after it.
+ SanitizerMask TrapRemove; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
SanitizerMask TrappingKinds;
SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
@@ -233,8 +235,8 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
if (InvalidValues && DiagnoseErrors) {
SanitizerSet S;
S.Mask = InvalidValues;
- D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
- << toString(S);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << toString(S);
}
TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
@@ -293,13 +295,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask AllRemove; // During the loop below, the accumulated set of
// sanitizers disabled by the current sanitizer
// argument or any argument after it.
- SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
- // -fsanitize= flags (directly or via group
- // expansion), some of which may be disabled
- // later. Used to carefully prune
- // unused-argument diagnostics.
- SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
- // Used to deduplicate diagnostics.
+ SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
+ // -fsanitize= flags (directly or via group
+ // expansion), some of which may be disabled
+ // later. Used to carefully prune
+ // unused-argument diagnostics.
+ SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
+ // Used to deduplicate diagnostics.
SanitizerMask Kinds;
const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
@@ -367,6 +369,19 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Add &= ~NotAllowedWithMinimalRuntime;
}
+ if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ StringRef CM = A->getValue();
+ if (CM != "small" &&
+ (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
+ if (DiagnoseErrors)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << "-fsanitize=function"
+ << "-mcmodel=small";
+ Add &= ~SanitizerKind::Function;
+ DiagnosedKinds |= SanitizerKind::Function;
+ }
+ }
+
// FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
// There are currently two problems:
// - Virtual function call checks need to pass a pointer to the function
@@ -402,7 +417,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
- "RTTI disabled without -fno-rtti option?");
+ "RTTI disabled without -fno-rtti option?");
// The user explicitly passed -fno-rtti with -fsanitize=vptr, but
// the vptr sanitizer requires RTTI, so this is a user error.
if (DiagnoseErrors)
@@ -638,20 +653,36 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
}
- MsanUseAfterDtor =
- Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
- options::OPT_fno_sanitize_memory_use_after_dtor,
- MsanUseAfterDtor);
+ MsanUseAfterDtor = Args.hasFlag(
+ options::OPT_fsanitize_memory_use_after_dtor,
+ options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
MsanParamRetval = Args.hasFlag(
options::OPT_fsanitize_memory_param_retval,
options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
NeedPIE |= !(TC.getTriple().isOSLinux() &&
TC.getTriple().getArch() == llvm::Triple::x86_64);
+ } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
+ MsanUseAfterDtor = false;
+ MsanParamRetval = Args.hasFlag(
+ options::OPT_fsanitize_memory_param_retval,
+ options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
} else {
MsanUseAfterDtor = false;
MsanParamRetval = false;
}
+ if (AllAddedKinds & SanitizerKind::MemTag) {
+ StringRef S =
+ Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
+ if (S == "async" || S == "sync") {
+ MemtagMode = S.str();
+ } else {
+ D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
+ << "-fsanitize-memtag-mode=" << S << "{async, sync}";
+ MemtagMode = "sync";
+ }
+ }
+
if (AllAddedKinds & SanitizerKind::Thread) {
TsanMemoryAccess = Args.hasFlag(
options::OPT_fsanitize_thread_memory_access,
@@ -777,7 +808,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
CoverageFeatures |= CoverageFunc;
}
- // Parse -fsanitize-coverage-(ignore|white)list options if coverage enabled.
+ // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
// This also validates special case lists format.
// Here, OptSpecifier() acts as a never-matching command-line argument.
// So, there is no way to clear coverage lists but you can append to them.
@@ -805,13 +836,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
NeedPIE |= TC.getTriple().isOSFuchsia();
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
- StringRef S = A->getValue();
- // Legal values are 0 and 1, 2, but in future we may add more levels.
- if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
- AsanFieldPadding > 2) &&
- DiagnoseErrors) {
- D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
- }
+ StringRef S = A->getValue();
+ // Legal values are 0 and 1, 2, but in future we may add more levels.
+ if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
+ AsanFieldPadding > 2) &&
+ DiagnoseErrors) {
+ D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
}
if (Arg *WindowsDebugRTArg =
@@ -846,12 +877,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
AsanOutlineInstrumentation);
// As a workaround for a bug in gold 2.26 and earlier, dead stripping of
- // globals in ASan is disabled by default on ELF targets.
+ // globals in ASan is disabled by default on most ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
- AsanGlobalsDeadStripping =
+ AsanGlobalsDeadStripping = Args.hasFlag(
+ options::OPT_fsanitize_address_globals_dead_stripping,
+ options::OPT_fno_sanitize_address_globals_dead_stripping,
!TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
- TC.getTriple().isPS4() ||
- Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
+ TC.getTriple().isPS());
AsanUseOdrIndicator =
Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
@@ -994,7 +1026,8 @@ static void addIncludeLinkerOption(const ToolChain &TC,
}
static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
- for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; ++Start) {
+ for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
+ ++Start) {
auto It = std::find(Start, End, StringRef("+mte"));
if (It == End)
break;
@@ -1015,8 +1048,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
if (TC.getTriple().isNVPTX() ||
(TC.getTriple().isAMDGPU() &&
- !Args.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize)))
+ !Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ true)))
return;
// Translate available CoverageFeatures to corresponding clang-cc1 flags.
@@ -1230,7 +1263,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
<< "-fvisibility=";
}
- if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs))
+ if (Sanitizers.has(SanitizerKind::MemtagStack) &&
+ !hasTargetFeatureMTE(CmdArgs))
TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
}
@@ -1319,8 +1353,8 @@ std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
}
std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
- assert(A->getOption().matches(options::OPT_fsanitize_EQ)
- && "Invalid argument in describeSanitizerArg!");
+ assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
+ "Invalid argument in describeSanitizerArg!");
std::string Sanitizers;
for (int i = 0, n = A->getNumValues(); i != n; ++i) {