brintos

brintos / llvm-project-archived public Read only

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