1778 lines · cpp
1//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "clang/Driver/SanitizerArgs.h"9#include "clang/Basic/Sanitizers.h"10#include "clang/Driver/Driver.h"11#include "clang/Driver/ToolChain.h"12#include "clang/Options/Options.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/StringSwitch.h"16#include "llvm/Support/Path.h"17#include "llvm/Support/SpecialCaseList.h"18#include "llvm/Support/VirtualFileSystem.h"19#include "llvm/TargetParser/AArch64TargetParser.h"20#include "llvm/TargetParser/RISCVTargetParser.h"21#include "llvm/TargetParser/TargetParser.h"22#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"23#include <memory>24 25using namespace clang;26using namespace clang::driver;27using namespace llvm::opt;28 29static const SanitizerMask NeedsUbsanRt =30 SanitizerKind::Undefined | SanitizerKind::Integer |31 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |32 SanitizerKind::Nullability | SanitizerKind::CFI |33 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |34 SanitizerKind::Vptr;35static const SanitizerMask NeedsUbsanCxxRt =36 SanitizerKind::Vptr | SanitizerKind::CFI;37static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;38static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;39static const SanitizerMask NotAllowedWithExecuteOnly =40 SanitizerKind::Function | SanitizerKind::KCFI;41static const SanitizerMask NeedsUnwindTables =42 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |43 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |44 SanitizerKind::NumericalStability;45static const SanitizerMask SupportsCoverage =46 SanitizerKind::Address | SanitizerKind::HWAddress |47 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |48 SanitizerKind::Type | SanitizerKind::MemtagStack |49 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |50 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |51 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |52 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |53 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |54 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |55 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |56 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |57 SanitizerKind::NumericalStability | SanitizerKind::Vptr |58 SanitizerKind::CFI | SanitizerKind::AllocToken;59static const SanitizerMask RecoverableByDefault =60 SanitizerKind::Undefined | SanitizerKind::Integer |61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |63 SanitizerKind::Vptr;64static const SanitizerMask Unrecoverable = SanitizerKind::Unreachable |65 SanitizerKind::Return |66 SanitizerKind::AllocToken;67static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |68 SanitizerKind::KernelHWAddress |69 SanitizerKind::KCFI;70static const SanitizerMask NeedsLTO = SanitizerKind::CFI;71static const SanitizerMask TrappingSupported =72 SanitizerKind::Undefined | SanitizerKind::Integer |73 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |74 SanitizerKind::LocalBounds | SanitizerKind::CFI |75 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;76static const SanitizerMask MergeDefault =77 SanitizerKind::Undefined | SanitizerKind::Vptr;78static const SanitizerMask TrappingDefault =79 SanitizerKind::CFI | SanitizerKind::LocalBounds;80static const SanitizerMask AnnotateDebugInfoDefault;81static const SanitizerMask CFIClasses =82 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |83 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |84 SanitizerKind::CFIUnrelatedCast;85static const SanitizerMask CompatibleWithMinimalRuntime =86 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |87 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |88 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI |89 SanitizerKind::AllocToken;90 91enum CoverageFeature {92 CoverageFunc = 1 << 0,93 CoverageBB = 1 << 1,94 CoverageEdge = 1 << 2,95 CoverageIndirCall = 1 << 3,96 CoverageTraceBB = 1 << 4, // Deprecated.97 CoverageTraceCmp = 1 << 5,98 CoverageTraceDiv = 1 << 6,99 CoverageTraceGep = 1 << 7,100 Coverage8bitCounters = 1 << 8, // Deprecated.101 CoverageTracePC = 1 << 9,102 CoverageTracePCGuard = 1 << 10,103 CoverageNoPrune = 1 << 11,104 CoverageInline8bitCounters = 1 << 12,105 CoveragePCTable = 1 << 13,106 CoverageStackDepth = 1 << 14,107 CoverageInlineBoolFlag = 1 << 15,108 CoverageTraceLoads = 1 << 16,109 CoverageTraceStores = 1 << 17,110 CoverageControlFlow = 1 << 18,111};112 113enum BinaryMetadataFeature {114 BinaryMetadataCovered = 1 << 0,115 BinaryMetadataAtomics = 1 << 1,116 BinaryMetadataUAR = 1 << 2,117};118 119/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any120/// invalid components. Returns a SanitizerMask.121static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,122 bool DiagnoseErrors);123 124/// Parse a -fsanitize=<sanitizer1>=<value1>... or -fno-sanitize= argument's125/// values, diagnosing any invalid components.126/// Cutoffs are stored in the passed parameter.127static void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,128 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs);129 130/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid131/// components. Returns OR of members of \c CoverageFeature enumeration.132static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,133 bool DiagnoseErrors);134 135/// Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing136/// any invalid values. Returns a mask of excluded overflow patterns.137static int parseOverflowPatternExclusionValues(const Driver &D,138 const llvm::opt::Arg *A,139 bool DiagnoseErrors);140 141/// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid142/// components. Returns OR of members of \c BinaryMetadataFeature enumeration.143static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,144 bool DiagnoseErrors);145 146/// Produce an argument string from ArgList \p Args, which shows how it147/// provides some sanitizer kind from \p Mask. For example, the argument list148/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt149/// would produce "-fsanitize=vptr".150static std::string lastArgumentForMask(const Driver &D,151 const llvm::opt::ArgList &Args,152 SanitizerMask Mask);153 154/// Produce an argument string from argument \p A, which shows how it provides155/// a value in \p Mask. For instance, the argument156/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce157/// "-fsanitize=alignment".158static std::string describeSanitizeArg(const llvm::opt::Arg *A,159 SanitizerMask Mask);160 161/// Produce a string containing comma-separated names of sanitizers in \p162/// Sanitizers set.163static std::string toString(const clang::SanitizerSet &Sanitizers);164 165/// Produce a string containing comma-separated names of sanitizers and166/// sanitizer groups in \p Sanitizers set.167static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers);168 169/// Return true if an execute-only target disallows data access to code170/// sections.171static bool isExecuteOnlyTarget(const llvm::Triple &Triple,172 const llvm::opt::ArgList &Args) {173 if (Triple.isPS5())174 return true;175 return Args.hasFlagNoClaim(options::OPT_mexecute_only,176 options::OPT_mno_execute_only, false);177}178 179static void validateSpecialCaseListFormat(const Driver &D,180 std::vector<std::string> &SCLFiles,181 unsigned MalformedSCLErrorDiagID,182 bool DiagnoseErrors) {183 if (SCLFiles.empty())184 return;185 186 std::string BLError;187 std::unique_ptr<llvm::SpecialCaseList> SCL(188 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));189 if (!SCL && DiagnoseErrors)190 D.Diag(MalformedSCLErrorDiagID) << BLError;191}192 193static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,194 std::vector<std::string> &IgnorelistFiles,195 bool DiagnoseErrors) {196 struct Ignorelist {197 const char *File;198 SanitizerMask Mask;199 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},200 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},201 {"memtag_ignorelist.txt", SanitizerKind::MemTag},202 {"msan_ignorelist.txt", SanitizerKind::Memory},203 {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},204 {"tsan_ignorelist.txt", SanitizerKind::Thread},205 {"tysan_blacklist.txt", SanitizerKind::Type},206 {"dfsan_abilist.txt", SanitizerKind::DataFlow},207 {"cfi_ignorelist.txt", SanitizerKind::CFI},208 {"alloc_token_ignorelist.txt", SanitizerKind::AllocToken},209 {"ubsan_ignorelist.txt",210 SanitizerKind::Undefined | SanitizerKind::Vptr |211 SanitizerKind::Integer | SanitizerKind::Nullability |212 SanitizerKind::FloatDivideByZero}};213 214 for (auto BL : Ignorelists) {215 if (!(Kinds & BL.Mask))216 continue;217 218 clang::SmallString<64> Path(D.ResourceDir);219 llvm::sys::path::append(Path, "share", BL.File);220 if (D.getVFS().exists(Path))221 IgnorelistFiles.push_back(std::string(Path));222 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)223 // If cfi_ignorelist.txt cannot be found in the resource dir, driver224 // should fail.225 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;226 }227 validateSpecialCaseListFormat(228 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,229 DiagnoseErrors);230}231 232/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,233/// diagnosing any invalid file paths and validating special case list format.234static void parseSpecialCaseListArg(const Driver &D,235 const llvm::opt::ArgList &Args,236 std::vector<std::string> &SCLFiles,237 llvm::opt::OptSpecifier SCLOptionID,238 llvm::opt::OptSpecifier NoSCLOptionID,239 unsigned MalformedSCLErrorDiagID,240 bool DiagnoseErrors) {241 for (const auto *Arg : Args) {242 // Match -fsanitize-(coverage-)?(allow|ignore)list.243 if (Arg->getOption().matches(SCLOptionID)) {244 Arg->claim();245 std::string SCLPath = Arg->getValue();246 if (D.getVFS().exists(SCLPath)) {247 SCLFiles.push_back(SCLPath);248 } else if (DiagnoseErrors) {249 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;250 }251 // Match -fno-sanitize-ignorelist.252 } else if (Arg->getOption().matches(NoSCLOptionID)) {253 Arg->claim();254 SCLFiles.clear();255 }256 }257 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,258 DiagnoseErrors);259}260 261/// Sets group bits for every group that has at least one representative already262/// enabled in \p Kinds.263static SanitizerMask setGroupBits(SanitizerMask Kinds) {264#define SANITIZER(NAME, ID)265#define SANITIZER_GROUP(NAME, ID, ALIAS) \266 if (Kinds & SanitizerKind::ID) \267 Kinds |= SanitizerKind::ID##Group;268#include "clang/Basic/Sanitizers.def"269 return Kinds;270}271 272// Computes the sanitizer mask as:273// Default + Arguments (in or out) + AlwaysIn - AlwaysOut274// with arguments parsed from left to right.275static SanitizerMask276parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,277 bool DiagnoseErrors, SanitizerMask Default,278 SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,279 int OptOutID) {280 assert(!(AlwaysIn & AlwaysOut) &&281 "parseSanitizeArgs called with contradictory in/out requirements");282 283 SanitizerMask Output = Default;284 // Keep track of which violations we have already reported, to avoid285 // duplicate error messages.286 SanitizerMask DiagnosedAlwaysInViolations;287 SanitizerMask DiagnosedAlwaysOutViolations;288 for (const auto *Arg : Args) {289 if (Arg->getOption().matches(OptInID)) {290 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);291 // Report error if user explicitly tries to opt-in to an always-out292 // sanitizer.293 if (SanitizerMask KindsToDiagnose =294 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {295 if (DiagnoseErrors) {296 SanitizerSet SetToDiagnose;297 SetToDiagnose.Mask |= KindsToDiagnose;298 D.Diag(diag::err_drv_unsupported_option_argument)299 << Arg->getSpelling() << toStringWithGroups(SetToDiagnose);300 DiagnosedAlwaysOutViolations |= KindsToDiagnose;301 }302 }303 Output |= expandSanitizerGroups(Add);304 Arg->claim();305 } else if (Arg->getOption().matches(OptOutID)) {306 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);307 // Report error if user explicitly tries to opt-out of an always-in308 // sanitizer.309 if (SanitizerMask KindsToDiagnose =310 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {311 if (DiagnoseErrors) {312 SanitizerSet SetToDiagnose;313 SetToDiagnose.Mask |= KindsToDiagnose;314 D.Diag(diag::err_drv_unsupported_option_argument)315 << Arg->getSpelling() << toStringWithGroups(SetToDiagnose);316 DiagnosedAlwaysInViolations |= KindsToDiagnose;317 }318 }319 Output &= ~expandSanitizerGroups(Remove);320 Arg->claim();321 }322 }323 324 Output |= AlwaysIn;325 Output &= ~AlwaysOut;326 327 return Output;328}329 330static SanitizerMask parseSanitizeTrapArgs(const Driver &D,331 const llvm::opt::ArgList &Args,332 bool DiagnoseErrors) {333 SanitizerMask AlwaysTrap; // Empty334 SanitizerMask NeverTrap = ~(setGroupBits(TrappingSupported));335 336 return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,337 NeverTrap, options::OPT_fsanitize_trap_EQ,338 options::OPT_fno_sanitize_trap_EQ);339}340 341static SanitizerMaskCutoffs342parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args,343 bool DiagnoseErrors) {344 SanitizerMaskCutoffs Cutoffs;345 for (const auto *Arg : Args)346 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {347 Arg->claim();348 parseArgCutoffs(D, Arg, DiagnoseErrors, Cutoffs);349 }350 351 return Cutoffs;352}353 354bool SanitizerArgs::needsFuzzerInterceptors() const {355 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();356}357 358bool SanitizerArgs::needsUbsanRt() const {359 // All of these include ubsan.360 if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||361 needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsTysanRt() ||362 needsCfiCrossDsoDiagRt() || (needsScudoRt() && !requiresMinimalRuntime()))363 return false;364 365 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||366 CoverageFeatures;367}368 369bool SanitizerArgs::needsUbsanCXXRt() const {370 // Link UBSAN C++ runtime very selectively, as it's needed in only very371 // specific cases, but forces the program to depend on C++ ABI. UBSAN C++372 // runtime is not included with other sanitizers.373 return static_cast<bool>(Sanitizers.Mask & NeedsUbsanCxxRt &374 ~TrapSanitizers.Mask);375}376 377bool SanitizerArgs::needsCfiCrossDsoRt() const {378 // Diag runtime includes cross dso runtime.379 return !needsCfiCrossDsoDiagRt() && CfiCrossDso && !ImplicitCfiRuntime;380}381 382bool SanitizerArgs::needsCfiCrossDsoDiagRt() const {383 // UBSsan handles CFI diagnostics without cross-DSO suppport.384 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&385 CfiCrossDso && !ImplicitCfiRuntime;386}387 388bool SanitizerArgs::requiresPIE() const { return NeedPIE; }389 390bool SanitizerArgs::needsUnwindTables() const {391 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);392}393 394bool SanitizerArgs::needsLTO() const {395 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);396}397 398SanitizerArgs::SanitizerArgs(const ToolChain &TC,399 const llvm::opt::ArgList &Args,400 bool DiagnoseErrors) {401 SanitizerMask AllRemove; // During the loop below, the accumulated set of402 // sanitizers disabled by the current sanitizer403 // argument or any argument after it.404 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by405 // -fsanitize= flags (directly or via group406 // expansion), some of which may be disabled407 // later. Used to carefully prune408 // unused-argument diagnostics.409 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.410 // Used to deduplicate diagnostics.411 SanitizerMask Kinds;412 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());413 414 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,415 options::OPT_fno_sanitize_cfi_cross_dso, false);416 417 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();418 419 const Driver &D = TC.getDriver();420 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);421 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;422 const llvm::Triple &Triple = TC.getTriple();423 424 MinimalRuntime =425 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,426 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);427 HandlerPreserveAllRegs =428 Args.hasFlag(options::OPT_fsanitize_handler_preserve_all_regs,429 options::OPT_fno_sanitize_handler_preserve_all_regs,430 HandlerPreserveAllRegs) &&431 MinimalRuntime && (Triple.isAArch64() || Triple.isX86_64());432 433 // The object size sanitizer should not be enabled at -O0.434 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);435 bool RemoveObjectSizeAtO0 =436 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);437 438 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {439 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {440 Arg->claim();441 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);442 443 if (RemoveObjectSizeAtO0) {444 AllRemove |= SanitizerKind::ObjectSize;445 446 // The user explicitly enabled the object size sanitizer. Warn447 // that this does nothing at -O0.448 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)449 D.Diag(diag::warn_drv_object_size_disabled_O0)450 << Arg->getAsString(Args);451 }452 453 AllAddedKinds |= expandSanitizerGroups(Add);454 455 // Avoid diagnosing any sanitizer which is disabled later.456 Add &= ~AllRemove;457 // At this point we have not expanded groups, so any unsupported458 // sanitizers in Add are those which have been explicitly enabled.459 // Diagnose them.460 if (SanitizerMask KindsToDiagnose =461 Add & InvalidTrappingKinds & ~DiagnosedKinds) {462 if (DiagnoseErrors) {463 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);464 D.Diag(diag::err_drv_argument_not_allowed_with)465 << Desc << "-fsanitize-trap=undefined";466 }467 DiagnosedKinds |= KindsToDiagnose;468 }469 Add &= ~InvalidTrappingKinds;470 471 if (MinimalRuntime) {472 if (SanitizerMask KindsToDiagnose =473 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {474 if (DiagnoseErrors) {475 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);476 D.Diag(diag::err_drv_argument_not_allowed_with)477 << Desc << "-fsanitize-minimal-runtime";478 }479 DiagnosedKinds |= KindsToDiagnose;480 }481 Add &= ~NotAllowedWithMinimalRuntime;482 }483 484 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {485 StringRef CM = A->getValue();486 if (CM != "small" &&487 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {488 if (DiagnoseErrors)489 D.Diag(diag::err_drv_argument_only_allowed_with)490 << "-fsanitize=function"491 << "-mcmodel=small";492 Add &= ~SanitizerKind::Function;493 DiagnosedKinds |= SanitizerKind::Function;494 }495 }496 // -fsanitize=function and -fsanitize=kcfi instrument indirect function497 // calls to load a type hash before the function label. Therefore, an498 // execute-only target doesn't support the function and kcfi sanitizers.499 if (isExecuteOnlyTarget(Triple, Args)) {500 if (SanitizerMask KindsToDiagnose =501 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {502 if (DiagnoseErrors) {503 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);504 llvm::opt::Arg *A = Args.getLastArgNoClaim(505 options::OPT_mexecute_only, options::OPT_mno_execute_only);506 if (A && A->getOption().matches(options::OPT_mexecute_only))507 D.Diag(diag::err_drv_argument_not_allowed_with)508 << Desc << A->getAsString(Args);509 else510 D.Diag(diag::err_drv_unsupported_opt_for_target)511 << Desc << Triple.str();512 }513 DiagnosedKinds |= KindsToDiagnose;514 }515 Add &= ~NotAllowedWithExecuteOnly;516 }517 518 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.519 // There are currently two problems:520 // - Virtual function call checks need to pass a pointer to the function521 // address to llvm.type.test and a pointer to the address point to the522 // diagnostic function. Currently we pass the same pointer to both523 // places.524 // - Non-virtual function call checks may need to check multiple type525 // identifiers.526 // Fixing both of those may require changes to the cross-DSO CFI527 // interface.528 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {529 if (DiagnoseErrors)530 D.Diag(diag::err_drv_argument_not_allowed_with)531 << "-fsanitize=cfi-mfcall"532 << "-fsanitize-cfi-cross-dso";533 Add &= ~SanitizerKind::CFIMFCall;534 DiagnosedKinds |= SanitizerKind::CFIMFCall;535 }536 537 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {538 if (DiagnoseErrors) {539 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);540 D.Diag(diag::err_drv_unsupported_opt_for_target)541 << Desc << TC.getTriple().str();542 }543 DiagnosedKinds |= KindsToDiagnose;544 }545 Add &= Supported;546 547 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups548 // so we don't error out if -fno-rtti and -fsanitize=undefined were549 // passed.550 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {551 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {552 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&553 "RTTI disabled without -fno-rtti option?");554 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but555 // the vptr sanitizer requires RTTI, so this is a user error.556 if (DiagnoseErrors)557 D.Diag(diag::err_drv_argument_not_allowed_with)558 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);559 } else {560 // The vptr sanitizer requires RTTI, but RTTI is disabled (by561 // default). Warn that the vptr sanitizer is being disabled.562 if (DiagnoseErrors)563 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);564 }565 566 // Take out the Vptr sanitizer from the enabled sanitizers567 AllRemove |= SanitizerKind::Vptr;568 }569 570 Add = expandSanitizerGroups(Add);571 // Group expansion may have enabled a sanitizer which is disabled later.572 Add &= ~AllRemove;573 // Silently discard any unsupported sanitizers implicitly enabled through574 // group expansion.575 Add &= ~InvalidTrappingKinds;576 if (MinimalRuntime) {577 Add &= ~NotAllowedWithMinimalRuntime;578 }579 // NotAllowedWithExecuteOnly is silently discarded on an execute-only580 // target if implicitly enabled through group expansion.581 if (isExecuteOnlyTarget(Triple, Args))582 Add &= ~NotAllowedWithExecuteOnly;583 if (CfiCrossDso)584 Add &= ~SanitizerKind::CFIMFCall;585 // -fsanitize=undefined does not expand to signed-integer-overflow in586 // -fwrapv (implied by -fno-strict-overflow) mode.587 if (Add & SanitizerKind::UndefinedGroup) {588 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,589 options::OPT_fstrict_overflow, false);590 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))591 Add &= ~SanitizerKind::SignedIntegerOverflow;592 if (Args.hasFlagNoClaim(options::OPT_fwrapv_pointer,593 options::OPT_fno_wrapv_pointer, S))594 Add &= ~SanitizerKind::PointerOverflow;595 }596 Add &= Supported;597 598 if (Add & SanitizerKind::Fuzzer)599 Add |= SanitizerKind::FuzzerNoLink;600 601 // Enable coverage if the fuzzing flag is set.602 if (Add & SanitizerKind::FuzzerNoLink) {603 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |604 CoverageTraceCmp | CoveragePCTable;605 // Due to TLS differences, stack depth tracking is only enabled on Linux606 if (TC.getTriple().isOSLinux())607 CoverageFeatures |= CoverageStackDepth;608 }609 610 Kinds |= Add;611 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {612 Arg->claim();613 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);614 AllRemove |= expandSanitizerGroups(Remove);615 }616 }617 618 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {619 std::make_pair(SanitizerKind::Address,620 SanitizerKind::Thread | SanitizerKind::Memory),621 std::make_pair(SanitizerKind::Type,622 SanitizerKind::Address | SanitizerKind::KernelAddress |623 SanitizerKind::Memory | SanitizerKind::Leak |624 SanitizerKind::Thread | SanitizerKind::KernelAddress),625 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),626 std::make_pair(SanitizerKind::Leak,627 SanitizerKind::Thread | SanitizerKind::Memory),628 std::make_pair(SanitizerKind::KernelAddress,629 SanitizerKind::Address | SanitizerKind::Leak |630 SanitizerKind::Thread | SanitizerKind::Memory),631 std::make_pair(SanitizerKind::HWAddress,632 SanitizerKind::Address | SanitizerKind::Thread |633 SanitizerKind::Memory | SanitizerKind::KernelAddress),634 std::make_pair(SanitizerKind::Scudo,635 SanitizerKind::Address | SanitizerKind::HWAddress |636 SanitizerKind::Leak | SanitizerKind::Thread |637 SanitizerKind::Memory | SanitizerKind::KernelAddress),638 std::make_pair(SanitizerKind::SafeStack,639 (TC.getTriple().isOSFuchsia() ? SanitizerMask()640 : SanitizerKind::Leak) |641 SanitizerKind::Address | SanitizerKind::HWAddress |642 SanitizerKind::Thread | SanitizerKind::Memory |643 SanitizerKind::KernelAddress),644 std::make_pair(SanitizerKind::KernelHWAddress,645 SanitizerKind::Address | SanitizerKind::HWAddress |646 SanitizerKind::Leak | SanitizerKind::Thread |647 SanitizerKind::Memory | SanitizerKind::KernelAddress |648 SanitizerKind::SafeStack),649 std::make_pair(SanitizerKind::KernelMemory,650 SanitizerKind::Address | SanitizerKind::HWAddress |651 SanitizerKind::Leak | SanitizerKind::Thread |652 SanitizerKind::Memory | SanitizerKind::KernelAddress |653 SanitizerKind::Scudo | SanitizerKind::SafeStack),654 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |655 SanitizerKind::KernelAddress |656 SanitizerKind::HWAddress |657 SanitizerKind::KernelHWAddress),658 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),659 std::make_pair(SanitizerKind::Realtime,660 SanitizerKind::Address | SanitizerKind::Thread |661 SanitizerKind::Undefined | SanitizerKind::Memory),662 std::make_pair(SanitizerKind::AllocToken,663 SanitizerKind::Address | SanitizerKind::HWAddress |664 SanitizerKind::KernelAddress |665 SanitizerKind::KernelHWAddress |666 SanitizerKind::Memory)};667 668 // Enable toolchain specific default sanitizers if not explicitly disabled.669 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;670 671 // Disable default sanitizers that are incompatible with explicitly requested672 // ones.673 for (auto G : IncompatibleGroups) {674 SanitizerMask Group = G.first;675 if ((Default & Group) && (Kinds & G.second))676 Default &= ~Group;677 }678 679 Kinds |= Default;680 681 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI682 // is disabled.683 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {684 Kinds &= ~SanitizerKind::Vptr;685 }686 687 // Check that LTO is enabled if we need it.688 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {689 D.Diag(diag::err_drv_argument_only_allowed_with)690 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";691 }692 693 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&694 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&695 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {696 D.Diag(diag::err_drv_argument_only_allowed_with)697 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)698 << "-ffixed-x18";699 }700 701 // Report error if there are non-trapping sanitizers that require702 // c++abi-specific parts of UBSan runtime, and they are not provided by the703 // toolchain. We don't have a good way to check the latter, so we just704 // check if the toolchan supports vptr.705 if (~Supported & SanitizerKind::Vptr) {706 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;707 // The runtime library supports the Microsoft C++ ABI, but only well enough708 // for CFI. FIXME: Remove this once we support vptr on Windows.709 if (TC.getTriple().isOSWindows())710 KindsToDiagnose &= ~SanitizerKind::CFI;711 if (KindsToDiagnose) {712 SanitizerSet S;713 S.Mask = KindsToDiagnose;714 if (DiagnoseErrors)715 D.Diag(diag::err_drv_unsupported_opt_for_target)716 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();717 Kinds &= ~KindsToDiagnose;718 }719 }720 721 // Warn about incompatible groups of sanitizers.722 for (auto G : IncompatibleGroups) {723 SanitizerMask Group = G.first;724 if (Kinds & Group) {725 if (SanitizerMask Incompatible = Kinds & G.second) {726 if (DiagnoseErrors)727 D.Diag(clang::diag::err_drv_argument_not_allowed_with)728 << lastArgumentForMask(D, Args, Group)729 << lastArgumentForMask(D, Args, Incompatible);730 Kinds &= ~Incompatible;731 }732 }733 }734 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of735 // -fsanitize=address. Perhaps it should print an error, or perhaps736 // -f(-no)sanitize=leak should change whether leak detection is enabled by737 // default in ASan?738 739 // Parse -f(no-)?sanitize-recover flags.740 SanitizerMask RecoverableKinds = parseSanitizeArgs(741 D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,742 Unrecoverable, options::OPT_fsanitize_recover_EQ,743 options::OPT_fno_sanitize_recover_EQ);744 RecoverableKinds &= Kinds;745 746 TrappingKinds &= Kinds;747 RecoverableKinds &= ~TrappingKinds;748 749 // Parse -f(no-)?sanitize-nonmerged-handlers flags750 SanitizerMask MergeKinds =751 parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {}, {},752 options::OPT_fsanitize_merge_handlers_EQ,753 options::OPT_fno_sanitize_merge_handlers_EQ);754 MergeKinds &= Kinds;755 756 // Parse -fno-fsanitize-skip-hot-cutoff flags757 SkipHotCutoffs = parseSanitizeSkipHotCutoffArgs(D, Args, DiagnoseErrors);758 759 // Parse -f(no-)?sanitize-annotate-debug-info flags760 SanitizerMask AnnotateDebugInfoKinds =761 parseSanitizeArgs(D, Args, DiagnoseErrors, AnnotateDebugInfoDefault, {},762 {}, options::OPT_fsanitize_annotate_debug_info_EQ,763 options::OPT_fno_sanitize_annotate_debug_info_EQ);764 AnnotateDebugInfoKinds &= Kinds;765 766 // Setup ignorelist files.767 // Add default ignorelist from resource directory for activated sanitizers,768 // and validate special case lists format.769 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))770 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);771 772 // Parse -f(no-)?sanitize-ignorelist options.773 // This also validates special case lists format.774 parseSpecialCaseListArg(775 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,776 options::OPT_fno_sanitize_ignorelist,777 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);778 779 // Verify that -fsanitize-coverage-stack-depth-callback-min is >= 0.780 if (Arg *A = Args.getLastArg(781 options::OPT_fsanitize_coverage_stack_depth_callback_min_EQ)) {782 StringRef S = A->getValue();783 if (S.getAsInteger(0, CoverageStackDepthCallbackMin) ||784 CoverageStackDepthCallbackMin < 0) {785 if (DiagnoseErrors)786 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;787 }788 }789 790 // Parse -f[no-]sanitize-memory-track-origins[=level] options.791 if (AllAddedKinds & SanitizerKind::Memory) {792 if (Arg *A =793 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,794 options::OPT_fno_sanitize_memory_track_origins)) {795 if (!A->getOption().matches(796 options::OPT_fno_sanitize_memory_track_origins)) {797 StringRef S = A->getValue();798 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||799 MsanTrackOrigins > 2) {800 if (DiagnoseErrors)801 D.Diag(clang::diag::err_drv_invalid_value)802 << A->getAsString(Args) << S;803 }804 }805 }806 MsanUseAfterDtor = Args.hasFlag(807 options::OPT_fsanitize_memory_use_after_dtor,808 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);809 MsanParamRetval = Args.hasFlag(810 options::OPT_fsanitize_memory_param_retval,811 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);812 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {813 MsanUseAfterDtor = false;814 MsanParamRetval = Args.hasFlag(815 options::OPT_fsanitize_memory_param_retval,816 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);817 } else {818 MsanUseAfterDtor = false;819 MsanParamRetval = false;820 }821 822 if (AllAddedKinds & SanitizerKind::MemTag) {823 StringRef S =824 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");825 if (S == "async" || S == "sync") {826 MemtagMode = S.str();827 } else {828 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)829 << "-fsanitize-memtag-mode=" << S << "{async, sync}";830 MemtagMode = "sync";831 }832 }833 834 if (AllAddedKinds & SanitizerKind::Thread) {835 TsanMemoryAccess = Args.hasFlag(836 options::OPT_fsanitize_thread_memory_access,837 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);838 TsanFuncEntryExit = Args.hasFlag(839 options::OPT_fsanitize_thread_func_entry_exit,840 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);841 TsanAtomics =842 Args.hasFlag(options::OPT_fsanitize_thread_atomics,843 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);844 }845 846 if (AllAddedKinds & SanitizerKind::CFI) {847 // Without PIE, external function address may resolve to a PLT record, which848 // can not be verified by the target module.849 NeedPIE |= CfiCrossDso;850 CfiICallGeneralizePointers =851 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);852 853 CfiICallNormalizeIntegers =854 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);855 856 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)857 D.Diag(diag::err_drv_argument_not_allowed_with)858 << "-fsanitize-cfi-cross-dso"859 << "-fsanitize-cfi-icall-generalize-pointers";860 861 CfiCanonicalJumpTables =862 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,863 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);864 }865 866 if (AllAddedKinds & SanitizerKind::KCFI) {867 CfiICallGeneralizePointers =868 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);869 CfiICallNormalizeIntegers =870 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);871 872 KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);873 874 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)875 D.Diag(diag::err_drv_argument_not_allowed_with)876 << "-fsanitize=kcfi"877 << lastArgumentForMask(D, Args, SanitizerKind::CFI);878 }879 880 Stats = Args.hasFlag(options::OPT_fsanitize_stats,881 options::OPT_fno_sanitize_stats, false);882 883 if (MinimalRuntime) {884 SanitizerMask IncompatibleMask =885 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);886 if (IncompatibleMask && DiagnoseErrors)887 D.Diag(clang::diag::err_drv_argument_not_allowed_with)888 << "-fsanitize-minimal-runtime"889 << lastArgumentForMask(D, Args, IncompatibleMask);890 }891 892 for (const auto *Arg : Args.filtered(893 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {894 Arg->claim();895 OverflowPatternExclusions |=896 parseOverflowPatternExclusionValues(D, Arg, DiagnoseErrors);897 }898 899 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the900 // enabled sanitizers.901 for (const auto *Arg : Args) {902 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {903 int LegacySanitizeCoverage;904 if (Arg->getNumValues() == 1 &&905 !StringRef(Arg->getValue(0))906 .getAsInteger(0, LegacySanitizeCoverage)) {907 CoverageFeatures = 0;908 Arg->claim();909 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {910 D.Diag(diag::warn_drv_deprecated_arg)911 << Arg->getAsString(Args) << /*hasReplacement=*/true912 << "-fsanitize-coverage=trace-pc-guard";913 }914 continue;915 }916 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);917 918 // Disable coverage and not claim the flags if there is at least one919 // non-supporting sanitizer.920 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {921 Arg->claim();922 } else {923 CoverageFeatures = 0;924 }925 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {926 Arg->claim();927 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);928 }929 }930 // Choose at most one coverage type: function, bb, or edge.931 if (DiagnoseErrors) {932 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))933 D.Diag(clang::diag::err_drv_argument_not_allowed_with)934 << "-fsanitize-coverage=func"935 << "-fsanitize-coverage=bb";936 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))937 D.Diag(clang::diag::err_drv_argument_not_allowed_with)938 << "-fsanitize-coverage=func"939 << "-fsanitize-coverage=edge";940 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))941 D.Diag(clang::diag::err_drv_argument_not_allowed_with)942 << "-fsanitize-coverage=bb"943 << "-fsanitize-coverage=edge";944 // Basic block tracing and 8-bit counters require some type of coverage945 // enabled.946 if (CoverageFeatures & CoverageTraceBB)947 D.Diag(clang::diag::warn_drv_deprecated_arg)948 << "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true949 << "-fsanitize-coverage=trace-pc-guard";950 if (CoverageFeatures & Coverage8bitCounters)951 D.Diag(clang::diag::warn_drv_deprecated_arg)952 << "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true953 << "-fsanitize-coverage=trace-pc-guard";954 }955 956 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;957 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |958 CoverageInline8bitCounters | CoverageTraceLoads |959 CoverageTraceStores | CoverageInlineBoolFlag |960 CoverageControlFlow;961 if ((CoverageFeatures & InsertionPointTypes) &&962 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {963 D.Diag(clang::diag::warn_drv_deprecated_arg)964 << "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true965 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["966 "control-flow]";967 }968 969 // trace-pc w/o func/bb/edge implies edge.970 if (!(CoverageFeatures & InsertionPointTypes)) {971 if (CoverageFeatures &972 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |973 CoverageInlineBoolFlag | CoverageControlFlow))974 CoverageFeatures |= CoverageEdge;975 976 if (CoverageFeatures & CoverageStackDepth)977 CoverageFeatures |= CoverageFunc;978 }979 980 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.981 // This also validates special case lists format.982 // Here, OptSpecifier() acts as a never-matching command-line argument.983 // So, there is no way to clear coverage lists but you can append to them.984 if (CoverageFeatures) {985 parseSpecialCaseListArg(986 D, Args, CoverageAllowlistFiles,987 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),988 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,989 DiagnoseErrors);990 parseSpecialCaseListArg(991 D, Args, CoverageIgnorelistFiles,992 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),993 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,994 DiagnoseErrors);995 }996 997 // Parse -f(no-)?sanitize-metadata.998 for (const auto *Arg :999 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,1000 options::OPT_fno_experimental_sanitize_metadata_EQ)) {1001 if (Arg->getOption().matches(1002 options::OPT_fexperimental_sanitize_metadata_EQ)) {1003 Arg->claim();1004 BinaryMetadataFeatures |=1005 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);1006 } else {1007 Arg->claim();1008 BinaryMetadataFeatures &=1009 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);1010 }1011 }1012 1013 // Parse -fsanitize-metadata-ignorelist option if enabled.1014 if (BinaryMetadataFeatures) {1015 parseSpecialCaseListArg(1016 D, Args, BinaryMetadataIgnorelistFiles,1017 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,1018 OptSpecifier(), // Cannot clear ignore list, only append.1019 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,1020 DiagnoseErrors);1021 }1022 1023 SharedRuntime = Args.hasFlag(1024 options::OPT_shared_libsan, options::OPT_static_libsan,1025 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||1026 TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());1027 if (!SharedRuntime && TC.getTriple().isOSWindows()) {1028 Arg *A =1029 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);1030 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)1031 << A->getSpelling() << TC.getTriple().str();1032 }1033 1034 ImplicitCfiRuntime = TC.getTriple().isAndroid();1035 1036 if (AllAddedKinds & SanitizerKind::Address) {1037 NeedPIE |= TC.getTriple().isOSFuchsia();1038 if (Arg *A =1039 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {1040 StringRef S = A->getValue();1041 // Legal values are 0 and 1, 2, but in future we may add more levels.1042 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||1043 AsanFieldPadding > 2) &&1044 DiagnoseErrors) {1045 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;1046 }1047 }1048 1049 if (Arg *WindowsDebugRTArg =1050 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,1051 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,1052 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {1053 switch (WindowsDebugRTArg->getOption().getID()) {1054 case options::OPT__SLASH_MTd:1055 case options::OPT__SLASH_MDd:1056 case options::OPT__SLASH_LDd:1057 if (DiagnoseErrors) {1058 D.Diag(clang::diag::err_drv_argument_not_allowed_with)1059 << WindowsDebugRTArg->getAsString(Args)1060 << lastArgumentForMask(D, Args, SanitizerKind::Address);1061 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);1062 }1063 }1064 }1065 1066 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,1067 options::OPT_fno_sanitize_stable_abi, false);1068 1069 AsanPoisonCustomArrayCookie = Args.hasFlag(1070 options::OPT_fsanitize_address_poison_custom_array_cookie,1071 options::OPT_fno_sanitize_address_poison_custom_array_cookie,1072 AsanPoisonCustomArrayCookie);1073 1074 AsanOutlineInstrumentation =1075 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,1076 options::OPT_fno_sanitize_address_outline_instrumentation,1077 AsanOutlineInstrumentation);1078 1079 AsanGlobalsDeadStripping = Args.hasFlag(1080 options::OPT_fsanitize_address_globals_dead_stripping,1081 options::OPT_fno_sanitize_address_globals_dead_stripping, true);1082 1083 // Enable ODR indicators which allow better handling of mixed instrumented1084 // and uninstrumented globals. Disable them for Windows where weak odr1085 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker1086 // errors in the absence of -lldmingw.1087 AsanUseOdrIndicator =1088 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,1089 options::OPT_fno_sanitize_address_use_odr_indicator,1090 !TC.getTriple().isOSWindows());1091 1092 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {1093 AsanInvalidPointerCmp = true;1094 }1095 1096 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {1097 AsanInvalidPointerSub = true;1098 }1099 1100 if (TC.getTriple().isOSDarwin() &&1101 (Args.hasArg(options::OPT_mkernel) ||1102 Args.hasArg(options::OPT_fapple_kext))) {1103 AsanDtorKind = llvm::AsanDtorKind::None;1104 }1105 1106 if (const auto *Arg =1107 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {1108 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());1109 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {1110 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)1111 << Arg->getSpelling() << Arg->getValue();1112 }1113 AsanDtorKind = parsedAsanDtorKind;1114 }1115 1116 if (const auto *Arg = Args.getLastArg(1117 options::OPT_sanitize_address_use_after_return_EQ)) {1118 auto parsedAsanUseAfterReturn =1119 AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());1120 if (parsedAsanUseAfterReturn ==1121 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&1122 DiagnoseErrors) {1123 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)1124 << Arg->getSpelling() << Arg->getValue();1125 }1126 AsanUseAfterReturn = parsedAsanUseAfterReturn;1127 }1128 1129 } else {1130 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.1131 SanitizerMask DetectInvalidPointerPairs =1132 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;1133 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&1134 DiagnoseErrors) {1135 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)1136 << lastArgumentForMask(D, Args,1137 SanitizerKind::PointerCompare |1138 SanitizerKind::PointerSubtract)1139 << "-fsanitize=address";1140 }1141 }1142 1143 if (AllAddedKinds & (SanitizerKind::Address | SanitizerKind::KernelAddress)) {1144 AsanUseAfterScope = Args.hasFlag(1145 options::OPT_fsanitize_address_use_after_scope,1146 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);1147 } else {1148 AsanUseAfterScope = false;1149 }1150 1151 if (AllAddedKinds & SanitizerKind::HWAddress) {1152 if (Arg *HwasanAbiArg =1153 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {1154 HwasanAbi = HwasanAbiArg->getValue();1155 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&1156 DiagnoseErrors)1157 D.Diag(clang::diag::err_drv_invalid_value)1158 << HwasanAbiArg->getAsString(Args) << HwasanAbi;1159 } else {1160 HwasanAbi = "interceptor";1161 }1162 if (TC.getTriple().getArch() == llvm::Triple::x86_64)1163 HwasanUseAliases = Args.hasFlag(1164 options::OPT_fsanitize_hwaddress_experimental_aliasing,1165 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,1166 HwasanUseAliases);1167 }1168 1169 if (AllAddedKinds & SanitizerKind::SafeStack) {1170 // SafeStack runtime is built into the system on Android and Fuchsia.1171 SafeStackRuntime =1172 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();1173 }1174 1175 if (AllAddedKinds & SanitizerKind::AllocToken) {1176 AllocTokenFastABI = Args.hasFlag(1177 options::OPT_fsanitize_alloc_token_fast_abi,1178 options::OPT_fno_sanitize_alloc_token_fast_abi, AllocTokenFastABI);1179 AllocTokenExtended = Args.hasFlag(1180 options::OPT_fsanitize_alloc_token_extended,1181 options::OPT_fno_sanitize_alloc_token_extended, AllocTokenExtended);1182 }1183 1184 if (AllAddedKinds & SanitizerKind::Type) {1185 TysanOutlineInstrumentation =1186 Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,1187 options::OPT_fno_sanitize_type_outline_instrumentation,1188 TysanOutlineInstrumentation);1189 }1190 1191 LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,1192 options::OPT_fno_sanitize_link_runtime,1193 !Args.hasArg(options::OPT_r));1194 1195 // Parse -link-cxx-sanitizer flag.1196 LinkCXXRuntimes = D.CCCIsCXX();1197 LinkCXXRuntimes =1198 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,1199 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);1200 1201 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,1202 options::OPT_fmemory_profile_EQ,1203 options::OPT_fno_memory_profile, false);1204 1205 // Finally, initialize the set of available and recoverable sanitizers.1206 Sanitizers.Mask |= Kinds;1207 RecoverableSanitizers.Mask |= RecoverableKinds;1208 TrapSanitizers.Mask |= TrappingKinds;1209 assert(!(RecoverableKinds & TrappingKinds) &&1210 "Overlap between recoverable and trapping sanitizers");1211 1212 MergeHandlers.Mask |= MergeKinds;1213 1214 AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;1215 1216 // Zero out SkipHotCutoffs for unused sanitizers1217 SkipHotCutoffs.clear(~Sanitizers.Mask);1218}1219 1220static std::string toString(const clang::SanitizerSet &Sanitizers) {1221 std::string Res;1222#define SANITIZER(NAME, ID) \1223 if (Sanitizers.has(SanitizerKind::ID)) { \1224 if (!Res.empty()) \1225 Res += ","; \1226 Res += NAME; \1227 }1228#include "clang/Basic/Sanitizers.def"1229 return Res;1230}1231 1232static std::string toString(const clang::SanitizerMaskCutoffs &Cutoffs) {1233 llvm::SmallVector<std::string, 4> Res;1234 serializeSanitizerMaskCutoffs(Cutoffs, Res);1235 return llvm::join(Res, ",");1236}1237 1238static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers) {1239 std::string Res;1240#define SANITIZER(NAME, ID) \1241 if (Sanitizers.has(SanitizerKind::ID)) { \1242 if (!Res.empty()) \1243 Res += ","; \1244 Res += NAME; \1245 }1246#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID##Group)1247#include "clang/Basic/Sanitizers.def"1248 return Res;1249}1250 1251static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,1252 llvm::opt::ArgStringList &CmdArgs,1253 const char *SCLOptFlag,1254 const std::vector<std::string> &SCLFiles) {1255 for (const auto &SCLPath : SCLFiles) {1256 SmallString<64> SCLOpt(SCLOptFlag);1257 SCLOpt += SCLPath;1258 CmdArgs.push_back(Args.MakeArgString(SCLOpt));1259 }1260}1261 1262static void addIncludeLinkerOption(const ToolChain &TC,1263 const llvm::opt::ArgList &Args,1264 llvm::opt::ArgStringList &CmdArgs,1265 StringRef SymbolName) {1266 SmallString<64> LinkerOptionFlag;1267 LinkerOptionFlag = "--linker-option=/include:";1268 if (TC.getTriple().getArch() == llvm::Triple::x86) {1269 // Win32 mangles C function names with a '_' prefix.1270 LinkerOptionFlag += '_';1271 }1272 LinkerOptionFlag += SymbolName;1273 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));1274}1275 1276static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {1277 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;1278 ++Start) {1279 auto It = std::find(Start, End, StringRef("+mte"));1280 if (It == End)1281 break;1282 if (It > Start && *std::prev(It) == StringRef("-target-feature"))1283 return true;1284 Start = It;1285 }1286 return false;1287}1288 1289void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,1290 llvm::opt::ArgStringList &CmdArgs,1291 types::ID InputType) const {1292 // NVPTX doesn't currently support sanitizers. Bailing out here means1293 // that e.g. -fsanitize=address applies only to host code, which is what we1294 // want for now.1295 if (TC.getTriple().isNVPTX())1296 return;1297 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.1298 bool GPUSanitize = false;1299 if (TC.getTriple().isAMDGPU()) {1300 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,1301 true))1302 return;1303 GPUSanitize = true;1304 }1305 1306 // Translate available CoverageFeatures to corresponding clang-cc1 flags.1307 // Do it even if Sanitizers.empty() since some forms of coverage don't require1308 // sanitizers.1309 std::pair<int, const char *> CoverageFlags[] = {1310 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),1311 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),1312 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),1313 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),1314 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),1315 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),1316 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),1317 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),1318 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),1319 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),1320 std::make_pair(CoverageTracePCGuard,1321 "-fsanitize-coverage-trace-pc-guard"),1322 std::make_pair(CoverageInline8bitCounters,1323 "-fsanitize-coverage-inline-8bit-counters"),1324 std::make_pair(CoverageInlineBoolFlag,1325 "-fsanitize-coverage-inline-bool-flag"),1326 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),1327 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),1328 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),1329 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),1330 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),1331 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};1332 for (auto F : CoverageFlags) {1333 if (CoverageFeatures & F.first)1334 CmdArgs.push_back(F.second);1335 }1336 addSpecialCaseListOpt(1337 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);1338 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",1339 CoverageIgnorelistFiles);1340 1341 if (CoverageStackDepthCallbackMin)1342 CmdArgs.push_back(1343 Args.MakeArgString("-fsanitize-coverage-stack-depth-callback-min=" +1344 Twine(CoverageStackDepthCallbackMin)));1345 1346 if (!GPUSanitize) {1347 // Translate available BinaryMetadataFeatures to corresponding clang-cc11348 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.1349 const std::pair<int, std::string> BinaryMetadataFlags[] = {1350 std::make_pair(BinaryMetadataCovered, "covered"),1351 std::make_pair(BinaryMetadataAtomics, "atomics"),1352 std::make_pair(BinaryMetadataUAR, "uar")};1353 for (const auto &F : BinaryMetadataFlags) {1354 if (BinaryMetadataFeatures & F.first)1355 CmdArgs.push_back(1356 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));1357 }1358 addSpecialCaseListOpt(Args, CmdArgs,1359 "-fexperimental-sanitize-metadata-ignorelist=",1360 BinaryMetadataIgnorelistFiles);1361 }1362 1363 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&1364 Args.hasFlag(options::OPT_frtlib_defaultlib,1365 options::OPT_fno_rtlib_defaultlib, true)) {1366 // Instruct the code generator to embed linker directives in the object file1367 // that cause the required runtime libraries to be linked.1368 CmdArgs.push_back(1369 Args.MakeArgString("--dependent-lib=" +1370 TC.getCompilerRTBasename(Args, "ubsan_standalone")));1371 if (types::isCXX(InputType))1372 CmdArgs.push_back(Args.MakeArgString(1373 "--dependent-lib=" +1374 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));1375 }1376 if (TC.getTriple().isOSWindows() && needsStatsRt() &&1377 Args.hasFlag(options::OPT_frtlib_defaultlib,1378 options::OPT_fno_rtlib_defaultlib, true)) {1379 CmdArgs.push_back(Args.MakeArgString(1380 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));1381 1382 // The main executable must export the stats runtime.1383 // FIXME: Only exporting from the main executable (e.g. based on whether the1384 // translation unit defines main()) would save a little space, but having1385 // multiple copies of the runtime shouldn't hurt.1386 CmdArgs.push_back(Args.MakeArgString(1387 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));1388 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");1389 }1390 1391 if (Sanitizers.empty())1392 return;1393 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));1394 1395 if (!RecoverableSanitizers.empty())1396 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +1397 toString(RecoverableSanitizers)));1398 1399 if (!TrapSanitizers.empty())1400 CmdArgs.push_back(1401 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));1402 1403 if (!MergeHandlers.empty())1404 CmdArgs.push_back(1405 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));1406 1407 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);1408 if (!SkipHotCutoffsStr.empty())1409 CmdArgs.push_back(1410 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));1411 1412 if (!AnnotateDebugInfo.empty())1413 CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +1414 toString(AnnotateDebugInfo)));1415 1416 Args.AddLastArg(CmdArgs, options::OPT_fsanitize_debug_trap_reasons_EQ);1417 1418 addSpecialCaseListOpt(Args, CmdArgs,1419 "-fsanitize-ignorelist=", UserIgnorelistFiles);1420 addSpecialCaseListOpt(Args, CmdArgs,1421 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);1422 1423 if (OverflowPatternExclusions)1424 Args.AddAllArgs(1425 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);1426 1427 if (MsanTrackOrigins)1428 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +1429 Twine(MsanTrackOrigins)));1430 1431 if (MsanUseAfterDtor)1432 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");1433 1434 if (!MsanParamRetval)1435 CmdArgs.push_back("-fno-sanitize-memory-param-retval");1436 1437 // FIXME: Pass these parameters as function attributes, not as -llvm flags.1438 if (!TsanMemoryAccess) {1439 CmdArgs.push_back("-mllvm");1440 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");1441 CmdArgs.push_back("-mllvm");1442 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");1443 }1444 if (!TsanFuncEntryExit) {1445 CmdArgs.push_back("-mllvm");1446 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");1447 }1448 if (!TsanAtomics) {1449 CmdArgs.push_back("-mllvm");1450 CmdArgs.push_back("-tsan-instrument-atomics=0");1451 }1452 1453 if (HwasanUseAliases) {1454 CmdArgs.push_back("-mllvm");1455 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");1456 }1457 1458 if (CfiCrossDso)1459 CmdArgs.push_back("-fsanitize-cfi-cross-dso");1460 1461 if (CfiICallGeneralizePointers)1462 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");1463 1464 if (CfiICallNormalizeIntegers)1465 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");1466 1467 if (KcfiArity) {1468 if (!TC.getTriple().isOSLinux() || !TC.getTriple().isArch64Bit()) {1469 TC.getDriver().Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)1470 << TC.getTriple().str();1471 }1472 CmdArgs.push_back("-fsanitize-kcfi-arity");1473 }1474 1475 if (CfiCanonicalJumpTables)1476 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");1477 1478 if (Stats)1479 CmdArgs.push_back("-fsanitize-stats");1480 1481 if (MinimalRuntime)1482 CmdArgs.push_back("-fsanitize-minimal-runtime");1483 1484 if (HandlerPreserveAllRegs)1485 CmdArgs.push_back("-fsanitize-handler-preserve-all-regs");1486 1487 if (AsanFieldPadding)1488 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +1489 Twine(AsanFieldPadding)));1490 1491 if (AsanUseAfterScope)1492 CmdArgs.push_back("-fsanitize-address-use-after-scope");1493 1494 if (AsanPoisonCustomArrayCookie)1495 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");1496 1497 if (AsanGlobalsDeadStripping)1498 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");1499 1500 if (!AsanUseOdrIndicator)1501 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");1502 1503 if (AsanInvalidPointerCmp) {1504 CmdArgs.push_back("-mllvm");1505 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");1506 }1507 1508 if (AsanInvalidPointerSub) {1509 CmdArgs.push_back("-mllvm");1510 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");1511 }1512 1513 if (AsanOutlineInstrumentation) {1514 CmdArgs.push_back("-mllvm");1515 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");1516 }1517 1518 if (!TysanOutlineInstrumentation) {1519 CmdArgs.push_back("-mllvm");1520 CmdArgs.push_back("-tysan-outline-instrumentation=false");1521 }1522 1523 // When emitting Stable ABI instrumentation, force outlining calls and avoid1524 // inlining shadow memory poisoning. While this is a big performance burden1525 // for now it allows full abstraction from implementation details.1526 if (StableABI) {1527 CmdArgs.push_back("-mllvm");1528 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");1529 CmdArgs.push_back("-mllvm");1530 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");1531 CmdArgs.push_back("-mllvm");1532 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");1533 }1534 1535 // Only pass the option to the frontend if the user requested,1536 // otherwise the frontend will just use the codegen default.1537 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {1538 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +1539 AsanDtorKindToString(AsanDtorKind)));1540 }1541 1542 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {1543 CmdArgs.push_back(Args.MakeArgString(1544 "-fsanitize-address-use-after-return=" +1545 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));1546 }1547 1548 if (!HwasanAbi.empty()) {1549 CmdArgs.push_back("-default-function-attr");1550 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));1551 }1552 1553 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {1554 CmdArgs.push_back("-target-feature");1555 CmdArgs.push_back("+tagged-globals");1556 }1557 1558 // MSan: Workaround for PR16386.1559 // ASan: This is mainly to help LSan with cases such as1560 // https://github.com/google/sanitizers/issues/3731561 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't1562 // affect compilation.1563 if (Sanitizers.has(SanitizerKind::Memory) ||1564 Sanitizers.has(SanitizerKind::Address))1565 CmdArgs.push_back("-fno-assume-sane-operator-new");1566 1567 // Flags for -fsanitize=alloc-token.1568 if (AllocTokenFastABI)1569 CmdArgs.push_back("-fsanitize-alloc-token-fast-abi");1570 if (AllocTokenExtended)1571 CmdArgs.push_back("-fsanitize-alloc-token-extended");1572 1573 // libFuzzer wants to intercept calls to certain library functions, so the1574 // following -fno-builtin-* flags force the compiler to emit interposable1575 // libcalls to these functions. Other sanitizers effectively do the same thing1576 // by marking all library call sites with NoBuiltin attribute in their LLVM1577 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)1578 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {1579 CmdArgs.push_back("-fno-builtin-bcmp");1580 CmdArgs.push_back("-fno-builtin-memcmp");1581 CmdArgs.push_back("-fno-builtin-strncmp");1582 CmdArgs.push_back("-fno-builtin-strcmp");1583 CmdArgs.push_back("-fno-builtin-strncasecmp");1584 CmdArgs.push_back("-fno-builtin-strcasecmp");1585 CmdArgs.push_back("-fno-builtin-strstr");1586 CmdArgs.push_back("-fno-builtin-strcasestr");1587 CmdArgs.push_back("-fno-builtin-memmem");1588 }1589 1590 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is1591 // enabled.1592 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&1593 !Args.hasArg(options::OPT_fvisibility_EQ)) {1594 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)1595 << lastArgumentForMask(TC.getDriver(), Args,1596 Sanitizers.Mask & CFIClasses)1597 << "-fvisibility=";1598 }1599 1600 if (Sanitizers.has(SanitizerKind::MemtagStack) &&1601 !hasTargetFeatureMTE(CmdArgs))1602 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);1603}1604 1605SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,1606 bool DiagnoseErrors) {1607 assert(1608 (A->getOption().matches(options::OPT_fsanitize_EQ) ||1609 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||1610 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||1611 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||1612 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||1613 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||1614 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||1615 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||1616 A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||1617 A->getOption().matches(1618 options::OPT_fno_sanitize_annotate_debug_info_EQ)) &&1619 "Invalid argument in parseArgValues!");1620 SanitizerMask Kinds;1621 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1622 const char *Value = A->getValue(i);1623 SanitizerMask Kind;1624 // Special case: don't accept -fsanitize=all.1625 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&1626 0 == strcmp("all", Value))1627 Kind = SanitizerMask();1628 else1629 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);1630 1631 if (Kind)1632 Kinds |= Kind;1633 else if (DiagnoseErrors)1634 D.Diag(clang::diag::err_drv_unsupported_option_argument)1635 << A->getSpelling() << Value;1636 }1637 return Kinds;1638}1639 1640void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,1641 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs) {1642 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&1643 "Invalid argument in parseArgCutoffs!");1644 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1645 const char *Value = A->getValue(i);1646 1647 // We don't check the value of Cutoffs[i]: it's legal to specify1648 // a cutoff of 0.1649 if (!parseSanitizerWeightedValue(Value, /*AllowGroups=*/true, Cutoffs) &&1650 DiagnoseErrors)1651 D.Diag(clang::diag::err_drv_unsupported_option_argument)1652 << A->getSpelling() << Value;1653 }1654}1655 1656static int parseOverflowPatternExclusionValues(const Driver &D,1657 const llvm::opt::Arg *A,1658 bool DiagnoseErrors) {1659 int Exclusions = 0;1660 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1661 const char *Value = A->getValue(i);1662 int E =1663 llvm::StringSwitch<int>(Value)1664 .Case("none", LangOptionsBase::None)1665 .Case("all", LangOptionsBase::All)1666 .Case("add-unsigned-overflow-test",1667 LangOptionsBase::AddUnsignedOverflowTest)1668 .Case("add-signed-overflow-test",1669 LangOptionsBase::AddSignedOverflowTest)1670 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)1671 .Case("unsigned-post-decr-while", LangOptionsBase::PostDecrInWhile)1672 .Default(0);1673 if (E == 0)1674 D.Diag(clang::diag::err_drv_unsupported_option_argument)1675 << A->getSpelling() << Value;1676 Exclusions |= E;1677 }1678 return Exclusions;1679}1680 1681int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,1682 bool DiagnoseErrors) {1683 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||1684 A->getOption().matches(options::OPT_fno_sanitize_coverage));1685 int Features = 0;1686 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1687 const char *Value = A->getValue(i);1688 int F = llvm::StringSwitch<int>(Value)1689 .Case("func", CoverageFunc)1690 .Case("bb", CoverageBB)1691 .Case("edge", CoverageEdge)1692 .Case("indirect-calls", CoverageIndirCall)1693 .Case("trace-bb", CoverageTraceBB)1694 .Case("trace-cmp", CoverageTraceCmp)1695 .Case("trace-div", CoverageTraceDiv)1696 .Case("trace-gep", CoverageTraceGep)1697 .Case("8bit-counters", Coverage8bitCounters)1698 .Case("trace-pc", CoverageTracePC)1699 .Case("trace-pc-guard", CoverageTracePCGuard)1700 .Case("no-prune", CoverageNoPrune)1701 .Case("inline-8bit-counters", CoverageInline8bitCounters)1702 .Case("inline-bool-flag", CoverageInlineBoolFlag)1703 .Case("pc-table", CoveragePCTable)1704 .Case("stack-depth", CoverageStackDepth)1705 .Case("trace-loads", CoverageTraceLoads)1706 .Case("trace-stores", CoverageTraceStores)1707 .Case("control-flow", CoverageControlFlow)1708 .Default(0);1709 if (F == 0 && DiagnoseErrors)1710 D.Diag(clang::diag::err_drv_unsupported_option_argument)1711 << A->getSpelling() << Value;1712 Features |= F;1713 }1714 return Features;1715}1716 1717int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,1718 bool DiagnoseErrors) {1719 assert(1720 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||1721 A->getOption().matches(1722 options::OPT_fno_experimental_sanitize_metadata_EQ));1723 int Features = 0;1724 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1725 const char *Value = A->getValue(i);1726 int F = llvm::StringSwitch<int>(Value)1727 .Case("covered", BinaryMetadataCovered)1728 .Case("atomics", BinaryMetadataAtomics)1729 .Case("uar", BinaryMetadataUAR)1730 .Case("all", ~0)1731 .Default(0);1732 if (F == 0 && DiagnoseErrors)1733 D.Diag(clang::diag::err_drv_unsupported_option_argument)1734 << A->getSpelling() << Value;1735 Features |= F;1736 }1737 return Features;1738}1739 1740std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,1741 SanitizerMask Mask) {1742 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),1743 E = Args.rend();1744 I != E; ++I) {1745 const auto *Arg = *I;1746 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {1747 SanitizerMask AddKinds =1748 expandSanitizerGroups(parseArgValues(D, Arg, false));1749 if (AddKinds & Mask)1750 return describeSanitizeArg(Arg, Mask);1751 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {1752 SanitizerMask RemoveKinds =1753 expandSanitizerGroups(parseArgValues(D, Arg, false));1754 Mask &= ~RemoveKinds;1755 }1756 }1757 llvm_unreachable("arg list didn't provide expected value");1758}1759 1760std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {1761 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&1762 "Invalid argument in describeSanitizerArg!");1763 1764 std::string Sanitizers;1765 for (int i = 0, n = A->getNumValues(); i != n; ++i) {1766 if (expandSanitizerGroups(1767 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &1768 Mask) {1769 if (!Sanitizers.empty())1770 Sanitizers += ",";1771 Sanitizers += A->getValue(i);1772 }1773 }1774 1775 assert(!Sanitizers.empty() && "arg didn't provide expected value");1776 return "-fsanitize=" + Sanitizers;1777}1778