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