diff options
Diffstat (limited to 'clang/lib/Driver/SanitizerArgs.cpp')
| -rw-r--r-- | clang/lib/Driver/SanitizerArgs.cpp | 116 |
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) { |
