Home | History | Annotate | Download | only in Driver
      1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools  ---------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include "clang/Driver/SanitizerArgs.h"
     10 #include "Tools.h"
     11 #include "clang/Basic/Sanitizers.h"
     12 #include "clang/Driver/Driver.h"
     13 #include "clang/Driver/DriverDiagnostic.h"
     14 #include "clang/Driver/Options.h"
     15 #include "clang/Driver/ToolChain.h"
     16 #include "llvm/ADT/StringExtras.h"
     17 #include "llvm/ADT/StringSwitch.h"
     18 #include "llvm/Support/FileSystem.h"
     19 #include "llvm/Support/Path.h"
     20 #include "llvm/Support/SpecialCaseList.h"
     21 #include <memory>
     22 
     23 using namespace clang;
     24 using namespace clang::SanitizerKind;
     25 using namespace clang::driver;
     26 using namespace llvm::opt;
     27 
     28 enum : SanitizerMask {
     29   NeedsUbsanRt = Undefined | Integer | CFI,
     30   NeedsUbsanCxxRt = Vptr | CFI,
     31   NotAllowedWithTrap = Vptr,
     32   RequiresPIE = DataFlow,
     33   NeedsUnwindTables = Address | Thread | Memory | DataFlow,
     34   SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
     35   RecoverableByDefault = Undefined | Integer,
     36   Unrecoverable = Unreachable | Return,
     37   LegacyFsanitizeRecoverMask = Undefined | Integer,
     38   NeedsLTO = CFI,
     39   TrappingSupported =
     40       (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
     41   TrappingDefault = CFI,
     42 };
     43 
     44 enum CoverageFeature {
     45   CoverageFunc = 1 << 0,
     46   CoverageBB = 1 << 1,
     47   CoverageEdge = 1 << 2,
     48   CoverageIndirCall = 1 << 3,
     49   CoverageTraceBB = 1 << 4,
     50   CoverageTraceCmp = 1 << 5,
     51   Coverage8bitCounters = 1 << 6,
     52 };
     53 
     54 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
     55 /// invalid components. Returns a SanitizerMask.
     56 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
     57                                     bool DiagnoseErrors);
     58 
     59 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
     60 /// components. Returns OR of members of \c CoverageFeature enumeration.
     61 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
     62 
     63 /// Produce an argument string from ArgList \p Args, which shows how it
     64 /// provides some sanitizer kind from \p Mask. For example, the argument list
     65 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
     66 /// would produce "-fsanitize=vptr".
     67 static std::string lastArgumentForMask(const Driver &D,
     68                                        const llvm::opt::ArgList &Args,
     69                                        SanitizerMask Mask);
     70 
     71 /// Produce an argument string from argument \p A, which shows how it provides
     72 /// a value in \p Mask. For instance, the argument
     73 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
     74 /// "-fsanitize=alignment".
     75 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
     76                                        SanitizerMask Mask);
     77 
     78 /// Produce a string containing comma-separated names of sanitizers in \p
     79 /// Sanitizers set.
     80 static std::string toString(const clang::SanitizerSet &Sanitizers);
     81 
     82 static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
     83                                 std::string &BLPath) {
     84   const char *BlacklistFile = nullptr;
     85   if (Kinds & Address)
     86     BlacklistFile = "asan_blacklist.txt";
     87   else if (Kinds & Memory)
     88     BlacklistFile = "msan_blacklist.txt";
     89   else if (Kinds & Thread)
     90     BlacklistFile = "tsan_blacklist.txt";
     91   else if (Kinds & DataFlow)
     92     BlacklistFile = "dfsan_abilist.txt";
     93   else if (Kinds & CFI)
     94     BlacklistFile = "cfi_blacklist.txt";
     95 
     96   if (BlacklistFile) {
     97     clang::SmallString<64> Path(D.ResourceDir);
     98     llvm::sys::path::append(Path, BlacklistFile);
     99     BLPath = Path.str();
    100     return true;
    101   }
    102   return false;
    103 }
    104 
    105 /// Sets group bits for every group that has at least one representative already
    106 /// enabled in \p Kinds.
    107 static SanitizerMask setGroupBits(SanitizerMask Kinds) {
    108 #define SANITIZER(NAME, ID)
    109 #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
    110   if (Kinds & SanitizerKind::ID)                                               \
    111     Kinds |= SanitizerKind::ID##Group;
    112 #include "clang/Basic/Sanitizers.def"
    113   return Kinds;
    114 }
    115 
    116 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
    117                                            const llvm::opt::ArgList &Args) {
    118   SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
    119                                 // sanitizers disabled by the current sanitizer
    120                                 // argument or any argument after it.
    121   SanitizerMask TrappingKinds = 0;
    122   SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
    123 
    124   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
    125        I != E; ++I) {
    126     const auto *Arg = *I;
    127     if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
    128       Arg->claim();
    129       SanitizerMask Add = parseArgValues(D, Arg, true);
    130       Add &= ~TrapRemove;
    131       if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
    132         SanitizerSet S;
    133         S.Mask = InvalidValues;
    134         D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
    135                                                           << toString(S);
    136       }
    137       TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
    138     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
    139       Arg->claim();
    140       TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
    141     } else if (Arg->getOption().matches(
    142                    options::OPT_fsanitize_undefined_trap_on_error)) {
    143       Arg->claim();
    144       TrappingKinds |=
    145           expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
    146     } else if (Arg->getOption().matches(
    147                    options::OPT_fno_sanitize_undefined_trap_on_error)) {
    148       Arg->claim();
    149       TrapRemove |= expandSanitizerGroups(UndefinedGroup);
    150     }
    151   }
    152 
    153   // Apply default trapping behavior.
    154   TrappingKinds |= TrappingDefault & ~TrapRemove;
    155 
    156   return TrappingKinds;
    157 }
    158 
    159 bool SanitizerArgs::needsUbsanRt() const {
    160   return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) &&
    161          !Sanitizers.has(Address) &&
    162          !Sanitizers.has(Memory) &&
    163          !Sanitizers.has(Thread) &&
    164          !CfiCrossDso;
    165 }
    166 
    167 bool SanitizerArgs::needsCfiRt() const {
    168   return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
    169 }
    170 
    171 bool SanitizerArgs::needsCfiDiagRt() const {
    172   return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
    173 }
    174 
    175 bool SanitizerArgs::requiresPIE() const {
    176   return NeedPIE || (Sanitizers.Mask & RequiresPIE);
    177 }
    178 
    179 bool SanitizerArgs::needsUnwindTables() const {
    180   return Sanitizers.Mask & NeedsUnwindTables;
    181 }
    182 
    183 void SanitizerArgs::clear() {
    184   Sanitizers.clear();
    185   RecoverableSanitizers.clear();
    186   TrapSanitizers.clear();
    187   BlacklistFiles.clear();
    188   ExtraDeps.clear();
    189   CoverageFeatures = 0;
    190   MsanTrackOrigins = 0;
    191   MsanUseAfterDtor = false;
    192   NeedPIE = false;
    193   AsanFieldPadding = 0;
    194   AsanSharedRuntime = false;
    195   LinkCXXRuntimes = false;
    196   CfiCrossDso = false;
    197 }
    198 
    199 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
    200                              const llvm::opt::ArgList &Args) {
    201   clear();
    202   SanitizerMask AllRemove = 0;  // During the loop below, the accumulated set of
    203                                 // sanitizers disabled by the current sanitizer
    204                                 // argument or any argument after it.
    205   SanitizerMask AllAddedKinds = 0;  // Mask of all sanitizers ever enabled by
    206                                     // -fsanitize= flags (directly or via group
    207                                     // expansion), some of which may be disabled
    208                                     // later. Used to carefully prune
    209                                     // unused-argument diagnostics.
    210   SanitizerMask DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
    211                                      // Used to deduplicate diagnostics.
    212   SanitizerMask Kinds = 0;
    213   const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
    214   ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
    215 
    216   const Driver &D = TC.getDriver();
    217   SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
    218   SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
    219 
    220   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
    221        I != E; ++I) {
    222     const auto *Arg = *I;
    223     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
    224       Arg->claim();
    225       SanitizerMask Add = parseArgValues(D, Arg, true);
    226       AllAddedKinds |= expandSanitizerGroups(Add);
    227 
    228       // Avoid diagnosing any sanitizer which is disabled later.
    229       Add &= ~AllRemove;
    230       // At this point we have not expanded groups, so any unsupported
    231       // sanitizers in Add are those which have been explicitly enabled.
    232       // Diagnose them.
    233       if (SanitizerMask KindsToDiagnose =
    234               Add & InvalidTrappingKinds & ~DiagnosedKinds) {
    235         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
    236         D.Diag(diag::err_drv_argument_not_allowed_with)
    237             << Desc << "-fsanitize-trap=undefined";
    238         DiagnosedKinds |= KindsToDiagnose;
    239       }
    240       Add &= ~InvalidTrappingKinds;
    241       if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
    242         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
    243         D.Diag(diag::err_drv_unsupported_opt_for_target)
    244             << Desc << TC.getTriple().str();
    245         DiagnosedKinds |= KindsToDiagnose;
    246       }
    247       Add &= Supported;
    248 
    249       // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
    250       // so we don't error out if -fno-rtti and -fsanitize=undefined were
    251       // passed.
    252       if (Add & Vptr &&
    253           (RTTIMode == ToolChain::RM_DisabledImplicitly ||
    254            RTTIMode == ToolChain::RM_DisabledExplicitly)) {
    255         if (RTTIMode == ToolChain::RM_DisabledImplicitly)
    256           // Warn about not having rtti enabled if the vptr sanitizer is
    257           // explicitly enabled
    258           D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
    259         else {
    260           const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
    261           assert(NoRTTIArg &&
    262                  "RTTI disabled explicitly but we have no argument!");
    263           D.Diag(diag::err_drv_argument_not_allowed_with)
    264               << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
    265         }
    266 
    267         // Take out the Vptr sanitizer from the enabled sanitizers
    268         AllRemove |= Vptr;
    269       }
    270 
    271       Add = expandSanitizerGroups(Add);
    272       // Group expansion may have enabled a sanitizer which is disabled later.
    273       Add &= ~AllRemove;
    274       // Silently discard any unsupported sanitizers implicitly enabled through
    275       // group expansion.
    276       Add &= ~InvalidTrappingKinds;
    277       Add &= Supported;
    278 
    279       Kinds |= Add;
    280     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
    281       Arg->claim();
    282       SanitizerMask Remove = parseArgValues(D, Arg, true);
    283       AllRemove |= expandSanitizerGroups(Remove);
    284     }
    285   }
    286 
    287   // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
    288   // is disabled.
    289   if ((Kinds & Vptr) &&
    290       (RTTIMode == ToolChain::RM_DisabledImplicitly ||
    291        RTTIMode == ToolChain::RM_DisabledExplicitly)) {
    292     Kinds &= ~Vptr;
    293   }
    294 
    295   // Check that LTO is enabled if we need it.
    296   if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {
    297     D.Diag(diag::err_drv_argument_only_allowed_with)
    298         << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
    299   }
    300 
    301   // Report error if there are non-trapping sanitizers that require
    302   // c++abi-specific  parts of UBSan runtime, and they are not provided by the
    303   // toolchain. We don't have a good way to check the latter, so we just
    304   // check if the toolchan supports vptr.
    305   if (~Supported & Vptr) {
    306     SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
    307     // The runtime library supports the Microsoft C++ ABI, but only well enough
    308     // for CFI. FIXME: Remove this once we support vptr on Windows.
    309     if (TC.getTriple().isOSWindows())
    310       KindsToDiagnose &= ~CFI;
    311     if (KindsToDiagnose) {
    312       SanitizerSet S;
    313       S.Mask = KindsToDiagnose;
    314       D.Diag(diag::err_drv_unsupported_opt_for_target)
    315           << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
    316       Kinds &= ~KindsToDiagnose;
    317     }
    318   }
    319 
    320   // Warn about incompatible groups of sanitizers.
    321   std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
    322       std::make_pair(Address, Thread), std::make_pair(Address, Memory),
    323       std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
    324       std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
    325       std::make_pair(KernelAddress, Leak),
    326       std::make_pair(KernelAddress, Thread),
    327       std::make_pair(KernelAddress, Memory)};
    328   for (auto G : IncompatibleGroups) {
    329     SanitizerMask Group = G.first;
    330     if (Kinds & Group) {
    331       if (SanitizerMask Incompatible = Kinds & G.second) {
    332         D.Diag(clang::diag::err_drv_argument_not_allowed_with)
    333             << lastArgumentForMask(D, Args, Group)
    334             << lastArgumentForMask(D, Args, Incompatible);
    335         Kinds &= ~Incompatible;
    336       }
    337     }
    338   }
    339   // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
    340   // -fsanitize=address. Perhaps it should print an error, or perhaps
    341   // -f(-no)sanitize=leak should change whether leak detection is enabled by
    342   // default in ASan?
    343 
    344   // Parse -f(no-)?sanitize-recover flags.
    345   SanitizerMask RecoverableKinds = RecoverableByDefault;
    346   SanitizerMask DiagnosedUnrecoverableKinds = 0;
    347   for (const auto *Arg : Args) {
    348     const char *DeprecatedReplacement = nullptr;
    349     if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
    350       DeprecatedReplacement = "-fsanitize-recover=undefined,integer";
    351       RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
    352       Arg->claim();
    353     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
    354       DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
    355       RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
    356       Arg->claim();
    357     } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
    358       SanitizerMask Add = parseArgValues(D, Arg, true);
    359       // Report error if user explicitly tries to recover from unrecoverable
    360       // sanitizer.
    361       if (SanitizerMask KindsToDiagnose =
    362               Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
    363         SanitizerSet SetToDiagnose;
    364         SetToDiagnose.Mask |= KindsToDiagnose;
    365         D.Diag(diag::err_drv_unsupported_option_argument)
    366             << Arg->getOption().getName() << toString(SetToDiagnose);
    367         DiagnosedUnrecoverableKinds |= KindsToDiagnose;
    368       }
    369       RecoverableKinds |= expandSanitizerGroups(Add);
    370       Arg->claim();
    371     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
    372       RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
    373       Arg->claim();
    374     }
    375     if (DeprecatedReplacement) {
    376       D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
    377                                             << DeprecatedReplacement;
    378     }
    379   }
    380   RecoverableKinds &= Kinds;
    381   RecoverableKinds &= ~Unrecoverable;
    382 
    383   TrappingKinds &= Kinds;
    384 
    385   // Setup blacklist files.
    386   // Add default blacklist from resource directory.
    387   {
    388     std::string BLPath;
    389     if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
    390       BlacklistFiles.push_back(BLPath);
    391   }
    392   // Parse -f(no-)sanitize-blacklist options.
    393   for (const auto *Arg : Args) {
    394     if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
    395       Arg->claim();
    396       std::string BLPath = Arg->getValue();
    397       if (llvm::sys::fs::exists(BLPath)) {
    398         BlacklistFiles.push_back(BLPath);
    399         ExtraDeps.push_back(BLPath);
    400       } else
    401         D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
    402 
    403     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
    404       Arg->claim();
    405       BlacklistFiles.clear();
    406       ExtraDeps.clear();
    407     }
    408   }
    409   // Validate blacklists format.
    410   {
    411     std::string BLError;
    412     std::unique_ptr<llvm::SpecialCaseList> SCL(
    413         llvm::SpecialCaseList::create(BlacklistFiles, BLError));
    414     if (!SCL.get())
    415       D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
    416   }
    417 
    418   // Parse -f[no-]sanitize-memory-track-origins[=level] options.
    419   if (AllAddedKinds & Memory) {
    420     if (Arg *A =
    421             Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
    422                             options::OPT_fsanitize_memory_track_origins,
    423                             options::OPT_fno_sanitize_memory_track_origins)) {
    424       if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
    425         MsanTrackOrigins = 2;
    426       } else if (A->getOption().matches(
    427                      options::OPT_fno_sanitize_memory_track_origins)) {
    428         MsanTrackOrigins = 0;
    429       } else {
    430         StringRef S = A->getValue();
    431         if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
    432             MsanTrackOrigins > 2) {
    433           D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
    434         }
    435       }
    436     }
    437     MsanUseAfterDtor =
    438         Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
    439     NeedPIE |= !(TC.getTriple().isOSLinux() &&
    440                  TC.getTriple().getArch() == llvm::Triple::x86_64);
    441   }
    442 
    443   if (AllAddedKinds & CFI) {
    444     CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
    445                                options::OPT_fno_sanitize_cfi_cross_dso, false);
    446     // Without PIE, external function address may resolve to a PLT record, which
    447     // can not be verified by the target module.
    448     NeedPIE |= CfiCrossDso;
    449   }
    450 
    451   // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
    452   // enabled sanitizers.
    453   if (AllAddedKinds & SupportsCoverage) {
    454     for (const auto *Arg : Args) {
    455       if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
    456         Arg->claim();
    457         int LegacySanitizeCoverage;
    458         if (Arg->getNumValues() == 1 &&
    459             !StringRef(Arg->getValue(0))
    460                  .getAsInteger(0, LegacySanitizeCoverage) &&
    461             LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
    462           // TODO: Add deprecation notice for this form.
    463           switch (LegacySanitizeCoverage) {
    464           case 0:
    465             CoverageFeatures = 0;
    466             break;
    467           case 1:
    468             CoverageFeatures = CoverageFunc;
    469             break;
    470           case 2:
    471             CoverageFeatures = CoverageBB;
    472             break;
    473           case 3:
    474             CoverageFeatures = CoverageEdge;
    475             break;
    476           case 4:
    477             CoverageFeatures = CoverageEdge | CoverageIndirCall;
    478             break;
    479           }
    480           continue;
    481         }
    482         CoverageFeatures |= parseCoverageFeatures(D, Arg);
    483       } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
    484         Arg->claim();
    485         CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
    486       }
    487     }
    488   }
    489   // Choose at most one coverage type: function, bb, or edge.
    490   if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
    491     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
    492         << "-fsanitize-coverage=func"
    493         << "-fsanitize-coverage=bb";
    494   if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
    495     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
    496         << "-fsanitize-coverage=func"
    497         << "-fsanitize-coverage=edge";
    498   if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
    499     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
    500         << "-fsanitize-coverage=bb"
    501         << "-fsanitize-coverage=edge";
    502   // Basic block tracing and 8-bit counters require some type of coverage
    503   // enabled.
    504   int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
    505   if ((CoverageFeatures & CoverageTraceBB) &&
    506       !(CoverageFeatures & CoverageTypes))
    507     D.Diag(clang::diag::err_drv_argument_only_allowed_with)
    508         << "-fsanitize-coverage=trace-bb"
    509         << "-fsanitize-coverage=(func|bb|edge)";
    510   if ((CoverageFeatures & Coverage8bitCounters) &&
    511       !(CoverageFeatures & CoverageTypes))
    512     D.Diag(clang::diag::err_drv_argument_only_allowed_with)
    513         << "-fsanitize-coverage=8bit-counters"
    514         << "-fsanitize-coverage=(func|bb|edge)";
    515 
    516   if (AllAddedKinds & Address) {
    517     AsanSharedRuntime =
    518         Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
    519     NeedPIE |= TC.getTriple().isAndroid();
    520     if (Arg *A =
    521             Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
    522         StringRef S = A->getValue();
    523         // Legal values are 0 and 1, 2, but in future we may add more levels.
    524         if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
    525             AsanFieldPadding > 2) {
    526           D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
    527         }
    528     }
    529 
    530     if (Arg *WindowsDebugRTArg =
    531             Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
    532                             options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
    533                             options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
    534       switch (WindowsDebugRTArg->getOption().getID()) {
    535       case options::OPT__SLASH_MTd:
    536       case options::OPT__SLASH_MDd:
    537       case options::OPT__SLASH_LDd:
    538         D.Diag(clang::diag::err_drv_argument_not_allowed_with)
    539             << WindowsDebugRTArg->getAsString(Args)
    540             << lastArgumentForMask(D, Args, Address);
    541         D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
    542       }
    543     }
    544   }
    545 
    546   // Parse -link-cxx-sanitizer flag.
    547   LinkCXXRuntimes =
    548       Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
    549 
    550   // Finally, initialize the set of available and recoverable sanitizers.
    551   Sanitizers.Mask |= Kinds;
    552   RecoverableSanitizers.Mask |= RecoverableKinds;
    553   TrapSanitizers.Mask |= TrappingKinds;
    554 }
    555 
    556 static std::string toString(const clang::SanitizerSet &Sanitizers) {
    557   std::string Res;
    558 #define SANITIZER(NAME, ID)                                                    \
    559   if (Sanitizers.has(ID)) {                                                    \
    560     if (!Res.empty())                                                          \
    561       Res += ",";                                                              \
    562     Res += NAME;                                                               \
    563   }
    564 #include "clang/Basic/Sanitizers.def"
    565   return Res;
    566 }
    567 
    568 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
    569                             llvm::opt::ArgStringList &CmdArgs,
    570                             types::ID InputType) const {
    571   if (Sanitizers.empty())
    572     return;
    573   CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
    574 
    575   if (!RecoverableSanitizers.empty())
    576     CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
    577                                          toString(RecoverableSanitizers)));
    578 
    579   if (!TrapSanitizers.empty())
    580     CmdArgs.push_back(
    581         Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
    582 
    583   for (const auto &BLPath : BlacklistFiles) {
    584     SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
    585     BlacklistOpt += BLPath;
    586     CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
    587   }
    588   for (const auto &Dep : ExtraDeps) {
    589     SmallString<64> ExtraDepOpt("-fdepfile-entry=");
    590     ExtraDepOpt += Dep;
    591     CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
    592   }
    593 
    594   if (MsanTrackOrigins)
    595     CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
    596                                          llvm::utostr(MsanTrackOrigins)));
    597 
    598   if (MsanUseAfterDtor)
    599     CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
    600 
    601   if (CfiCrossDso)
    602     CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso"));
    603 
    604   if (AsanFieldPadding)
    605     CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
    606                                          llvm::utostr(AsanFieldPadding)));
    607   // Translate available CoverageFeatures to corresponding clang-cc1 flags.
    608   std::pair<int, const char *> CoverageFlags[] = {
    609     std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
    610     std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
    611     std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
    612     std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
    613     std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
    614     std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
    615     std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters")};
    616   for (auto F : CoverageFlags) {
    617     if (CoverageFeatures & F.first)
    618       CmdArgs.push_back(Args.MakeArgString(F.second));
    619   }
    620 
    621 
    622   // MSan: Workaround for PR16386.
    623   // ASan: This is mainly to help LSan with cases such as
    624   // https://code.google.com/p/address-sanitizer/issues/detail?id=373
    625   // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
    626   // affect compilation.
    627   if (Sanitizers.has(Memory) || Sanitizers.has(Address))
    628     CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
    629 
    630   if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
    631     // Instruct the code generator to embed linker directives in the object file
    632     // that cause the required runtime libraries to be linked.
    633     CmdArgs.push_back(Args.MakeArgString(
    634         "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone")));
    635     if (types::isCXX(InputType))
    636       CmdArgs.push_back(Args.MakeArgString(
    637           "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx")));
    638   }
    639 }
    640 
    641 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
    642                              bool DiagnoseErrors) {
    643   assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
    644           A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
    645           A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
    646           A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
    647           A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
    648           A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
    649          "Invalid argument in parseArgValues!");
    650   SanitizerMask Kinds = 0;
    651   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    652     const char *Value = A->getValue(i);
    653     SanitizerMask Kind;
    654     // Special case: don't accept -fsanitize=all.
    655     if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
    656         0 == strcmp("all", Value))
    657       Kind = 0;
    658     else
    659       Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
    660 
    661     if (Kind)
    662       Kinds |= Kind;
    663     else if (DiagnoseErrors)
    664       D.Diag(clang::diag::err_drv_unsupported_option_argument)
    665           << A->getOption().getName() << Value;
    666   }
    667   return Kinds;
    668 }
    669 
    670 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
    671   assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
    672          A->getOption().matches(options::OPT_fno_sanitize_coverage));
    673   int Features = 0;
    674   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    675     const char *Value = A->getValue(i);
    676     int F = llvm::StringSwitch<int>(Value)
    677         .Case("func", CoverageFunc)
    678         .Case("bb", CoverageBB)
    679         .Case("edge", CoverageEdge)
    680         .Case("indirect-calls", CoverageIndirCall)
    681         .Case("trace-bb", CoverageTraceBB)
    682         .Case("trace-cmp", CoverageTraceCmp)
    683         .Case("8bit-counters", Coverage8bitCounters)
    684         .Default(0);
    685     if (F == 0)
    686       D.Diag(clang::diag::err_drv_unsupported_option_argument)
    687           << A->getOption().getName() << Value;
    688     Features |= F;
    689   }
    690   return Features;
    691 }
    692 
    693 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
    694                                 SanitizerMask Mask) {
    695   for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
    696                                                   E = Args.rend();
    697        I != E; ++I) {
    698     const auto *Arg = *I;
    699     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
    700       SanitizerMask AddKinds =
    701           expandSanitizerGroups(parseArgValues(D, Arg, false));
    702       if (AddKinds & Mask)
    703         return describeSanitizeArg(Arg, Mask);
    704     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
    705       SanitizerMask RemoveKinds =
    706           expandSanitizerGroups(parseArgValues(D, Arg, false));
    707       Mask &= ~RemoveKinds;
    708     }
    709   }
    710   llvm_unreachable("arg list didn't provide expected value");
    711 }
    712 
    713 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
    714   assert(A->getOption().matches(options::OPT_fsanitize_EQ)
    715          && "Invalid argument in describeSanitizerArg!");
    716 
    717   std::string Sanitizers;
    718   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    719     if (expandSanitizerGroups(
    720             parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
    721         Mask) {
    722       if (!Sanitizers.empty())
    723         Sanitizers += ",";
    724       Sanitizers += A->getValue(i);
    725     }
    726   }
    727 
    728   assert(!Sanitizers.empty() && "arg didn't provide expected value");
    729   return "-fsanitize=" + Sanitizers;
    730 }
    731