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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #include "clang/Driver/SanitizerArgs.h" 9 #include "ToolChains/CommonArgs.h" 10 #include "clang/Basic/Sanitizers.h" 11 #include "clang/Driver/Driver.h" 12 #include "clang/Driver/DriverDiagnostic.h" 13 #include "clang/Driver/Options.h" 14 #include "clang/Driver/ToolChain.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/Support/Path.h" 19 #include "llvm/Support/SpecialCaseList.h" 20 #include "llvm/Support/VirtualFileSystem.h" 21 #include "llvm/TargetParser/AArch64TargetParser.h" 22 #include "llvm/TargetParser/RISCVTargetParser.h" 23 #include "llvm/TargetParser/TargetParser.h" 24 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" 25 #include <memory> 26 27 using namespace clang; 28 using namespace clang::driver; 29 using namespace llvm::opt; 30 31 static const SanitizerMask NeedsUbsanRt = 32 SanitizerKind::Undefined | SanitizerKind::Integer | 33 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | 34 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | 35 SanitizerKind::ObjCCast; 36 static const SanitizerMask NeedsUbsanCxxRt = 37 SanitizerKind::Vptr | SanitizerKind::CFI; 38 static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; 39 static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; 40 static const SanitizerMask NotAllowedWithExecuteOnly = 41 SanitizerKind::Function | SanitizerKind::KCFI; 42 static const SanitizerMask RequiresPIE = 43 SanitizerKind::DataFlow | SanitizerKind::Scudo; 44 static const SanitizerMask NeedsUnwindTables = 45 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread | 46 SanitizerKind::Memory | SanitizerKind::DataFlow; 47 static const SanitizerMask SupportsCoverage = 48 SanitizerKind::Address | SanitizerKind::HWAddress | 49 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress | 50 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap | 51 SanitizerKind::MemtagGlobals | SanitizerKind::Memory | 52 SanitizerKind::KernelMemory | SanitizerKind::Leak | 53 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds | 54 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | 55 SanitizerKind::DataFlow | SanitizerKind::Fuzzer | 56 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero | 57 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack | 58 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI; 59 static const SanitizerMask RecoverableByDefault = 60 SanitizerKind::Undefined | SanitizerKind::Integer | 61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | 62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; 63 static const SanitizerMask Unrecoverable = 64 SanitizerKind::Unreachable | SanitizerKind::Return; 65 static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress | 66 SanitizerKind::KernelHWAddress | 67 SanitizerKind::KCFI; 68 static const SanitizerMask NeedsLTO = SanitizerKind::CFI; 69 static const SanitizerMask TrappingSupported = 70 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer | 71 SanitizerKind::Nullability | SanitizerKind::LocalBounds | 72 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | 73 SanitizerKind::ObjCCast; 74 static const SanitizerMask TrappingDefault = SanitizerKind::CFI; 75 static const SanitizerMask CFIClasses = 76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | 77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast | 78 SanitizerKind::CFIUnrelatedCast; 79 static const SanitizerMask CompatibleWithMinimalRuntime = 80 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack | 81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap | 82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI; 83 84 enum CoverageFeature { 85 CoverageFunc = 1 << 0, 86 CoverageBB = 1 << 1, 87 CoverageEdge = 1 << 2, 88 CoverageIndirCall = 1 << 3, 89 CoverageTraceBB = 1 << 4, // Deprecated. 90 CoverageTraceCmp = 1 << 5, 91 CoverageTraceDiv = 1 << 6, 92 CoverageTraceGep = 1 << 7, 93 Coverage8bitCounters = 1 << 8, // Deprecated. 94 CoverageTracePC = 1 << 9, 95 CoverageTracePCGuard = 1 << 10, 96 CoverageNoPrune = 1 << 11, 97 CoverageInline8bitCounters = 1 << 12, 98 CoveragePCTable = 1 << 13, 99 CoverageStackDepth = 1 << 14, 100 CoverageInlineBoolFlag = 1 << 15, 101 CoverageTraceLoads = 1 << 16, 102 CoverageTraceStores = 1 << 17, 103 CoverageControlFlow = 1 << 18, 104 }; 105 106 enum BinaryMetadataFeature { 107 BinaryMetadataCovered = 1 << 0, 108 BinaryMetadataAtomics = 1 << 1, 109 BinaryMetadataUAR = 1 << 2, 110 }; 111 112 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any 113 /// invalid components. Returns a SanitizerMask. 114 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, 115 bool DiagnoseErrors); 116 117 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid 118 /// components. Returns OR of members of \c CoverageFeature enumeration. 119 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, 120 bool DiagnoseErrors); 121 122 /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid 123 /// components. Returns OR of members of \c BinaryMetadataFeature enumeration. 124 static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, 125 bool DiagnoseErrors); 126 127 /// Produce an argument string from ArgList \p Args, which shows how it 128 /// provides some sanitizer kind from \p Mask. For example, the argument list 129 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt 130 /// would produce "-fsanitize=vptr". 131 static std::string lastArgumentForMask(const Driver &D, 132 const llvm::opt::ArgList &Args, 133 SanitizerMask Mask); 134 135 /// Produce an argument string from argument \p A, which shows how it provides 136 /// a value in \p Mask. For instance, the argument 137 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce 138 /// "-fsanitize=alignment". 139 static std::string describeSanitizeArg(const llvm::opt::Arg *A, 140 SanitizerMask Mask); 141 142 /// Produce a string containing comma-separated names of sanitizers in \p 143 /// Sanitizers set. 144 static std::string toString(const clang::SanitizerSet &Sanitizers); 145 146 /// Return true if an execute-only target disallows data access to code 147 /// sections. 148 static bool isExecuteOnlyTarget(const llvm::Triple &Triple, 149 const llvm::opt::ArgList &Args) { 150 if (Triple.isPS5()) 151 return true; 152 return Args.hasFlagNoClaim(options::OPT_mexecute_only, 153 options::OPT_mno_execute_only, false); 154 } 155 156 static void validateSpecialCaseListFormat(const Driver &D, 157 std::vector<std::string> &SCLFiles, 158 unsigned MalformedSCLErrorDiagID, 159 bool DiagnoseErrors) { 160 if (SCLFiles.empty()) 161 return; 162 163 std::string BLError; 164 std::unique_ptr<llvm::SpecialCaseList> SCL( 165 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError)); 166 if (!SCL.get() && DiagnoseErrors) 167 D.Diag(MalformedSCLErrorDiagID) << BLError; 168 } 169 170 static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, 171 std::vector<std::string> &IgnorelistFiles, 172 bool DiagnoseErrors) { 173 struct Ignorelist { 174 const char *File; 175 SanitizerMask Mask; 176 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address}, 177 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress}, 178 {"memtag_ignorelist.txt", SanitizerKind::MemTag}, 179 {"msan_ignorelist.txt", SanitizerKind::Memory}, 180 {"tsan_ignorelist.txt", SanitizerKind::Thread}, 181 {"dfsan_abilist.txt", SanitizerKind::DataFlow}, 182 {"cfi_ignorelist.txt", SanitizerKind::CFI}, 183 {"ubsan_ignorelist.txt", 184 SanitizerKind::Undefined | SanitizerKind::Integer | 185 SanitizerKind::Nullability | 186 SanitizerKind::FloatDivideByZero}}; 187 188 for (auto BL : Ignorelists) { 189 if (!(Kinds & BL.Mask)) 190 continue; 191 192 clang::SmallString<64> Path(D.ResourceDir); 193 llvm::sys::path::append(Path, "share", BL.File); 194 if (D.getVFS().exists(Path)) 195 IgnorelistFiles.push_back(std::string(Path.str())); 196 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors) 197 // If cfi_ignorelist.txt cannot be found in the resource dir, driver 198 // should fail. 199 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path; 200 } 201 validateSpecialCaseListFormat( 202 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist, 203 DiagnoseErrors); 204 } 205 206 /// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, 207 /// diagnosing any invalid file paths and validating special case list format. 208 static void parseSpecialCaseListArg(const Driver &D, 209 const llvm::opt::ArgList &Args, 210 std::vector<std::string> &SCLFiles, 211 llvm::opt::OptSpecifier SCLOptionID, 212 llvm::opt::OptSpecifier NoSCLOptionID, 213 unsigned MalformedSCLErrorDiagID, 214 bool DiagnoseErrors) { 215 for (const auto *Arg : Args) { 216 // Match -fsanitize-(coverage-)?(allow|ignore)list. 217 if (Arg->getOption().matches(SCLOptionID)) { 218 Arg->claim(); 219 std::string SCLPath = Arg->getValue(); 220 if (D.getVFS().exists(SCLPath)) { 221 SCLFiles.push_back(SCLPath); 222 } else if (DiagnoseErrors) { 223 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath; 224 } 225 // Match -fno-sanitize-ignorelist. 226 } else if (Arg->getOption().matches(NoSCLOptionID)) { 227 Arg->claim(); 228 SCLFiles.clear(); 229 } 230 } 231 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID, 232 DiagnoseErrors); 233 } 234 235 /// Sets group bits for every group that has at least one representative already 236 /// enabled in \p Kinds. 237 static SanitizerMask setGroupBits(SanitizerMask Kinds) { 238 #define SANITIZER(NAME, ID) 239 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 240 if (Kinds & SanitizerKind::ID) \ 241 Kinds |= SanitizerKind::ID##Group; 242 #include "clang/Basic/Sanitizers.def" 243 return Kinds; 244 } 245 246 static SanitizerMask parseSanitizeTrapArgs(const Driver &D, 247 const llvm::opt::ArgList &Args, 248 bool DiagnoseErrors) { 249 SanitizerMask TrapRemove; // During the loop below, the accumulated set of 250 // sanitizers disabled by the current sanitizer 251 // argument or any argument after it. 252 SanitizerMask TrappingKinds; 253 SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported); 254 255 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) { 256 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) { 257 Arg->claim(); 258 SanitizerMask Add = parseArgValues(D, Arg, true); 259 Add &= ~TrapRemove; 260 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups; 261 if (InvalidValues && DiagnoseErrors) { 262 SanitizerSet S; 263 S.Mask = InvalidValues; 264 D.Diag(diag::err_drv_unsupported_option_argument) 265 << Arg->getSpelling() << toString(S); 266 } 267 TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove; 268 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) { 269 Arg->claim(); 270 TrapRemove |= 271 expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors)); 272 } 273 } 274 275 // Apply default trapping behavior. 276 TrappingKinds |= TrappingDefault & ~TrapRemove; 277 278 return TrappingKinds; 279 } 280 281 bool SanitizerArgs::needsFuzzerInterceptors() const { 282 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt(); 283 } 284 285 bool SanitizerArgs::needsUbsanRt() const { 286 // All of these include ubsan. 287 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() || 288 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || 289 (needsScudoRt() && !requiresMinimalRuntime())) 290 return false; 291 292 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || 293 CoverageFeatures; 294 } 295 296 bool SanitizerArgs::needsCfiRt() const { 297 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && 298 CfiCrossDso && !ImplicitCfiRuntime; 299 } 300 301 bool SanitizerArgs::needsCfiDiagRt() const { 302 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) && 303 CfiCrossDso && !ImplicitCfiRuntime; 304 } 305 306 bool SanitizerArgs::requiresPIE() const { 307 return NeedPIE || (Sanitizers.Mask & RequiresPIE); 308 } 309 310 bool SanitizerArgs::needsUnwindTables() const { 311 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables); 312 } 313 314 bool SanitizerArgs::needsLTO() const { 315 return static_cast<bool>(Sanitizers.Mask & NeedsLTO); 316 } 317 318 SanitizerArgs::SanitizerArgs(const ToolChain &TC, 319 const llvm::opt::ArgList &Args, 320 bool DiagnoseErrors) { 321 SanitizerMask AllRemove; // During the loop below, the accumulated set of 322 // sanitizers disabled by the current sanitizer 323 // argument or any argument after it. 324 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by 325 // -fsanitize= flags (directly or via group 326 // expansion), some of which may be disabled 327 // later. Used to carefully prune 328 // unused-argument diagnostics. 329 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now. 330 // Used to deduplicate diagnostics. 331 SanitizerMask Kinds; 332 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers()); 333 334 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, 335 options::OPT_fno_sanitize_cfi_cross_dso, false); 336 337 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); 338 339 const Driver &D = TC.getDriver(); 340 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors); 341 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap; 342 343 MinimalRuntime = 344 Args.hasFlag(options::OPT_fsanitize_minimal_runtime, 345 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime); 346 347 // The object size sanitizer should not be enabled at -O0. 348 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group); 349 bool RemoveObjectSizeAtO0 = 350 !OptLevel || OptLevel->getOption().matches(options::OPT_O0); 351 352 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) { 353 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { 354 Arg->claim(); 355 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors); 356 357 if (RemoveObjectSizeAtO0) { 358 AllRemove |= SanitizerKind::ObjectSize; 359 360 // The user explicitly enabled the object size sanitizer. Warn 361 // that this does nothing at -O0. 362 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors) 363 D.Diag(diag::warn_drv_object_size_disabled_O0) 364 << Arg->getAsString(Args); 365 } 366 367 AllAddedKinds |= expandSanitizerGroups(Add); 368 369 // Avoid diagnosing any sanitizer which is disabled later. 370 Add &= ~AllRemove; 371 // At this point we have not expanded groups, so any unsupported 372 // sanitizers in Add are those which have been explicitly enabled. 373 // Diagnose them. 374 if (SanitizerMask KindsToDiagnose = 375 Add & InvalidTrappingKinds & ~DiagnosedKinds) { 376 if (DiagnoseErrors) { 377 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose); 378 D.Diag(diag::err_drv_argument_not_allowed_with) 379 << Desc << "-fsanitize-trap=undefined"; 380 } 381 DiagnosedKinds |= KindsToDiagnose; 382 } 383 Add &= ~InvalidTrappingKinds; 384 385 if (MinimalRuntime) { 386 if (SanitizerMask KindsToDiagnose = 387 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) { 388 if (DiagnoseErrors) { 389 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose); 390 D.Diag(diag::err_drv_argument_not_allowed_with) 391 << Desc << "-fsanitize-minimal-runtime"; 392 } 393 DiagnosedKinds |= KindsToDiagnose; 394 } 395 Add &= ~NotAllowedWithMinimalRuntime; 396 } 397 398 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { 399 StringRef CM = A->getValue(); 400 if (CM != "small" && 401 (Add & SanitizerKind::Function & ~DiagnosedKinds)) { 402 if (DiagnoseErrors) 403 D.Diag(diag::err_drv_argument_only_allowed_with) 404 << "-fsanitize=function" 405 << "-mcmodel=small"; 406 Add &= ~SanitizerKind::Function; 407 DiagnosedKinds |= SanitizerKind::Function; 408 } 409 } 410 // -fsanitize=function and -fsanitize=kcfi instrument indirect function 411 // calls to load a type hash before the function label. Therefore, an 412 // execute-only target doesn't support the function and kcfi sanitizers. 413 const llvm::Triple &Triple = TC.getTriple(); 414 if (isExecuteOnlyTarget(Triple, Args)) { 415 if (SanitizerMask KindsToDiagnose = 416 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) { 417 if (DiagnoseErrors) { 418 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose); 419 D.Diag(diag::err_drv_argument_not_allowed_with) 420 << Desc << Triple.str(); 421 } 422 DiagnosedKinds |= KindsToDiagnose; 423 } 424 Add &= ~NotAllowedWithExecuteOnly; 425 } 426 427 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI. 428 // There are currently two problems: 429 // - Virtual function call checks need to pass a pointer to the function 430 // address to llvm.type.test and a pointer to the address point to the 431 // diagnostic function. Currently we pass the same pointer to both 432 // places. 433 // - Non-virtual function call checks may need to check multiple type 434 // identifiers. 435 // Fixing both of those may require changes to the cross-DSO CFI 436 // interface. 437 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) { 438 if (DiagnoseErrors) 439 D.Diag(diag::err_drv_argument_not_allowed_with) 440 << "-fsanitize=cfi-mfcall" 441 << "-fsanitize-cfi-cross-dso"; 442 Add &= ~SanitizerKind::CFIMFCall; 443 DiagnosedKinds |= SanitizerKind::CFIMFCall; 444 } 445 446 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) { 447 if (DiagnoseErrors) { 448 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose); 449 D.Diag(diag::err_drv_unsupported_opt_for_target) 450 << Desc << TC.getTriple().str(); 451 } 452 DiagnosedKinds |= KindsToDiagnose; 453 } 454 Add &= Supported; 455 456 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups 457 // so we don't error out if -fno-rtti and -fsanitize=undefined were 458 // passed. 459 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) { 460 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) { 461 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) && 462 "RTTI disabled without -fno-rtti option?"); 463 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but 464 // the vptr sanitizer requires RTTI, so this is a user error. 465 if (DiagnoseErrors) 466 D.Diag(diag::err_drv_argument_not_allowed_with) 467 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args); 468 } else { 469 // The vptr sanitizer requires RTTI, but RTTI is disabled (by 470 // default). Warn that the vptr sanitizer is being disabled. 471 if (DiagnoseErrors) 472 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default); 473 } 474 475 // Take out the Vptr sanitizer from the enabled sanitizers 476 AllRemove |= SanitizerKind::Vptr; 477 } 478 479 Add = expandSanitizerGroups(Add); 480 // Group expansion may have enabled a sanitizer which is disabled later. 481 Add &= ~AllRemove; 482 // Silently discard any unsupported sanitizers implicitly enabled through 483 // group expansion. 484 Add &= ~InvalidTrappingKinds; 485 if (MinimalRuntime) { 486 Add &= ~NotAllowedWithMinimalRuntime; 487 } 488 // NotAllowedWithExecuteOnly is silently discarded on an execute-only 489 // target if implicitly enabled through group expansion. 490 if (isExecuteOnlyTarget(Triple, Args)) 491 Add &= ~NotAllowedWithExecuteOnly; 492 if (CfiCrossDso) 493 Add &= ~SanitizerKind::CFIMFCall; 494 Add &= Supported; 495 496 if (Add & SanitizerKind::Fuzzer) 497 Add |= SanitizerKind::FuzzerNoLink; 498 499 // Enable coverage if the fuzzing flag is set. 500 if (Add & SanitizerKind::FuzzerNoLink) { 501 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall | 502 CoverageTraceCmp | CoveragePCTable; 503 // Due to TLS differences, stack depth tracking is only enabled on Linux 504 if (TC.getTriple().isOSLinux()) 505 CoverageFeatures |= CoverageStackDepth; 506 } 507 508 Kinds |= Add; 509 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { 510 Arg->claim(); 511 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors); 512 AllRemove |= expandSanitizerGroups(Remove); 513 } 514 } 515 516 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = { 517 std::make_pair(SanitizerKind::Address, 518 SanitizerKind::Thread | SanitizerKind::Memory), 519 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory), 520 std::make_pair(SanitizerKind::Leak, 521 SanitizerKind::Thread | SanitizerKind::Memory), 522 std::make_pair(SanitizerKind::KernelAddress, 523 SanitizerKind::Address | SanitizerKind::Leak | 524 SanitizerKind::Thread | SanitizerKind::Memory), 525 std::make_pair(SanitizerKind::HWAddress, 526 SanitizerKind::Address | SanitizerKind::Thread | 527 SanitizerKind::Memory | SanitizerKind::KernelAddress), 528 std::make_pair(SanitizerKind::Scudo, 529 SanitizerKind::Address | SanitizerKind::HWAddress | 530 SanitizerKind::Leak | SanitizerKind::Thread | 531 SanitizerKind::Memory | SanitizerKind::KernelAddress), 532 std::make_pair(SanitizerKind::SafeStack, 533 (TC.getTriple().isOSFuchsia() ? SanitizerMask() 534 : SanitizerKind::Leak) | 535 SanitizerKind::Address | SanitizerKind::HWAddress | 536 SanitizerKind::Thread | SanitizerKind::Memory | 537 SanitizerKind::KernelAddress), 538 std::make_pair(SanitizerKind::KernelHWAddress, 539 SanitizerKind::Address | SanitizerKind::HWAddress | 540 SanitizerKind::Leak | SanitizerKind::Thread | 541 SanitizerKind::Memory | SanitizerKind::KernelAddress | 542 SanitizerKind::SafeStack), 543 std::make_pair(SanitizerKind::KernelMemory, 544 SanitizerKind::Address | SanitizerKind::HWAddress | 545 SanitizerKind::Leak | SanitizerKind::Thread | 546 SanitizerKind::Memory | SanitizerKind::KernelAddress | 547 SanitizerKind::Scudo | SanitizerKind::SafeStack), 548 std::make_pair(SanitizerKind::MemTag, 549 SanitizerKind::Address | SanitizerKind::KernelAddress | 550 SanitizerKind::HWAddress | 551 SanitizerKind::KernelHWAddress), 552 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)}; 553 // Enable toolchain specific default sanitizers if not explicitly disabled. 554 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove; 555 556 // Disable default sanitizers that are incompatible with explicitly requested 557 // ones. 558 for (auto G : IncompatibleGroups) { 559 SanitizerMask Group = G.first; 560 if ((Default & Group) && (Kinds & G.second)) 561 Default &= ~Group; 562 } 563 564 Kinds |= Default; 565 566 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI 567 // is disabled. 568 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) { 569 Kinds &= ~SanitizerKind::Vptr; 570 } 571 572 // Check that LTO is enabled if we need it. 573 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) { 574 D.Diag(diag::err_drv_argument_only_allowed_with) 575 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto"; 576 } 577 578 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() && 579 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) && 580 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) { 581 D.Diag(diag::err_drv_argument_only_allowed_with) 582 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack) 583 << "-ffixed-x18"; 584 } 585 586 // Report error if there are non-trapping sanitizers that require 587 // c++abi-specific parts of UBSan runtime, and they are not provided by the 588 // toolchain. We don't have a good way to check the latter, so we just 589 // check if the toolchan supports vptr. 590 if (~Supported & SanitizerKind::Vptr) { 591 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt; 592 // The runtime library supports the Microsoft C++ ABI, but only well enough 593 // for CFI. FIXME: Remove this once we support vptr on Windows. 594 if (TC.getTriple().isOSWindows()) 595 KindsToDiagnose &= ~SanitizerKind::CFI; 596 if (KindsToDiagnose) { 597 SanitizerSet S; 598 S.Mask = KindsToDiagnose; 599 if (DiagnoseErrors) 600 D.Diag(diag::err_drv_unsupported_opt_for_target) 601 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str(); 602 Kinds &= ~KindsToDiagnose; 603 } 604 } 605 606 // Warn about incompatible groups of sanitizers. 607 for (auto G : IncompatibleGroups) { 608 SanitizerMask Group = G.first; 609 if (Kinds & Group) { 610 if (SanitizerMask Incompatible = Kinds & G.second) { 611 if (DiagnoseErrors) 612 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 613 << lastArgumentForMask(D, Args, Group) 614 << lastArgumentForMask(D, Args, Incompatible); 615 Kinds &= ~Incompatible; 616 } 617 } 618 } 619 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of 620 // -fsanitize=address. Perhaps it should print an error, or perhaps 621 // -f(-no)sanitize=leak should change whether leak detection is enabled by 622 // default in ASan? 623 624 // Parse -f(no-)?sanitize-recover flags. 625 SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable; 626 SanitizerMask DiagnosedUnrecoverableKinds; 627 SanitizerMask DiagnosedAlwaysRecoverableKinds; 628 for (const auto *Arg : Args) { 629 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { 630 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors); 631 // Report error if user explicitly tries to recover from unrecoverable 632 // sanitizer. 633 if (SanitizerMask KindsToDiagnose = 634 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) { 635 SanitizerSet SetToDiagnose; 636 SetToDiagnose.Mask |= KindsToDiagnose; 637 if (DiagnoseErrors) 638 D.Diag(diag::err_drv_unsupported_option_argument) 639 << Arg->getSpelling() << toString(SetToDiagnose); 640 DiagnosedUnrecoverableKinds |= KindsToDiagnose; 641 } 642 RecoverableKinds |= expandSanitizerGroups(Add); 643 Arg->claim(); 644 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) { 645 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors); 646 // Report error if user explicitly tries to disable recovery from 647 // always recoverable sanitizer. 648 if (SanitizerMask KindsToDiagnose = 649 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) { 650 SanitizerSet SetToDiagnose; 651 SetToDiagnose.Mask |= KindsToDiagnose; 652 if (DiagnoseErrors) 653 D.Diag(diag::err_drv_unsupported_option_argument) 654 << Arg->getSpelling() << toString(SetToDiagnose); 655 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose; 656 } 657 RecoverableKinds &= ~expandSanitizerGroups(Remove); 658 Arg->claim(); 659 } 660 } 661 RecoverableKinds &= Kinds; 662 RecoverableKinds &= ~Unrecoverable; 663 664 TrappingKinds &= Kinds; 665 RecoverableKinds &= ~TrappingKinds; 666 667 // Setup ignorelist files. 668 // Add default ignorelist from resource directory for activated sanitizers, 669 // and validate special case lists format. 670 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist)) 671 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors); 672 673 // Parse -f(no-)?sanitize-ignorelist options. 674 // This also validates special case lists format. 675 parseSpecialCaseListArg( 676 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ, 677 options::OPT_fno_sanitize_ignorelist, 678 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors); 679 680 // Parse -f[no-]sanitize-memory-track-origins[=level] options. 681 if (AllAddedKinds & SanitizerKind::Memory) { 682 if (Arg *A = 683 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ, 684 options::OPT_fno_sanitize_memory_track_origins)) { 685 if (!A->getOption().matches( 686 options::OPT_fno_sanitize_memory_track_origins)) { 687 StringRef S = A->getValue(); 688 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 || 689 MsanTrackOrigins > 2) { 690 if (DiagnoseErrors) 691 D.Diag(clang::diag::err_drv_invalid_value) 692 << A->getAsString(Args) << S; 693 } 694 } 695 } 696 MsanUseAfterDtor = Args.hasFlag( 697 options::OPT_fsanitize_memory_use_after_dtor, 698 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor); 699 MsanParamRetval = Args.hasFlag( 700 options::OPT_fsanitize_memory_param_retval, 701 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval); 702 NeedPIE |= !(TC.getTriple().isOSLinux() && 703 TC.getTriple().getArch() == llvm::Triple::x86_64); 704 } else if (AllAddedKinds & SanitizerKind::KernelMemory) { 705 MsanUseAfterDtor = false; 706 MsanParamRetval = Args.hasFlag( 707 options::OPT_fsanitize_memory_param_retval, 708 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval); 709 } else { 710 MsanUseAfterDtor = false; 711 MsanParamRetval = false; 712 } 713 714 if (AllAddedKinds & SanitizerKind::MemTag) { 715 StringRef S = 716 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync"); 717 if (S == "async" || S == "sync") { 718 MemtagMode = S.str(); 719 } else { 720 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion) 721 << "-fsanitize-memtag-mode=" << S << "{async, sync}"; 722 MemtagMode = "sync"; 723 } 724 } 725 726 if (AllAddedKinds & SanitizerKind::Thread) { 727 TsanMemoryAccess = Args.hasFlag( 728 options::OPT_fsanitize_thread_memory_access, 729 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess); 730 TsanFuncEntryExit = Args.hasFlag( 731 options::OPT_fsanitize_thread_func_entry_exit, 732 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit); 733 TsanAtomics = 734 Args.hasFlag(options::OPT_fsanitize_thread_atomics, 735 options::OPT_fno_sanitize_thread_atomics, TsanAtomics); 736 } 737 738 if (AllAddedKinds & SanitizerKind::CFI) { 739 // Without PIE, external function address may resolve to a PLT record, which 740 // can not be verified by the target module. 741 NeedPIE |= CfiCrossDso; 742 CfiICallGeneralizePointers = 743 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers); 744 745 CfiICallNormalizeIntegers = 746 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers); 747 748 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors) 749 D.Diag(diag::err_drv_argument_not_allowed_with) 750 << "-fsanitize-cfi-cross-dso" 751 << "-fsanitize-cfi-icall-generalize-pointers"; 752 753 CfiCanonicalJumpTables = 754 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables, 755 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true); 756 } 757 758 if (AllAddedKinds & SanitizerKind::KCFI) { 759 CfiICallNormalizeIntegers = 760 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers); 761 762 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors) 763 D.Diag(diag::err_drv_argument_not_allowed_with) 764 << "-fsanitize=kcfi" 765 << lastArgumentForMask(D, Args, SanitizerKind::CFI); 766 } 767 768 Stats = Args.hasFlag(options::OPT_fsanitize_stats, 769 options::OPT_fno_sanitize_stats, false); 770 771 if (MinimalRuntime) { 772 SanitizerMask IncompatibleMask = 773 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime); 774 if (IncompatibleMask && DiagnoseErrors) 775 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 776 << "-fsanitize-minimal-runtime" 777 << lastArgumentForMask(D, Args, IncompatibleMask); 778 779 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds; 780 if (NonTrappingCfi && DiagnoseErrors) 781 D.Diag(clang::diag::err_drv_argument_only_allowed_with) 782 << "fsanitize-minimal-runtime" 783 << "fsanitize-trap=cfi"; 784 } 785 786 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the 787 // enabled sanitizers. 788 for (const auto *Arg : Args) { 789 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) { 790 int LegacySanitizeCoverage; 791 if (Arg->getNumValues() == 1 && 792 !StringRef(Arg->getValue(0)) 793 .getAsInteger(0, LegacySanitizeCoverage)) { 794 CoverageFeatures = 0; 795 Arg->claim(); 796 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) { 797 D.Diag(diag::warn_drv_deprecated_arg) 798 << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard"; 799 } 800 continue; 801 } 802 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors); 803 804 // Disable coverage and not claim the flags if there is at least one 805 // non-supporting sanitizer. 806 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) { 807 Arg->claim(); 808 } else { 809 CoverageFeatures = 0; 810 } 811 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) { 812 Arg->claim(); 813 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors); 814 } 815 } 816 // Choose at most one coverage type: function, bb, or edge. 817 if (DiagnoseErrors) { 818 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB)) 819 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 820 << "-fsanitize-coverage=func" 821 << "-fsanitize-coverage=bb"; 822 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge)) 823 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 824 << "-fsanitize-coverage=func" 825 << "-fsanitize-coverage=edge"; 826 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge)) 827 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 828 << "-fsanitize-coverage=bb" 829 << "-fsanitize-coverage=edge"; 830 // Basic block tracing and 8-bit counters require some type of coverage 831 // enabled. 832 if (CoverageFeatures & CoverageTraceBB) 833 D.Diag(clang::diag::warn_drv_deprecated_arg) 834 << "-fsanitize-coverage=trace-bb" 835 << "-fsanitize-coverage=trace-pc-guard"; 836 if (CoverageFeatures & Coverage8bitCounters) 837 D.Diag(clang::diag::warn_drv_deprecated_arg) 838 << "-fsanitize-coverage=8bit-counters" 839 << "-fsanitize-coverage=trace-pc-guard"; 840 } 841 842 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge; 843 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard | 844 CoverageInline8bitCounters | CoverageTraceLoads | 845 CoverageTraceStores | CoverageInlineBoolFlag | 846 CoverageControlFlow; 847 if ((CoverageFeatures & InsertionPointTypes) && 848 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) { 849 D.Diag(clang::diag::warn_drv_deprecated_arg) 850 << "-fsanitize-coverage=[func|bb|edge]" 851 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],[" 852 "control-flow]"; 853 } 854 855 // trace-pc w/o func/bb/edge implies edge. 856 if (!(CoverageFeatures & InsertionPointTypes)) { 857 if (CoverageFeatures & 858 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters | 859 CoverageInlineBoolFlag | CoverageControlFlow)) 860 CoverageFeatures |= CoverageEdge; 861 862 if (CoverageFeatures & CoverageStackDepth) 863 CoverageFeatures |= CoverageFunc; 864 } 865 866 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled. 867 // This also validates special case lists format. 868 // Here, OptSpecifier() acts as a never-matching command-line argument. 869 // So, there is no way to clear coverage lists but you can append to them. 870 if (CoverageFeatures) { 871 parseSpecialCaseListArg( 872 D, Args, CoverageAllowlistFiles, 873 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(), 874 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist, 875 DiagnoseErrors); 876 parseSpecialCaseListArg( 877 D, Args, CoverageIgnorelistFiles, 878 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(), 879 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist, 880 DiagnoseErrors); 881 } 882 883 // Parse -f(no-)?sanitize-metadata. 884 for (const auto *Arg : 885 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ, 886 options::OPT_fno_experimental_sanitize_metadata_EQ)) { 887 if (Arg->getOption().matches( 888 options::OPT_fexperimental_sanitize_metadata_EQ)) { 889 Arg->claim(); 890 BinaryMetadataFeatures |= 891 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors); 892 } else { 893 Arg->claim(); 894 BinaryMetadataFeatures &= 895 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors); 896 } 897 } 898 899 // Parse -fsanitize-metadata-ignorelist option if enabled. 900 if (BinaryMetadataFeatures) { 901 parseSpecialCaseListArg( 902 D, Args, BinaryMetadataIgnorelistFiles, 903 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ, 904 OptSpecifier(), // Cannot clear ignore list, only append. 905 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist, 906 DiagnoseErrors); 907 } 908 909 SharedRuntime = 910 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan, 911 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() || 912 TC.getTriple().isOSDarwin()); 913 914 ImplicitCfiRuntime = TC.getTriple().isAndroid(); 915 916 if (AllAddedKinds & SanitizerKind::Address) { 917 NeedPIE |= TC.getTriple().isOSFuchsia(); 918 if (Arg *A = 919 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) { 920 StringRef S = A->getValue(); 921 // Legal values are 0 and 1, 2, but in future we may add more levels. 922 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 || 923 AsanFieldPadding > 2) && 924 DiagnoseErrors) { 925 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; 926 } 927 } 928 929 if (Arg *WindowsDebugRTArg = 930 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT, 931 options::OPT__SLASH_MDd, options::OPT__SLASH_MD, 932 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) { 933 switch (WindowsDebugRTArg->getOption().getID()) { 934 case options::OPT__SLASH_MTd: 935 case options::OPT__SLASH_MDd: 936 case options::OPT__SLASH_LDd: 937 if (DiagnoseErrors) { 938 D.Diag(clang::diag::err_drv_argument_not_allowed_with) 939 << WindowsDebugRTArg->getAsString(Args) 940 << lastArgumentForMask(D, Args, SanitizerKind::Address); 941 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime); 942 } 943 } 944 } 945 946 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi, 947 options::OPT_fno_sanitize_stable_abi, false); 948 949 AsanUseAfterScope = Args.hasFlag( 950 options::OPT_fsanitize_address_use_after_scope, 951 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope); 952 953 AsanPoisonCustomArrayCookie = Args.hasFlag( 954 options::OPT_fsanitize_address_poison_custom_array_cookie, 955 options::OPT_fno_sanitize_address_poison_custom_array_cookie, 956 AsanPoisonCustomArrayCookie); 957 958 AsanOutlineInstrumentation = 959 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation, 960 options::OPT_fno_sanitize_address_outline_instrumentation, 961 AsanOutlineInstrumentation); 962 963 AsanGlobalsDeadStripping = Args.hasFlag( 964 options::OPT_fsanitize_address_globals_dead_stripping, 965 options::OPT_fno_sanitize_address_globals_dead_stripping, true); 966 967 // Enable ODR indicators which allow better handling of mixed instrumented 968 // and uninstrumented globals. Disable them for Windows where weak odr 969 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker 970 // errors in the absence of -lldmingw. 971 AsanUseOdrIndicator = 972 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator, 973 options::OPT_fno_sanitize_address_use_odr_indicator, 974 !TC.getTriple().isOSWindows()); 975 976 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) { 977 AsanInvalidPointerCmp = true; 978 } 979 980 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) { 981 AsanInvalidPointerSub = true; 982 } 983 984 if (TC.getTriple().isOSDarwin() && 985 (Args.hasArg(options::OPT_mkernel) || 986 Args.hasArg(options::OPT_fapple_kext))) { 987 AsanDtorKind = llvm::AsanDtorKind::None; 988 } 989 990 if (const auto *Arg = 991 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) { 992 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue()); 993 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) { 994 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument) 995 << Arg->getSpelling() << Arg->getValue(); 996 } 997 AsanDtorKind = parsedAsanDtorKind; 998 } 999 1000 if (const auto *Arg = Args.getLastArg( 1001 options::OPT_sanitize_address_use_after_return_EQ)) { 1002 auto parsedAsanUseAfterReturn = 1003 AsanDetectStackUseAfterReturnModeFromString(Arg->getValue()); 1004 if (parsedAsanUseAfterReturn == 1005 llvm::AsanDetectStackUseAfterReturnMode::Invalid && 1006 DiagnoseErrors) { 1007 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument) 1008 << Arg->getSpelling() << Arg->getValue(); 1009 } 1010 AsanUseAfterReturn = parsedAsanUseAfterReturn; 1011 } 1012 1013 } else { 1014 AsanUseAfterScope = false; 1015 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address. 1016 SanitizerMask DetectInvalidPointerPairs = 1017 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract; 1018 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) && 1019 DiagnoseErrors) { 1020 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with) 1021 << lastArgumentForMask(D, Args, 1022 SanitizerKind::PointerCompare | 1023 SanitizerKind::PointerSubtract) 1024 << "-fsanitize=address"; 1025 } 1026 } 1027 1028 if (AllAddedKinds & SanitizerKind::HWAddress) { 1029 if (Arg *HwasanAbiArg = 1030 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) { 1031 HwasanAbi = HwasanAbiArg->getValue(); 1032 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" && 1033 DiagnoseErrors) 1034 D.Diag(clang::diag::err_drv_invalid_value) 1035 << HwasanAbiArg->getAsString(Args) << HwasanAbi; 1036 } else { 1037 HwasanAbi = "interceptor"; 1038 } 1039 if (TC.getTriple().getArch() == llvm::Triple::x86_64) 1040 HwasanUseAliases = Args.hasFlag( 1041 options::OPT_fsanitize_hwaddress_experimental_aliasing, 1042 options::OPT_fno_sanitize_hwaddress_experimental_aliasing, 1043 HwasanUseAliases); 1044 } 1045 1046 if (AllAddedKinds & SanitizerKind::SafeStack) { 1047 // SafeStack runtime is built into the system on Android and Fuchsia. 1048 SafeStackRuntime = 1049 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia(); 1050 } 1051 1052 LinkRuntimes = 1053 Args.hasFlag(options::OPT_fsanitize_link_runtime, 1054 options::OPT_fno_sanitize_link_runtime, LinkRuntimes); 1055 1056 // Parse -link-cxx-sanitizer flag. 1057 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime, 1058 options::OPT_fno_sanitize_link_cxx_runtime, 1059 LinkCXXRuntimes) || 1060 D.CCCIsCXX(); 1061 1062 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile, 1063 options::OPT_fmemory_profile_EQ, 1064 options::OPT_fno_memory_profile, false); 1065 1066 // Finally, initialize the set of available and recoverable sanitizers. 1067 Sanitizers.Mask |= Kinds; 1068 RecoverableSanitizers.Mask |= RecoverableKinds; 1069 TrapSanitizers.Mask |= TrappingKinds; 1070 assert(!(RecoverableKinds & TrappingKinds) && 1071 "Overlap between recoverable and trapping sanitizers"); 1072 } 1073 1074 static std::string toString(const clang::SanitizerSet &Sanitizers) { 1075 std::string Res; 1076 #define SANITIZER(NAME, ID) \ 1077 if (Sanitizers.has(SanitizerKind::ID)) { \ 1078 if (!Res.empty()) \ 1079 Res += ","; \ 1080 Res += NAME; \ 1081 } 1082 #include "clang/Basic/Sanitizers.def" 1083 return Res; 1084 } 1085 1086 static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args, 1087 llvm::opt::ArgStringList &CmdArgs, 1088 const char *SCLOptFlag, 1089 const std::vector<std::string> &SCLFiles) { 1090 for (const auto &SCLPath : SCLFiles) { 1091 SmallString<64> SCLOpt(SCLOptFlag); 1092 SCLOpt += SCLPath; 1093 CmdArgs.push_back(Args.MakeArgString(SCLOpt)); 1094 } 1095 } 1096 1097 static void addIncludeLinkerOption(const ToolChain &TC, 1098 const llvm::opt::ArgList &Args, 1099 llvm::opt::ArgStringList &CmdArgs, 1100 StringRef SymbolName) { 1101 SmallString<64> LinkerOptionFlag; 1102 LinkerOptionFlag = "--linker-option=/include:"; 1103 if (TC.getTriple().getArch() == llvm::Triple::x86) { 1104 // Win32 mangles C function names with a '_' prefix. 1105 LinkerOptionFlag += '_'; 1106 } 1107 LinkerOptionFlag += SymbolName; 1108 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag)); 1109 } 1110 1111 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) { 1112 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; 1113 ++Start) { 1114 auto It = std::find(Start, End, StringRef("+mte")); 1115 if (It == End) 1116 break; 1117 if (It > Start && *std::prev(It) == StringRef("-target-feature")) 1118 return true; 1119 Start = It; 1120 } 1121 return false; 1122 } 1123 1124 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, 1125 llvm::opt::ArgStringList &CmdArgs, 1126 types::ID InputType) const { 1127 // NVPTX doesn't currently support sanitizers. Bailing out here means 1128 // that e.g. -fsanitize=address applies only to host code, which is what we 1129 // want for now. 1130 if (TC.getTriple().isNVPTX()) 1131 return; 1132 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize. 1133 bool GPUSanitize = false; 1134 if (TC.getTriple().isAMDGPU()) { 1135 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize, 1136 true)) 1137 return; 1138 GPUSanitize = true; 1139 } 1140 1141 // Translate available CoverageFeatures to corresponding clang-cc1 flags. 1142 // Do it even if Sanitizers.empty() since some forms of coverage don't require 1143 // sanitizers. 1144 std::pair<int, const char *> CoverageFlags[] = { 1145 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"), 1146 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"), 1147 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"), 1148 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"), 1149 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"), 1150 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"), 1151 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"), 1152 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"), 1153 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), 1154 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), 1155 std::make_pair(CoverageTracePCGuard, 1156 "-fsanitize-coverage-trace-pc-guard"), 1157 std::make_pair(CoverageInline8bitCounters, 1158 "-fsanitize-coverage-inline-8bit-counters"), 1159 std::make_pair(CoverageInlineBoolFlag, 1160 "-fsanitize-coverage-inline-bool-flag"), 1161 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"), 1162 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"), 1163 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"), 1164 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"), 1165 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"), 1166 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")}; 1167 for (auto F : CoverageFlags) { 1168 if (CoverageFeatures & F.first) 1169 CmdArgs.push_back(F.second); 1170 } 1171 addSpecialCaseListOpt( 1172 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles); 1173 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=", 1174 CoverageIgnorelistFiles); 1175 1176 if (!GPUSanitize) { 1177 // Translate available BinaryMetadataFeatures to corresponding clang-cc1 1178 // flags. Does not depend on any other sanitizers. Unsupported on GPUs. 1179 const std::pair<int, std::string> BinaryMetadataFlags[] = { 1180 std::make_pair(BinaryMetadataCovered, "covered"), 1181 std::make_pair(BinaryMetadataAtomics, "atomics"), 1182 std::make_pair(BinaryMetadataUAR, "uar")}; 1183 for (const auto &F : BinaryMetadataFlags) { 1184 if (BinaryMetadataFeatures & F.first) 1185 CmdArgs.push_back( 1186 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second)); 1187 } 1188 addSpecialCaseListOpt(Args, CmdArgs, 1189 "-fexperimental-sanitize-metadata-ignorelist=", 1190 BinaryMetadataIgnorelistFiles); 1191 } 1192 1193 if (TC.getTriple().isOSWindows() && needsUbsanRt()) { 1194 // Instruct the code generator to embed linker directives in the object file 1195 // that cause the required runtime libraries to be linked. 1196 CmdArgs.push_back( 1197 Args.MakeArgString("--dependent-lib=" + 1198 TC.getCompilerRTBasename(Args, "ubsan_standalone"))); 1199 if (types::isCXX(InputType)) 1200 CmdArgs.push_back(Args.MakeArgString( 1201 "--dependent-lib=" + 1202 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx"))); 1203 } 1204 if (TC.getTriple().isOSWindows() && needsStatsRt()) { 1205 CmdArgs.push_back(Args.MakeArgString( 1206 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client"))); 1207 1208 // The main executable must export the stats runtime. 1209 // FIXME: Only exporting from the main executable (e.g. based on whether the 1210 // translation unit defines main()) would save a little space, but having 1211 // multiple copies of the runtime shouldn't hurt. 1212 CmdArgs.push_back(Args.MakeArgString( 1213 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats"))); 1214 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register"); 1215 } 1216 1217 if (Sanitizers.empty()) 1218 return; 1219 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers))); 1220 1221 if (!RecoverableSanitizers.empty()) 1222 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" + 1223 toString(RecoverableSanitizers))); 1224 1225 if (!TrapSanitizers.empty()) 1226 CmdArgs.push_back( 1227 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers))); 1228 1229 addSpecialCaseListOpt(Args, CmdArgs, 1230 "-fsanitize-ignorelist=", UserIgnorelistFiles); 1231 addSpecialCaseListOpt(Args, CmdArgs, 1232 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles); 1233 1234 if (MsanTrackOrigins) 1235 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + 1236 Twine(MsanTrackOrigins))); 1237 1238 if (MsanUseAfterDtor) 1239 CmdArgs.push_back("-fsanitize-memory-use-after-dtor"); 1240 1241 if (!MsanParamRetval) 1242 CmdArgs.push_back("-fno-sanitize-memory-param-retval"); 1243 1244 // FIXME: Pass these parameters as function attributes, not as -llvm flags. 1245 if (!TsanMemoryAccess) { 1246 CmdArgs.push_back("-mllvm"); 1247 CmdArgs.push_back("-tsan-instrument-memory-accesses=0"); 1248 CmdArgs.push_back("-mllvm"); 1249 CmdArgs.push_back("-tsan-instrument-memintrinsics=0"); 1250 } 1251 if (!TsanFuncEntryExit) { 1252 CmdArgs.push_back("-mllvm"); 1253 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0"); 1254 } 1255 if (!TsanAtomics) { 1256 CmdArgs.push_back("-mllvm"); 1257 CmdArgs.push_back("-tsan-instrument-atomics=0"); 1258 } 1259 1260 if (HwasanUseAliases) { 1261 CmdArgs.push_back("-mllvm"); 1262 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1"); 1263 } 1264 1265 if (CfiCrossDso) 1266 CmdArgs.push_back("-fsanitize-cfi-cross-dso"); 1267 1268 if (CfiICallGeneralizePointers) 1269 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers"); 1270 1271 if (CfiICallNormalizeIntegers) 1272 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers"); 1273 1274 if (CfiCanonicalJumpTables) 1275 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables"); 1276 1277 if (Stats) 1278 CmdArgs.push_back("-fsanitize-stats"); 1279 1280 if (MinimalRuntime) 1281 CmdArgs.push_back("-fsanitize-minimal-runtime"); 1282 1283 if (AsanFieldPadding) 1284 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + 1285 Twine(AsanFieldPadding))); 1286 1287 if (AsanUseAfterScope) 1288 CmdArgs.push_back("-fsanitize-address-use-after-scope"); 1289 1290 if (AsanPoisonCustomArrayCookie) 1291 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie"); 1292 1293 if (AsanGlobalsDeadStripping) 1294 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping"); 1295 1296 if (!AsanUseOdrIndicator) 1297 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator"); 1298 1299 if (AsanInvalidPointerCmp) { 1300 CmdArgs.push_back("-mllvm"); 1301 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp"); 1302 } 1303 1304 if (AsanInvalidPointerSub) { 1305 CmdArgs.push_back("-mllvm"); 1306 CmdArgs.push_back("-asan-detect-invalid-pointer-sub"); 1307 } 1308 1309 if (AsanOutlineInstrumentation) { 1310 CmdArgs.push_back("-mllvm"); 1311 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0"); 1312 } 1313 1314 // When emitting Stable ABI instrumentation, force outlining calls and avoid 1315 // inlining shadow memory poisoning. While this is a big performance burden 1316 // for now it allows full abstraction from implementation details. 1317 if (StableABI) { 1318 CmdArgs.push_back("-mllvm"); 1319 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0"); 1320 CmdArgs.push_back("-mllvm"); 1321 CmdArgs.push_back("-asan-max-inline-poisoning-size=0"); 1322 } 1323 1324 // Only pass the option to the frontend if the user requested, 1325 // otherwise the frontend will just use the codegen default. 1326 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) { 1327 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" + 1328 AsanDtorKindToString(AsanDtorKind))); 1329 } 1330 1331 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) { 1332 CmdArgs.push_back(Args.MakeArgString( 1333 "-fsanitize-address-use-after-return=" + 1334 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn))); 1335 } 1336 1337 if (!HwasanAbi.empty()) { 1338 CmdArgs.push_back("-default-function-attr"); 1339 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi)); 1340 } 1341 1342 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) { 1343 CmdArgs.push_back("-target-feature"); 1344 CmdArgs.push_back("+tagged-globals"); 1345 } 1346 1347 // MSan: Workaround for PR16386. 1348 // ASan: This is mainly to help LSan with cases such as 1349 // https://github.com/google/sanitizers/issues/373 1350 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't 1351 // affect compilation. 1352 if (Sanitizers.has(SanitizerKind::Memory) || 1353 Sanitizers.has(SanitizerKind::Address)) 1354 CmdArgs.push_back("-fno-assume-sane-operator-new"); 1355 1356 // libFuzzer wants to intercept calls to certain library functions, so the 1357 // following -fno-builtin-* flags force the compiler to emit interposable 1358 // libcalls to these functions. Other sanitizers effectively do the same thing 1359 // by marking all library call sites with NoBuiltin attribute in their LLVM 1360 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin) 1361 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) { 1362 CmdArgs.push_back("-fno-builtin-bcmp"); 1363 CmdArgs.push_back("-fno-builtin-memcmp"); 1364 CmdArgs.push_back("-fno-builtin-strncmp"); 1365 CmdArgs.push_back("-fno-builtin-strcmp"); 1366 CmdArgs.push_back("-fno-builtin-strncasecmp"); 1367 CmdArgs.push_back("-fno-builtin-strcasecmp"); 1368 CmdArgs.push_back("-fno-builtin-strstr"); 1369 CmdArgs.push_back("-fno-builtin-strcasestr"); 1370 CmdArgs.push_back("-fno-builtin-memmem"); 1371 } 1372 1373 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is 1374 // enabled. 1375 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() && 1376 !Args.hasArg(options::OPT_fvisibility_EQ)) { 1377 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with) 1378 << lastArgumentForMask(TC.getDriver(), Args, 1379 Sanitizers.Mask & CFIClasses) 1380 << "-fvisibility="; 1381 } 1382 1383 if (Sanitizers.has(SanitizerKind::MemtagStack) && 1384 !hasTargetFeatureMTE(CmdArgs)) 1385 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature); 1386 } 1387 1388 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, 1389 bool DiagnoseErrors) { 1390 assert((A->getOption().matches(options::OPT_fsanitize_EQ) || 1391 A->getOption().matches(options::OPT_fno_sanitize_EQ) || 1392 A->getOption().matches(options::OPT_fsanitize_recover_EQ) || 1393 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || 1394 A->getOption().matches(options::OPT_fsanitize_trap_EQ) || 1395 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) && 1396 "Invalid argument in parseArgValues!"); 1397 SanitizerMask Kinds; 1398 for (int i = 0, n = A->getNumValues(); i != n; ++i) { 1399 const char *Value = A->getValue(i); 1400 SanitizerMask Kind; 1401 // Special case: don't accept -fsanitize=all. 1402 if (A->getOption().matches(options::OPT_fsanitize_EQ) && 1403 0 == strcmp("all", Value)) 1404 Kind = SanitizerMask(); 1405 else 1406 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true); 1407 1408 if (Kind) 1409 Kinds |= Kind; 1410 else if (DiagnoseErrors) 1411 D.Diag(clang::diag::err_drv_unsupported_option_argument) 1412 << A->getSpelling() << Value; 1413 } 1414 return Kinds; 1415 } 1416 1417 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, 1418 bool DiagnoseErrors) { 1419 assert(A->getOption().matches(options::OPT_fsanitize_coverage) || 1420 A->getOption().matches(options::OPT_fno_sanitize_coverage)); 1421 int Features = 0; 1422 for (int i = 0, n = A->getNumValues(); i != n; ++i) { 1423 const char *Value = A->getValue(i); 1424 int F = llvm::StringSwitch<int>(Value) 1425 .Case("func", CoverageFunc) 1426 .Case("bb", CoverageBB) 1427 .Case("edge", CoverageEdge) 1428 .Case("indirect-calls", CoverageIndirCall) 1429 .Case("trace-bb", CoverageTraceBB) 1430 .Case("trace-cmp", CoverageTraceCmp) 1431 .Case("trace-div", CoverageTraceDiv) 1432 .Case("trace-gep", CoverageTraceGep) 1433 .Case("8bit-counters", Coverage8bitCounters) 1434 .Case("trace-pc", CoverageTracePC) 1435 .Case("trace-pc-guard", CoverageTracePCGuard) 1436 .Case("no-prune", CoverageNoPrune) 1437 .Case("inline-8bit-counters", CoverageInline8bitCounters) 1438 .Case("inline-bool-flag", CoverageInlineBoolFlag) 1439 .Case("pc-table", CoveragePCTable) 1440 .Case("stack-depth", CoverageStackDepth) 1441 .Case("trace-loads", CoverageTraceLoads) 1442 .Case("trace-stores", CoverageTraceStores) 1443 .Case("control-flow", CoverageControlFlow) 1444 .Default(0); 1445 if (F == 0 && DiagnoseErrors) 1446 D.Diag(clang::diag::err_drv_unsupported_option_argument) 1447 << A->getSpelling() << Value; 1448 Features |= F; 1449 } 1450 return Features; 1451 } 1452 1453 int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, 1454 bool DiagnoseErrors) { 1455 assert( 1456 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) || 1457 A->getOption().matches( 1458 options::OPT_fno_experimental_sanitize_metadata_EQ)); 1459 int Features = 0; 1460 for (int i = 0, n = A->getNumValues(); i != n; ++i) { 1461 const char *Value = A->getValue(i); 1462 int F = llvm::StringSwitch<int>(Value) 1463 .Case("covered", BinaryMetadataCovered) 1464 .Case("atomics", BinaryMetadataAtomics) 1465 .Case("uar", BinaryMetadataUAR) 1466 .Case("all", ~0) 1467 .Default(0); 1468 if (F == 0 && DiagnoseErrors) 1469 D.Diag(clang::diag::err_drv_unsupported_option_argument) 1470 << A->getSpelling() << Value; 1471 Features |= F; 1472 } 1473 return Features; 1474 } 1475 1476 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, 1477 SanitizerMask Mask) { 1478 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(), 1479 E = Args.rend(); 1480 I != E; ++I) { 1481 const auto *Arg = *I; 1482 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { 1483 SanitizerMask AddKinds = 1484 expandSanitizerGroups(parseArgValues(D, Arg, false)); 1485 if (AddKinds & Mask) 1486 return describeSanitizeArg(Arg, Mask); 1487 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { 1488 SanitizerMask RemoveKinds = 1489 expandSanitizerGroups(parseArgValues(D, Arg, false)); 1490 Mask &= ~RemoveKinds; 1491 } 1492 } 1493 llvm_unreachable("arg list didn't provide expected value"); 1494 } 1495 1496 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) { 1497 assert(A->getOption().matches(options::OPT_fsanitize_EQ) && 1498 "Invalid argument in describeSanitizerArg!"); 1499 1500 std::string Sanitizers; 1501 for (int i = 0, n = A->getNumValues(); i != n; ++i) { 1502 if (expandSanitizerGroups( 1503 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) & 1504 Mask) { 1505 if (!Sanitizers.empty()) 1506 Sanitizers += ","; 1507 Sanitizers += A->getValue(i); 1508 } 1509 } 1510 1511 assert(!Sanitizers.empty() && "arg didn't provide expected value"); 1512 return "-fsanitize=" + Sanitizers; 1513 } 1514